Menu

Send a transactional message

POST/v1/transactional/messages

Requires an API key with the transactional:send scope. About keys and scopes

Takes an Idempotency-Key header: a retry with the same key returns the first result instead of acting twice. Derive the key from what you are sending, and reuse it on every retry. About idempotency

Sends a one-off message to one recipient — a receipt, a password reset, a confirmation — bypassing campaigns. It ignores marketing preferences (it is the critical tier) but respects suppression. Agent keys are refused with 403.

Channels. Give email, push, or both. With both, deliver: all (the default) sends each one the contact can receive, and deliver: first sends push when the contact has a reachable device and email otherwise. A channel the contact cannot receive is passed over; only when none is left does the send fail, with that channel's reason. The response lists one message per channel sent.

Email. Inline (subject, from, html, optional text, previewText, replyTo), or a stored template: templateId (its id or alias) with data, readable as {{ data.<key> }}. The template's published version is rendered when the request is accepted and supplies the envelope; each envelope field given overrides it. The result needs a subject and a from (409 TEMPLATE_ENVELOPE_INCOMPLETE), and the from domain must be verified. A template never published is 409 TEMPLATE_NOT_PUBLISHED. Email is tracked only when tracking asks, and never for a contact in the EEA or the UK; threading continues a conversation.

Recipient. to names a contactId, an externalId or an email. With externalId or email, firstName, lastName and attributes create the contact or update it, as POST /v1/contacts/identify does; consent is never changed. A bare email that matches no contact creates one for transactional mail only.

Retries. An Idempotency-Key header is required. A retry with the same key and request returns the first result, with Idempotency-Replay: true, and sends nothing again; the same key with a different request is 409 IDEMPOTENCY_KEY_REUSED. Set correlationId to your own reference: it is echoed on each message's webhooks and its read. sendAt times the send, email and push alike.

Header parameters

Idempotency-Keystringrequired

8–255 characters

Request body

toobjectrequired

Who receives it.

One of 3 shapes
By contact id
1 child attribute
contactIdstringrequired

An existing contact.

uuid

By external id
5 child attributes
externalIdstringrequired

Your own id for the contact. Alone it must match an existing contact; with email or profile fields the contact is created or updated, as identify does.

1–255 characters

emailstringoptional

Sets or updates the contact email.

email · up to 320 characters

firstNamestring | nulloptional

1–100 characters

lastNamestring | nulloptional

1–100 characters

attributesobjectoptional

Custom attributes, merged key by key; null removes one. At most 50 keys and 16 KB.

By email
4 child attributes
emailstringrequired

The recipient's address. With profile fields the contact is created or updated, as identify does; alone, an email send creates a transactional-only contact when none has it, and a push-only send needs an existing contact.

email · up to 320 characters

firstNamestring | nulloptional

1–100 characters

lastNamestring | nulloptional

1–100 characters

attributesobjectoptional

Custom attributes, merged key by key; null removes one. At most 50 keys and 16 KB.

sensitivebooleanoptional

Set when the message carries a secret (a reset link, a one-time code): its content is never kept, whatever retainContent and the workspace's retention say.

correlationIdstringoptional

Your own reference for this send, echoed on its webhooks and its read.

1–255 characters

retainContentbooleanoptional

false discards what was sent as soon as it is sent.

emailobjectoptional

Inline content (subject, from, html), or a stored templateId.

One of 2 shapes
Stored template
6 child attributes
templateIdstringrequired

The template's id, or its alias (such as password-reset).

dataobjectoptional

Values for the template's {{ data.* }} merge tags.

subjectstringoptional

The subject line. Merge tags are allowed.

1–998 characters

previewTextstringoptional

Shown by inboxes after the subject. Merge tags are allowed; keep it near 100 characters.

1–255 characters

fromstringoptional

The sender address, on a verified sending domain.

1–320 characters

replyTostringoptional

Where replies go.

email

Inline content
6 child attributes
subjectstringrequired

The subject line. Merge tags are allowed.

1–998 characters

previewTextstringoptional

Shown by inboxes after the subject. Merge tags are allowed; keep it near 100 characters.

1–255 characters

htmlstringrequired

The HTML body. Rendered from the design when one is set.

1–512000 characters

textstringoptional

The plain-text alternative.

1–512000 characters

fromstringrequired

The sender address, on a verified sending domain.

1–320 characters

replyTostringoptional

Where replies go.

email

pushobjectoptional

A push notification to the contact's devices. Give push, email, or both.

2 child attributes
pushProjectIdstringrequired

Reaches the contact's devices on every app of the project.

uuid

contentobjectrequired
13 child attributes
titlestringrequired

The notification title (up to 100 characters).

1–100 characters

bodystringrequired

The notification text (up to 500 characters).

1–500 characters

actionUrlstringoptional

The HTTPS page opened when the notification is tapped.

uri · up to 2048 characters

imageUrlstringoptional

A large picture: web and Android show it; iOS needs the app's service extension.

uri · up to 2048 characters

iconUrlstringoptional

Web only; iOS and Android show the app's own notification icon.

uri · up to 2048 characters

dataobjectoptional

Up to 10 string key-value pairs passed to the app untouched, for deep links and in-app routing.

buttonsobject[]optional

Up to 2 action buttons.

at least 1 item · at most 2 items

2 child attributes
titlestringrequired

The button label.

1–30 characters

urlstringrequired

The HTTPS page the button opens.

uri · up to 2048 characters

collapseKeystringoptional

A newer notification with the same key replaces the older one on the device.

soundstringoptional

The name of a sound the app ships; the device's default if unset.

1–64 characters

badgeintegeroptional

The number shown on the iOS app icon.

min 0 · max 99999

ttlSecondsintegeroptional

Seconds a provider keeps trying an offline device (up to 28 days); defaults to 86400 (one day).

min 0 · max 2419200

urgencystringoptional

high wakes the device now; normal lets it wait for a good moment to save battery. Unset, a transactional push is high and any other normal.

one of high, normal

overridesobjectoptional

Fields that differ on one platform, each replacing the shared one there (a whole data map, not merged key by key). On iOS and Android actionUrl may be an app link such as myapp://orders; the shared one and the web one must be HTTPS.

3 child attributes
iosobjectoptional

Replaces shared fields on iOS.

14 child attributes
titlestringoptional

The notification title (up to 100 characters).

1–100 characters

bodystringoptional

The notification text (up to 500 characters).

1–500 characters

actionUrlstringoptional

up to 2048 characters

imageUrlstringoptional

A large picture: web and Android show it; iOS needs the app's service extension.

uri · up to 2048 characters

iconUrlstringoptional

Web only; iOS and Android show the app's own notification icon.

uri · up to 2048 characters

dataobjectoptional

Up to 10 string key-value pairs passed to the app untouched, for deep links and in-app routing.

buttonsobject[]optional

Up to 2 action buttons.

at least 1 item · at most 2 items

collapseKeystringoptional

A newer notification with the same key replaces the older one on the device.

soundstringoptional

The name of a sound the app ships; the device's default if unset.

1–64 characters

badgeintegeroptional

The number shown on the iOS app icon.

min 0 · max 99999

ttlSecondsintegeroptional

Seconds a provider keeps trying an offline device (up to 28 days); defaults to 86400 (one day).

min 0 · max 2419200

urgencystringoptional

high wakes the device now; normal lets it wait for a good moment to save battery. Unset, a transactional push is high and any other normal.

one of high, normal

interruptionLevelstringoptional

How iOS presents it: passive arrives silently, time-sensitive breaks through Focus and needs the app's Time Sensitive Notifications capability.

one of passive, active, time-sensitive

threadIdstringoptional

Notifications with the same thread are grouped together in Notification Center.

androidobjectoptional

Replaces shared fields on Android.

13 child attributes
titlestringoptional

The notification title (up to 100 characters).

1–100 characters

bodystringoptional

The notification text (up to 500 characters).

1–500 characters

actionUrlstringoptional

up to 2048 characters

imageUrlstringoptional

A large picture: web and Android show it; iOS needs the app's service extension.

uri · up to 2048 characters

iconUrlstringoptional

Web only; iOS and Android show the app's own notification icon.

uri · up to 2048 characters

dataobjectoptional

Up to 10 string key-value pairs passed to the app untouched, for deep links and in-app routing.

buttonsobject[]optional

Up to 2 action buttons.

at least 1 item · at most 2 items

collapseKeystringoptional

A newer notification with the same key replaces the older one on the device.

soundstringoptional

The name of a sound the app ships; the device's default if unset.

1–64 characters

badgeintegeroptional

The number shown on the iOS app icon.

min 0 · max 99999

ttlSecondsintegeroptional

Seconds a provider keeps trying an offline device (up to 28 days); defaults to 86400 (one day).

min 0 · max 2419200

urgencystringoptional

high wakes the device now; normal lets it wait for a good moment to save battery. Unset, a transactional push is high and any other normal.

one of high, normal

channelIdstringoptional

The Android notification channel to post in, which the app creates; it sets the sound and importance a person can tune, e.g. one for offers and one for orders.

webobjectoptional

Replaces shared fields on web.

12 child attributes
titlestringoptional

The notification title (up to 100 characters).

1–100 characters

bodystringoptional

The notification text (up to 500 characters).

1–500 characters

actionUrlstringoptional

The HTTPS page opened when the notification is tapped.

uri · up to 2048 characters

imageUrlstringoptional

A large picture: web and Android show it; iOS needs the app's service extension.

uri · up to 2048 characters

iconUrlstringoptional

Web only; iOS and Android show the app's own notification icon.

uri · up to 2048 characters

dataobjectoptional

Up to 10 string key-value pairs passed to the app untouched, for deep links and in-app routing.

buttonsobject[]optional

Up to 2 action buttons.

at least 1 item · at most 2 items

collapseKeystringoptional

A newer notification with the same key replaces the older one on the device.

soundstringoptional

The name of a sound the app ships; the device's default if unset.

1–64 characters

badgeintegeroptional

The number shown on the iOS app icon.

min 0 · max 99999

ttlSecondsintegeroptional

Seconds a provider keeps trying an offline device (up to 28 days); defaults to 86400 (one day).

min 0 · max 2419200

urgencystringoptional

high wakes the device now; normal lets it wait for a good moment to save battery. Unset, a transactional push is high and any other normal.

one of high, normal

attachmentsEmailAttachmentInput[]optional

Files the email carries (not push): up to 10, 10 MB in all.

at least 1 item · at most 10 items

3 child attributes
filenamestringrequired

Its extension sets the type it is sent as.

1–255 characters

contentstringrequired

The file, base64-encoded.

base64

contentIdstringoptional

Shows an image inside the body instead of attaching it: the HTML refers to it as <img src="cid:<contentId>">.

threadingEmailThreadingInputoptional

Places the email in an existing conversation, as the In-Reply-To and References headers.

2 child attributes
inReplyTostringrequired

The Message-ID of the email being replied to, angle brackets included.

referencesstring[]optional

The Message-IDs earlier in the conversation, oldest first (up to 20).

at least 1 item · at most 20 items

trackingTransactionalEmailTrackingInputoptional

Open and click tracking for this email; off unless asked for. Contacts whose country is in the EEA or the UK are never tracked.

2 child attributes
opensbooleanoptional

Track opens with a pixel.

default false

clicksbooleanoptional

Rewrite links to track clicks.

default false

sendAtstringoptional

When to send, up to 90 days ahead, with its UTC offset. Suppression and push reachability are checked when the request is accepted and again when it goes; deliver: first picks its channel when accepted.

date-time

deliverstringoptional

With both push and email: all sends each the contact can receive; first sends push when the contact has a reachable device, else email.

one of all, first · default "all"

Returns

Returns 202 Accepted with a TransactionalSendResult in data. Otherwise returns an error; Errors lists every code and which to retry.

messagesTransactionalMessage[]required
6 child attributes
idstringrequired

uuid

channelstringrequired

one of email, push

statusstringrequired

one of queued, sending, skipped, sent, failed, delivered, bounced, complained

correlationIdstring | nullrequired

The correlationId given when it was sent, if any.

createdAtstringrequired

date-time

sendAtstring | nullrequired

When a timed email goes out; null when it went at once.

date-time