The Transactional Email API lets you send personalized, event-triggered emails, such as order confirmations, password resets, and shipping updates, to every user in a batch. Each recipient receives a message built from their own data, their actual order items, amounts, dates, and tracking details, rather than one identical template where only the name changes.
V2 offers the following feature set:
Per-recipient personalization with Liquid, using structured data (nested objects and lists)
Conditional content that shows or hides within a template based on each recipient's data
View in Browser support
Analytics categories, for reporting by email type
Template validation before a send goes live
Delivery-status tracking, per recipient
V1, the legacy Transactional Email API, will remain supported until August 2027.
Before you start
Channel setup
Complete the Transactional Email Channel Setup first. The sender domain you use in the from email must be authenticated; unauthenticated domains are rejected.
Authentication
V2 supports two authentication methods. The request and response bodies are identical for both, and in both cases your client is implicit in your credentials: no request carries a partner or tenant parameter.
Method | Base URL | Auth header | Purpose |
|---|---|---|---|
API key | https://email.useinsider.com | X-INS-AUTH-KEY: INS.{id}.{secret} | Existing integrations. One key covers every endpoint. |
OAuth 2.0, through the Insider Gateway | https://gw.useinsider.com | Authorization: Bearer {token} | New integrations. Per-scope permissions, IP allowlisting, and short-lived tokens. |
Once OAuth 2.0 is enabled and used for Transactional Email, generating a new API key for the same API is restricted. API keys already issued continue to work, and both methods can be called against the same account. Plan the switch before you retire an existing key.
The two methods do not share the same paths. Direct calls go to /mail/v2/send; gateway calls go to /api/em/v2/tx/send. Use the path that matches your authentication method, as shown in the endpoints table below.
API key
One key covers every endpoint on this page. Generate it once, following API Authentication Tokens, and reuse the same X-INS-AUTH-KEY across send, validate, delivery status, and all category endpoints. You do not generate a separate key per endpoint, nor do you need to regenerate it to call a different endpoint.
OAuth 2.0
The auth flow is the same for every endpoint, but each endpoint requires its own scope. Request every scope you need when you generate the token, and that one token then works across those endpoints. For credential creation, the full scope table, token handling, and gateway error codes, refer to Transactional Email OAuth 2.0 Authentication.
Endpoints
Each path below links to its own page with headers, parameters, examples, and responses.
Method | Direct Path (API key) | Gateway path (OAuth 2.0) | Purpose |
|---|---|---|---|
POST | /mail/V2/send | /api/em/v2/tx/send | Send a transactional email to up to 100 recipients |
POST | /mail/V2/validate | /api/em/v2/tx/validate | Check a template's Liquid syntax, and optionally render it, without sending |
GET | /mail/V2/messages/{message_id} | /api/em/v2/tx/messages/{message_id} | Read the delivery status for a previously accepted message |
POST | /mail/V2/categories | /api/em/v2/tx/categories | Create a category for analytics tracking purposes |
GET | /mail/V2/categories | /api/em/v2/tx/categories | List existing categories |
GET | /mail/V2/categories/{id} | /api/em/v2/tx/categories/{id} | Read a single category |
Authenticate directly with the X-INS-AUTH-KEY header, or through the Insider Gateway API using OAuth 2.0 (authenticate to the Gateway with Authorization: Bearer {token}, and it proxies your request to the internal endpoint). The request and response bodies are identical for both.
Sample request and response
Below is a minimal personalized send. For the full parameter list and more examples, refer to POST /mail/v2/send.
{
"subject": "Order {{ order.id }} confirmed",
"from": {
"email": "no-reply@acme.com",
"name": "Acme Store"
},
"recipients": [
{
"email": "alice@example.com",
"fields": {
"first_name": "Alice",
"order": {
"id": "A-1024"
}
}
}
],
"content": [
{
"type": "text/html",
"value": "<p>Hi {{ first_name }}, order {{ order.id }} is confirmed.</p>"
}
]
}A successful send returns 202 Accepted with a message_id:
{
"status": "accepted",
"message_id": "550e8400-e29b-41d4-a716-446655440000"
}Templating and personalization
The subject and the HTML body are rendered for each recipient using Liquid, with values from that recipient's fields. Insider One's Liquid supports the full set of Liquid tags and filters; the table below lists the capabilities most templates use. For the complete reference, refer to Liquid tags.
Capability | Example |
|---|---|
Variables | {{ first_name }} |
Nested values with dot-notation | {{ order.total }}, {{ address.city }} |
Conditions | {% if order.total > 100 %} ... {% endif %} |
Loops over lists | {% for item in order.items %}{{ item.name }}{% endfor %} |
Before a template goes live, confirm it is well-formed with the validation endpoint POST /mail/v2/validate.
Analytics categories
Categories group transactional emails so you can report on performance by email type, e.g., order confirmations versus password resets. Register a category, then reference it by its integer ID in the category field of a send. Categories are append-only. IDs are never reused, and you can't change a name or description after creation.
Manage categories with the Create, List, and Read category endpoints. Reporting by category is shown in Transactional Email Analytics.
Delivery events
V2 emits delivered, open, click, bounce, blocked, and dropped events. They reach you through two independent channels, and each uses different event names.
Webhook payload
The event field in the webhook body carries the bare event name: delivered, open, click, bounce, dropped, deferred, spam_complaint. For payloads and signature details, see Webhooks for Transactional Emails.
UCD profile events
When UCD event logging is enabled for your account, the same events are also recorded on the user's profile under the names below. These names appear in UCD and in segmentation, not in the webhook body.
Event | Parameters |
|---|---|
txn_email_delivered | ip_address, src, subject, message_id |
txn_email_open | ip_address, src, subject, user_agent, message_id |
txn_email_click | ip_address, src, subject, user_agent, url, url_offset_index (number), url_offset_type, message_id |
txn_email_bounce | ip_address, reason, src, subject, type, message_id |
txn_email_blocked | ip_address, reason, src, subject, type |
txn_email_dropped | reason, src, subject, message_id |
Unless otherwise noted, a parameter's type is string; any exception is marked next to the parameter.
Callbacks
Unlike V1, the callback URL and secret are not part of the send payload. Configure them once in the panel under Settings > Email Settings > Webhook Integration for Transactional Email. After you enable it there and enter your Callback URL and Secret, V2 POSTs delivery events to that URL using the bare event names listed above. For payload and signature details, see Email Webhooks for Transactional Emails.
Error responses
Errors arrive from one of two layers, and the two use different response shapes.
Layer | Applies to | Envelope | Reference |
|---|---|---|---|
Gateway | OAuth 2.0 callers only | { "code": "R1", "message": "Invalid Token" } | |
Service | All callers | { "status": "error", "message": "...", "errors": [ ... ] } |
A gateway error means the request never reached the email service, so nothing was queued. A successful send returns 202; a duplicate within the 15-minute window returns 409. Each endpoint page shows its own responses, and the Error Codes page carries the full list across all endpoints.
Limitations
Constraint | Value |
|---|---|
Recipients per request | 100 |
Top-level fields keys per recipient | 150 |
fields nesting depth | 5 |
Serialized fields per recipient | 256 KB |
unique_args | 10 keys / 1 KB |
Content blocks | 2 (one HTML, one plain text) |
Request body | 20 MB (about 14 MB of decoded attachments) |
Deduplication window | 15 minutes |
Delivery-status retention | 2 days |
Categories per customer | 100 |
Send Rate Limit* | No per-account limit. Requests are subject to a platform-wide rate limit; when it is reached, the API returns 429 with retry_after. |
Rate limit, gateway layer** | Per credential and per scope. Default 100 requests per 60 seconds, with a burst allowance of 10. |
*Rate limiting is fail-closed: if the limiter is unreachable, requests receive 429 with a retry_after value.
**The gateway layer applies only to OAuth 2.0 callers and is evaluated before the request reaches the email service. It returns 429 with {"code": "R3"} and no retry_after value. Limits are set per scope when the credential is created.