Send a transactional messageMenu

Send a transactional message

POST/v1/transactional/messages

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

Works with integration and partner keys, not agent keys.

Send Idempotency-Key. A retry with the same key and body repeats nothing. Most writes replay the first response; a transactional send returns the message as it stands now. 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, each one the contact can receive is sent. fallbackOrder: ["email", "push"] tries them in that order instead: the first the contact can receive goes, and each later one waits as a fallback (fallbackFor), sent only when the one before it fails, is skipped or bounces (an email gets 15 minutes to bounce), else skipped with reason fallback_not_needed. A fallback is charged only when it goes; with no room left in the plan by then it is skipped with reason plan_limit_reached. A channel the contact cannot receive, or the plan has no room for, is passed over and listed in skippedChannels with its error code; only when none is left does the send fail, with that channel's error. So without fallbackOrder too, a 202 can leave a channel unsent: check skippedChannels. The response lists one message per channel stored, and one per cc or bcc copy. Each copy is its own message with its own bounces, and an address that cannot take one is listed in skippedCopies while the send goes on.

Data. data holds the values the content reads as {{ data.<key> }}, once for every channel: a stored template, inline email, and the push title and body. Inline content (email or push) whose {{ data.<key> }} tag has no value in data, and no default, is refused with 400 rather than sent blank.

Email. Inline (subject, from, html, optional text, previewText, replyTo), or a stored template named by template (its alias, such as password-reset, or its id). 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. attachments, threading and tracking sit inside email.

Push. push takes the notification fields (title, body, actionUrl, …) beside pushProjectId, which is needed only when the workspace has several push projects. Unlike email, push needs the contact's push consent (consent.push) besides a device that allows notifications.

Recipient. to names one contactId, externalId or email, and nothing else: set a contact's name or attributes with POST /v1/contacts/identify first. An email that matches no contact creates one for transactional mail only.

Retries. Send an Idempotency-Key header to make a retry safe. 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. Without a key, every request sends: a retry after a timeout can send the message twice. A replay answers from the messages as they are now, so its status can differ from the first answer, and an externalId or email recipient the first request created or updated stays so even when the send itself was refused. Set correlationId to your own reference: it is echoed on each message's webhooks and its read, and GET /v1/messages?correlationId= finds them. sendAt times the send, email and push alike.

Header parameters

Idempotency-Keystringoptional

Makes a retry safe for as long as what the request created exists: a repeat with the same key and body gets the first response again, with Idempotency-Replay: true. The same key with another request is 409 IDEMPOTENCY_KEY_REUSED. Use a new key, such as a UUID, for each new request.

8–255 characters

Kirora-Workspacestringoptional

Partner keys only: the child workspace to act in, by the external id the partner gave it. Without it, a partner key acts in its own workspace. Any other key that sends it is refused with 403, and an unknown workspace is 404.

pattern ^[A-Za-z0-9._:-]{1,128}$

Request body

toobjectrequired

Who receives it.

Any of 3 shapes
By contact id
1 child attribute
contactIdstringrequired

An existing contact.

uuid

By external id
1 child attribute
externalIdstringrequired

Your own id for an existing contact, as set with identify.

1–255 characters

By email
1 child attribute
emailstringrequired

The recipient's address. An email send to an address no contact has creates a transactional-only contact; a push-only send needs an existing contact.

email · up to 320 characters

datamap<string, any>optional

Values the content reads as {{ data.<key> }}: a stored template, inline email and the push title and body alike.

keys: pattern ^[A-Za-z0-9_-]{1,64}$

sensitivebooleanoptional

Set when the message carries a secret (a reset link, a one-time code): its content is kept only while the message is queued or sending, and removed once sending finishes, whatever the workspace's retention says.

correlationIdstringoptional

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

1–255 characters

emailobjectoptional

Inline (subject, from, html), or a stored template by template; either may carry attachments, threading, tracking, cc and bcc.

Any of 2 shapes
Stored template
10 child attributes
templatestringrequired

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

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; the part before the @ must be ASCII.

email

attachmentsEmailAttachmentInput[]optional

Files it carries: 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>">.

pattern ^[A-Za-z0-9._-]{1,100}$

threadingEmailThreadingInputoptional

Places it 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.

pattern ^<[^<>\s@]+@[^<>\s@]+>$

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; 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

ccstring[]optional

Addresses that get a copy and are shown in its Cc line. Each goes as its own message, with its own bounces and complaints, and counts as one email. Up to 14 across cc and bcc.

at least 1 item · at most 14 items

bccstring[]optional

Addresses that get a copy without being shown to anyone. Sent and counted as cc is.

at least 1 item · at most 14 items

Inline content
12 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–512,000 characters

textstringoptional

The plain-text alternative.

1–512,000 characters

fromstringrequired

The sender address, on a verified sending domain.

1–320 characters

replyTostringoptional

Where replies go; the part before the @ must be ASCII.

email

attachmentsEmailAttachmentInput[]optional

Files it carries: 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>">.

pattern ^[A-Za-z0-9._-]{1,100}$

threadingEmailThreadingInputoptional

Places it 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.

pattern ^<[^<>\s@]+@[^<>\s@]+>$

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; 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

ccstring[]optional

Addresses that get a copy and are shown in its Cc line. Each goes as its own message, with its own bounces and complaints, and counts as one email. Up to 14 across cc and bcc.

at least 1 item · at most 14 items

bccstring[]optional

Addresses that get a copy without being shown to anyone. Sent and counted as cc is.

at least 1 item · at most 14 items

mergeTagsbooleanoptional

Set to false for HTML that is already finished: {{ then goes out exactly as written, and nothing is checked or filled in. {{unsubscribe_url}} and {{web_version_url}} still work. Defaults to true.

pushTransactionalPushInputoptional

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

14 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 2,048 characters

imageUrlstringoptional

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

uri · up to 2,048 characters

iconUrlstringoptional

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

uri · up to 2,048 characters

datamap<string, string>optional

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

at most 10 keys · keys: pattern ^[A-Za-z0-9_.-]{1,64}$ · values: up to 1,024 characters

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 2,048 characters

collapseKeystringoptional

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

pattern ^[A-Za-z0-9_-]{1,64}$

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

ttlDurationOrZeroInputoptional

How long a provider keeps trying an offline device, up to 28 days; zero delivers now or never. Defaults to one day.

2 child attributes
valueintegerrequired

min 0

unitstringrequired

one of seconds, minutes, hours, days

urgencystringoptional

high asks the push service to deliver promptly, even to a sleeping device; normal lets it wait for a good moment to save battery. Device settings and the app still decide whether and how it is shown. 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

pattern ^[a-z][a-z0-9+.-]*:\S+$ · up to 2,048 characters

imageUrlstringoptional

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

uri · up to 2,048 characters

iconUrlstringoptional

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

uri · up to 2,048 characters

datamap<string, string>optional

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

at most 10 keys · keys: pattern ^[A-Za-z0-9_.-]{1,64}$ · values: up to 1,024 characters

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 2,048 characters

collapseKeystringoptional

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

pattern ^[A-Za-z0-9_-]{1,64}$

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

ttlDurationOrZeroInputoptional

How long a provider keeps trying an offline device, up to 28 days; zero delivers now or never. Defaults to one day.

2 child attributes
valueintegerrequired

min 0

unitstringrequired

one of seconds, minutes, hours, days

urgencystringoptional

high asks the push service to deliver promptly, even to a sleeping device; normal lets it wait for a good moment to save battery. Device settings and the app still decide whether and how it is shown. Unset, a transactional push is high and any other normal.

one of high, normal

interruptionLevelstringoptional

How iOS presents it: passive arrives silently, time-sensitive can break through Focus when the user allows it, 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.

pattern ^[A-Za-z0-9_.-]{1,64}$

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

pattern ^[a-z][a-z0-9+.-]*:\S+$ · up to 2,048 characters

imageUrlstringoptional

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

uri · up to 2,048 characters

iconUrlstringoptional

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

uri · up to 2,048 characters

datamap<string, string>optional

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

at most 10 keys · keys: pattern ^[A-Za-z0-9_.-]{1,64}$ · values: up to 1,024 characters

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 2,048 characters

collapseKeystringoptional

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

pattern ^[A-Za-z0-9_-]{1,64}$

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

ttlDurationOrZeroInputoptional

How long a provider keeps trying an offline device, up to 28 days; zero delivers now or never. Defaults to one day.

2 child attributes
valueintegerrequired

min 0

unitstringrequired

one of seconds, minutes, hours, days

urgencystringoptional

high asks the push service to deliver promptly, even to a sleeping device; normal lets it wait for a good moment to save battery. Device settings and the app still decide whether and how it is shown. 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.

pattern ^[A-Za-z0-9_.-]{1,64}$

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 2,048 characters

imageUrlstringoptional

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

uri · up to 2,048 characters

iconUrlstringoptional

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

uri · up to 2,048 characters

datamap<string, string>optional

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

at most 10 keys · keys: pattern ^[A-Za-z0-9_.-]{1,64}$ · values: up to 1,024 characters

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 2,048 characters

collapseKeystringoptional

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

pattern ^[A-Za-z0-9_-]{1,64}$

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

ttlDurationOrZeroInputoptional

How long a provider keeps trying an offline device, up to 28 days; zero delivers now or never. Defaults to one day.

2 child attributes
valueintegerrequired

min 0

unitstringrequired

one of seconds, minutes, hours, days

urgencystringoptional

high asks the push service to deliver promptly, even to a sleeping device; normal lets it wait for a good moment to save battery. Device settings and the app still decide whether and how it is shown. Unset, a transactional push is high and any other normal.

one of high, normal

pushProjectIdstringoptional

Reaches the contact's devices on every app of the project. Needed only when the workspace has more than one push project.

uuid

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. A fallbackOrder fallback keeps this time but goes only after the message before it fails, is skipped or bounces.

date-time

fallbackOrderstring[]optional

With both push and email, each once, in the order to try them: the first the contact can receive is sent, and the next only if it fails, is skipped or bounces. Left out, each channel the contact can receive is sent.

at least 1 item

Returns

Returns 202 Accepted with a TransactionalSendResult in data. It can also return 409 Conflict, 413 Payload Too Large or 415 Unsupported Media Type; see the statuses below. Otherwise returns an error; Errors lists every code and which to retry.

  • 202 AcceptedAccepted: one message per channel sent.
  • 409 ConflictThe request conflicts with current state — a duplicate unique value, or a resource whose status does not allow this operation.
  • 413 Payload Too LargeThe body is larger than this operation accepts (PAYLOAD_TOO_LARGE).
  • 415 Unsupported Media TypeThe body is not JSON, or not the upload the operation takes (UNSUPPORTED_MEDIA_TYPE).
messagesTransactionalMessage[]required
8 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 message goes out; null when it went at once.

date-time

fallbackForstring | nullrequired

With fallbackOrder: the message this one stands in for. It waits as queued until that one ends: sent when it failed, was skipped or bounced, else skipped with reason fallback_not_needed. Null otherwise.

uuid

copyobject | nullrequired

Set on a cc or bcc copy; null on the message itself.

2 child attributes
kindstringrequired

one of cc, bcc

ofstringrequired

The message it is a copy of.

uuid

skippedChannelsTransactionalSkippedChannel[]required

Channels given that were not sent, each with the reason: the contact cannot receive it, or the plan has no room for it.

3 child attributes
channelstringrequired

one of email, push

codestringrequired

Its error code, such as SUPPRESSED.

messagestringrequired
skippedCopiesTransactionalSkippedCopy[]required

cc or bcc addresses that got no copy, each with the reason.

4 child attributes
emailstringrequired
kindstringrequired

one of cc, bcc

codestringrequired

Its error code, such as SUPPRESSED.

messagestringrequired

Headers on 202 Accepted

Idempotency-Replaystringoptional

true when this is the stored response to an earlier request with the same key.

one of true