Send transactional or marketing email
Changed onQueues an email for sending. The default emailType is transactional. Set it to marketing for a consented single-recipient lifecycle or promotional message. Marketing mode creates or links a minimal subscriber, honors unsubscribe suppression, adds the standard marketing footer, and emits RFC 8058 one-click-unsubscribe headers. The caller remains responsible for having consent or another lawful basis.
For callers that may retry, send a stable Idempotency-Key header. The same key and request returns the original emailSendId for 14 days without another delivery. Reusing a key with different request content returns 409.
Repeated identical transactional content reaching many distinct recipients can trigger a junk/list-testing review. Sending continues while review is pending or unavailable. A substantiated verdict can reject later matching deliveries before sending; these become terminal failed sends with an errorMessage beginning Transactional content rejected:. Read GET /email-sends/{emailSendId} for the final outcome. Failed deliveries are not held or replayed automatically, and replaying the same Idempotency-Key returns the original acceptance response. Dashboard retries of rejected deliveries also fail without sending, even after the decision expires. Correct the content or contact support before deliberately submitting a new logical send. This check does not pause the company or ban the account.
You can either:
- Provide a canonical slug (or compatibility alias templateId) to use a saved template
- Provide subject and canonical body (or compatibility alias html) to send custom content directly
If both a canonical field and its alias are provided, slug must match templateId and body must match html.
Tracking direct-content sends:
- Set trackAs on a direct-content send (for example weekly-report) to count it under one code-managed transactional email. The first send with a new value creates it with managedBy: code; later sends with the same value link to it. The value may use up to 255 ASCII letters, digits, spaces and . _ - : /, and is normalized like a slug (Weekly Report and weekly-report are the same email). Other values, including empty ones, return 400 INVALID_TRACK_AS.
- Opens, clicks, bounces and the other transactional stats then aggregate on that email, and it appears in GET /transactional next to your saved templates. Its subject, preview text and HTML are a snapshot of a recent send, refreshed at most every 10 minutes and stored before variable substitution.
- Disabling the code-managed email makes further sends with that trackAs fail with 400 TRACKED_EMAIL_DISABLED until you enable it again. Deleting it lets the next send recreate it with fresh stats.
- trackAs cannot be combined with slug/templateId, cannot reuse the slug of a template managed in the dashboard, and a company can have at most 100 code-managed emails. Use a stable name for an email type, never per-recipient values. Code-managed emails cannot be sent by slug.
- The email is created after the send passes request validation, so an invalid send does not create it. A send that fails later, for example on an Idempotency-Key conflict, can still leave the newly created email with no sends.
Recipients:
- to can be a single email or an array of up to 50 emails
- Duplicate emails are automatically deduplicated
- Marketing mode requires exactly one to recipient and does not support cc or bcc
Attachments:
- Attachments can be provided as Base64-encoded content or URLs
- Maximum 10 attachments and 15MB total per email
- Any file type supported (PDFs, images, documents, etc.)
- Set contentId on an attachment to embed it as an inline image referenced from the HTML as <img src="cid:VALUE">
A successful response means the email was accepted for background processing. Transactional emails are not blocked by subscriber unsubscribe or double opt-in status. If a recipient is suppressed because of a hard bounce or spam complaint, the worker records the send as suppressed instead of delivering it.
Optionally set from (domain must be verified) and replyTo addresses. When reply tracking is enabled, Sequenzy uses a unique trackable Reply-To header and treats the resolved reply destination as the forwarding destination for captured replies. Without a reply identity override, saved-template sends prefer the template reply profile. Otherwise sends prefer the effective sending domain's default reply profile, then the company default, then the first company reply profile. The resolved destination is retained whether or not reply tracking is enabled; it is sent as the Reply-To header only when reply tracking is disabled. Variables can be passed to customize the email content. Nested objects and arrays are supported for repeat blocks, such as items. {{viewInBrowserUrl}} is generated automatically for a hosted copy link. For a single recipient, Sequenzy matches an existing subscriber by subscriberExternalId or email and backfills stored first and last names when the corresponding request variables are omitted; explicit variables take precedence. Returns immediately with a durable emailSendId and the accepted emailType. If Sequenzy detects likely missing or unused variables before queueing, the successful response includes a non-blocking diagnostics warning object. Missing values do not block queueing or sending; a required variable that is not provided and has no default renders as an empty string.
Select existing identities with senderProfileId or fromEmail (and optional fromName), and replyProfileId or replyTo (with optional replyToName). These inputs look up profiles rather than create them. Use emailType, not isMarketing, to choose delivery policy.
Request
- Base URLhttps://api.sequenzy.com/api/v1
- URLhttps://api.sequenzy.com/api/v1/transactional/send
- AuthHTTP bearer
Headers
Caller-owned key for one logical email. Reuse the same key and request on retries to receive the original send for 14 days. Reusing the key with different content returns 409.
Request body
Example request
{
"slug": "welcome-email",
"templateId": "welcome-email",
"subscriberExternalId": "user_123",
"emailType": "marketing",
"subject": "Welcome to our platform!",
"body": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
"preview": "Welcome to our platform",
"trackAs": "weekly-report",
"variables": {
"NAME": "John",
"event": {
"items": [
{
"title": "Pro plan",
"description": "Monthly subscription"
}
]
}
},
"from": "Notifications <notifications@example.com>",
"replyTo": "Support <support@example.com>",
"attachments": [
{
"filename": "invoice.pdf",
"path": "https://example.com/invoices/123.pdf"
}
],
"trackingSettings": {
"clickTracking": false
},
"headers": {
"List-Unsubscribe": "<https://example.com/unsubscribe/digest?token=abc>",
"List-Unsubscribe-Post": "List-Unsubscribe=One-Click"
}
}Response
Email queued successfully
Example response
{
"success": true,
"emailSendId": "send_abc123",
"jobId": "job_abc123",
"diagnostics": {
"status": "warning",
"message": "Email was queued. A required variable is missing and will render as an empty string.",
"missingRequiredVariables": [
{
"name": "RESET_URL",
"lookupName": "reset_url",
"message": "Email was queued. Required variable \"RESET_URL\" is missing and will render as an empty string.",
"usedIn": [
{
"surface": "block",
"field": "url",
"blockId": "reset-button",
"blockType": "button"
}
],
"suggestions": [
"resetpasswordlink"
]
}
],
"unusedVariables": [
{
"name": "resetpasswordlink",
"message": "Variable \"resetpasswordlink\" was provided but is not used by the email template.",
"suggestions": [
"reset_url"
]
}
]
},
"ignoredHeaders": [
{
"name": "List-Unsubscribe",
"reason": "managed_in_marketing_mode"
}
]
}Changes
- info
added the new optional request property
- info
added the new optional request property
- info
added the optional property
/to the response with the status - info
added the optional property
/to the response with the status - info
added the optional property
/to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status
- info
- breaking
the
/request property's minItems was increased to1 - info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
the
request property default valuetruewas removed - info
the
request property default valuetruewas removed - info
added
subschema #1: Slug-based responsesubschema #2: Direct content responseto the response bodyanyOflist for the response status - info
removed
subschema #1: Slug-based responsesubschema #2: Direct content responsefrom the response bodyoneOflist for the response status
- breaking