API referenceAudiences

Broadcast an email to an email list

Broadcasts one email to every active member of the list and returns 202 with a broadcast object: { "object": "broadcast", "id": "bcast_...", "audienceId", "status": "queued" }.

Endpoint
POST https://api.dairo.app/v1/audiences/{audienceId}/send

Broadcasts one email to every active member of the list and returns 202 with a broadcast object: { "object": "broadcast", "id": "bcast_...", "audienceId", "status": "queued" }. Recipients come from list membership; inboxId (the verified sending address) is required, along with a subject and exactly one body via text, html, react, or a stored template — a bad template reference fails synchronously with a 400. replyTo, headers, and tags apply to every member's message. Per-recipient fields — to, cc, bcc, contactId, channel, sendAt, replyToMessageId, inReplyTo, references, and dryRun — are refused with a 400 naming the field, since a broadcast always sends immediately to every active member; the Telegram-only buttons and telegram payloads are a 400 too. Members are reached by email, so inboxId must be an email inbox (a Telegram or Slack inbox is a 400). Delivery is asynchronous: each accepted recipient becomes an individual message emitting message.sent, then message.delivered, message.bounced, or message.complained, and a contact member with no current email handle is skipped. Each recipient is de-duplicated on a key derived from your idempotencyKey and their address (derived deterministically from the list and body when you omit one), so a retried broadcast never double-sends; recipients that previously complained are suppressed unless ignoreComplaints is true. Requires the messages:send scope.

Scope: messages:send. Send the API key as a bearer token; Scopes lists what each one reaches.

Request

cURL
curl -X POST "https://api.dairo.app/v1/audiences/3fa85f64-5717-4562-b3fc-2c963f66afa6/send" \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "inboxId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "text": "Thanks for signing up."
  }'

Path parameters

NameTypeRequiredDescription
audienceIdstring (uuid)yesThe audience's ID.

Body

Required, application/json: BroadcastRequest.

The body of an audience broadcast. Every active member of the audience receives its own email from inboxId, which must be an email inbox. Per-recipient fields (to, cc, bcc, contactId, channel, sendAt, inReplyTo, references, replyToMessageId, dryRun) and the Telegram-only buttons and telegram are rejected with 400: members are the recipients, one message each, so none of them can apply.

FieldTypeRequiredDescription
inboxIdstringyes
subjectstringno(default "")
textstringno
htmlstringno
reactReactRenderInputno
templateMessageTemplateRefno
attachmentsarray of SendMessageAttachmentnoOutbound send attachments. 'attachment' and safe 'auto' sends are inline; current inline API limit is 10 files, 8 MiB per file, 8 MiB total decoded bytes. 'link' is explicit and must be backed by a pre-created Dairo share link placed deliberately in text/html by the caller. (max items 10)
idempotencyKeystringnoPer-broadcast idempotency base: each member's message is keyed {idempotencyKey}:{address}, so re-posting the same broadcast never re-sends to a member already accepted. Omitted, the base is derived from the org, the audience and the body. (max length 128)
replyTostring (email)noOptional single Reply-To address, set verbatim as the MIME Reply-To header. E-mail only: a send with replyTo stays on e-mail even when every recipient is a Dairo inbox; channel a2a and Telegram or Slack inboxes answer 400.
headersmap of stringnoOptional custom MIME headers ({name: value}). Spoofable/provenance headers are dropped server-side; malformed names or CR/LF are rejected. E-mail only: a send with headers stays on e-mail even when every recipient is a Dairo inbox; channel a2a and Telegram or Slack inboxes answer 400.
tagsmap of stringnoOptional SES message tags ({name: value}), validated against SES tag constraints. E-mail only: a send with tags stays on e-mail even when every recipient is a Dairo inbox; channel a2a and Telegram or Slack inboxes answer 400.
ignoreComplaintsbooleannoOverride complaint and hard-bounce suppression for every member that previously complained or bounced. (default false)

Response

202 Accepted. Body: application/json, Broadcast.

FieldTypeRequiredDescription
object"broadcast"yes
idstringyesThe server-minted broadcast id (bcast_...).
audienceIdstring (uuid)yes
status"queued"yes
202
{
  "object": "broadcast",
  "id": "string",
  "audienceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "queued"
}

Errors

Every error has the same body, {"error": {"type", "code", "message", "param"}}; branch on code. Errors lists every code.

StatusMeaning
400The request is malformed or a value is invalid (invalid_request, invalid_domain, idempotency_key_mismatch).
401The API key is missing or invalid.
403The key lacks the scope this endpoint needs (scope_missing) or may not do this (not_permitted).
404No such resource in this account (resource_not_found).
422The request is well-formed but a field failed validation (validation_failed).
429Rate limit, plan limit, budget or spend cap reached (rate_limited, plan_limit_reached, budget_exceeded, spend_cap_reached).
500An unexpected error; retry with backoff, then contact support (internal_error).

On this page