Ir a la documentación
API

Enviar a audiencias

Envía un mensaje a todos los de una o más audiencias, como copia aparte para cada persona y personalizado a partir de cada contacto. Cada copia tiene exactamente un destinatario y ni cc ni bcc, así que nadie ve a quién más se envió, y cada copia es un correo normal con su propio id `msg_`, eventos, seguimiento y webhooks. La llamada responde `202` enseguida y el envío sigue en segundo plano, así que síguelo con `GET /broadcasts/{id}`.

POSTapi.openemail.uk/broadcasts

Ejecuta la llamada real contra tu espacio de trabajo, con tu propia clave.

POST /broadcasts

Envía un mensaje a todos los de una o más audiencias, como copia aparte para cada persona y personalizado a partir de cada contacto. Cada copia tiene exactamente un destinatario y ni cc ni bcc, así que nadie ve a quién más se envió, y cada copia es un correo normal con su propio id msg_, eventos, seguimiento y webhooks. La llamada responde 202 enseguida y el envío sigue en segundo plano, así que síguelo con GET /broadcasts/{id}.

Ejemplo

Necesita emails:send y audiences:read. audienceIds contiene de 1 a 10 ids. El cuerpo sale de html y/o text, o de una template guardada, nunca de ambos, y subject es obligatorio salvo que la plantilla lo aporte.

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"}'
Respuesta
{  "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}

La respuesta es queued, o scheduled con scheduledAt, que acepta un instante ISO 8601 o una duración como PT2H, a 365 días como máximo. counts.recipients es la estimación tomada ahora, y los demás contadores empiezan en 0. La cabecera Location nombra el envío masivo.

Se puede reintentar con seguridad con una cabecera Idempotency-Key: la misma clave responde 200 con el envío masivo que creó la primera llamada y Idempotency-Replayed: true, y la misma clave con otro cuerpo es un 422 idempotency_key_reuse. Sin clave, enviar el mismo cuerpo dos veces envía el envío masivo dos veces.

Las copias no se archivan en la carpeta Enviados, porque el envío masivo es el registro. GET /emails?broadcastId=brd_5a8c1e3f7b2d94a06c8e1f3b las lista, una por persona.

Quién lo recibe

Todo contacto de al menos una de las audiencias, contado una vez aunque esté en varias. Quedan fuera dos tipos de contacto: el que se dio de baja de todas las audiencias elegidas en las que está, y el que tiene su dirección en la lista de supresión tras un rebote o una queja, o porque alguien la añadió. Un contacto añadido a una de las audiencias después de la llamada, pero antes de que el envío le llegue, sí lo recibe.

El envío recorre las audiencias de 50 personas en 50 y entrega cada copia a la misma cadena que usa POST /emails, así que cada copia se reintenta, se sigue y se informa como cualquier otro mensaje. POST /broadcasts/preview devuelve la cifra de la que partiría esta llamada, sin enviar nada.

Todo el envío se compara con los envíos mensuales del plan antes de escribir nada. Un envío masivo que la cuota no puede cubrir se rechaza con 429 send_quota_exceeded y no deja nada atrás. Cada copia cuenta como un envío.

Campos de combinación

subject, html y text se rellenan para cada persona. Cada campo admite un valor de reserva tras una barra, que se usa cuando el contacto no tiene valor para él, así que {{firstName|there}} se convierte en "there" para un contacto guardado sin nombre. Los valores se escapan en html, se permiten espacios dentro de las llaves y cualquier otro {{…}} se deja tal como está escrito.

CampoSe rellena con
`{{firstName}}`La primera palabra del nombre del contacto.
`{{lastName}}`El resto del nombre del contacto tras la primera palabra.
`{{name}}`El nombre completo del contacto.
`{{email}}`La dirección a la que va la copia.
`{{unsubscribeUrl}}`El enlace que da de baja a esta persona de estas audiencias.

Con template en lugar de un cuerpo, los mismos cinco valores se pasan como props, pero solo los props que declara la plantilla. Una plantilla que declara firstName lo recibe, y un prop que no declara nunca se envía, así que las copias nunca fallan por un prop desconocido. Todo lo que pongas en template.props va igual a todas las copias.

Darse de baja

Cada copia lleva List-Unsubscribe y List-Unsubscribe-Post: List-Unsubscribe=One-Click. Eso es lo que permite a un cliente de correo mostrar su propio botón de baja, y lo que los grandes proveedores de buzones exigen al correo masivo.

Un cuerpo html o text que no coloca {{unsubscribeUrl}} por sí mismo recibe un pie de una línea: "You are receiving this because you are on this mailing list. Unsubscribe". Una plantilla se envía exactamente como es, así que pon {{unsubscribeUrl}} en la plantilla.

El enlace abre una página con un botón para darse de baja, así que un escáner de enlaces que lo abra no da de baja a nadie, mientras que la solicitud de un clic que hace un cliente de correo da de baja al instante. En ambos casos la persona queda marcada como dada de baja en todas las audiencias a las que fue este envío masivo, lo que aparece como unsubscribedAt en GET /audiences/{id}/contacts. Sus otras audiencias, su contacto y el correo que se le envía de uno en uno no se ven afectados.

Rechazos

EstadoCódigoCuándo
403from_address_forbiddenLa clave no puede enviar como from.
404audience_not_foundUn id de audienceIds no nombra ninguna audiencia de este espacio de trabajo.
409domain_not_sendableEl dominio de from aún no puede firmar correo, como en POST /emails.
422no_recipientsLas audiencias están vacías, o todos los que hay en ellas se dieron de baja o están suprimidos.
422invalid_parameterSin cuerpo, html o text junto a template, sin subject y sin plantilla, más de 10 audiencias u 8 etiquetas, o un scheduledAt que no está en el futuro o está a más de 365 días.
422template_not_foundLa plantilla no se resuelve. Los demás rechazos de plantilla también nombran template.*.
422capability_unsupportedLa clave está limitada a direcciones concretas. Las audiencias pertenecen a todo el espacio de trabajo.
429send_quota_exceededEl plan no puede cubrir una copia para todos este mes.

Sin adjuntos, cc, bcc, traducción ni cifrado. tags admite hasta 8, y cada copia lleva además broadcast_id, que añade el servidor.