Sending
Send one email or a batch, schedule a send, read the email log and manage follow-ups.
/v1/transactional/follow-upsAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Query Parameters
Optional filter by active status
^-?(?:0|[1-9]\d*)$int3220Response Body
application/json
application/json
application/json
curl -X GET "https://example.com/v1/transactional/follow-ups"{ "items": [ { "id": "string", "name": "string", "description": null, "triggerTemplateId": "string", "triggerTemplateName": "string", "triggerMessageStream": null, "followUpTemplateId": "string", "followUpTemplateName": "string", "delayValue": 0, "delayUnit": "string", "onlyIfNotOpened": true, "onlyIfNotClicked": true, "skipWeekends": true, "allowedFromHour": null, "allowedToHour": null, "maxPerRecipientPerDay": null, "isActive": true, "priority": 0, "totalTriggered": 0, "totalSent": 0, "totalSkipped": 0, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": null } ], "nextCursor": null, "hasMore": true}/v1/transactional/follow-upsAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/transactional/follow-ups" \ -H "Content-Type: application/json" \ -d '{}'{ "id": "string", "name": "string", "description": null, "triggerTemplateId": "string", "triggerTemplateName": "string", "triggerMessageStream": null, "followUpTemplateId": "string", "followUpTemplateName": "string", "delayValue": 0, "delayUnit": "string", "onlyIfNotOpened": true, "onlyIfNotClicked": true, "skipWeekends": true, "allowedFromHour": null, "allowedToHour": null, "maxPerRecipientPerDay": null, "isActive": true, "priority": 0, "totalTriggered": 0, "totalSent": 0, "totalSkipped": 0, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": null}/v1/transactional/follow-ups/{id}Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
Public ID of the rule
Response Body
application/json
application/json
application/json
curl -X GET "https://example.com/v1/transactional/follow-ups/string"{ "id": "string", "name": "string", "description": null, "triggerTemplateId": "string", "triggerTemplateName": "string", "triggerMessageStream": null, "followUpTemplateId": "string", "followUpTemplateName": "string", "delayValue": 0, "delayUnit": "string", "onlyIfNotOpened": true, "onlyIfNotClicked": true, "skipWeekends": true, "allowedFromHour": null, "allowedToHour": null, "maxPerRecipientPerDay": null, "isActive": true, "priority": 0, "totalTriggered": 0, "totalSent": 0, "totalSkipped": 0, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": null}/v1/transactional/follow-ups/{id}Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
Public ID of the rule
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/v1/transactional/follow-ups/string" \ -H "Content-Type: application/json" \ -d '{}'{ "id": "string", "name": "string", "description": null, "triggerTemplateId": "string", "triggerTemplateName": "string", "triggerMessageStream": null, "followUpTemplateId": "string", "followUpTemplateName": "string", "delayValue": 0, "delayUnit": "string", "onlyIfNotOpened": true, "onlyIfNotClicked": true, "skipWeekends": true, "allowedFromHour": null, "allowedToHour": null, "maxPerRecipientPerDay": null, "isActive": true, "priority": 0, "totalTriggered": 0, "totalSent": 0, "totalSkipped": 0, "createdAt": "2019-08-24T14:15:22Z", "updatedAt": null}/v1/transactional/follow-ups/{id}Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
Public ID of the rule
Response Body
application/json
application/json
curl -X DELETE "https://example.com/v1/transactional/follow-ups/string"/v1/transactional/follow-ups/{id}/toggleAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
Public ID of the rule
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Request DTO for toggling rule active status
Response Body
application/json
application/json
curl -X POST "https://example.com/v1/transactional/follow-ups/string/toggle" \ -H "Content-Type: application/json" \ -d '{}'/v1/transactional/follow-ups/scheduledAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Query Parameters
Optional filter by rule ID
Optional filter by status (Pending, Sent, Skipped, Cancelled, Failed)
^-?(?:0|[1-9]\d*)$int3220Response Body
application/json
application/json
application/json
curl -X GET "https://example.com/v1/transactional/follow-ups/scheduled"{ "items": [ { "publicId": "string", "ruleId": "string", "ruleName": "string", "recipientEmail": "string", "recipientName": null, "scheduledAt": "2019-08-24T14:15:22Z", "status": "string", "skipReason": null, "processedAt": null, "createdAt": "2019-08-24T14:15:22Z" } ], "nextCursor": null, "hasMore": true}/v1/transactional/follow-ups/scheduled/{id}/cancelAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
ID of the scheduled follow-up
Response Body
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/transactional/follow-ups/scheduled/string/cancel"/v1/transactional/follow-ups/statsAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Response Body
application/json
application/json
curl -X GET "https://example.com/v1/transactional/follow-ups/stats"{ "totalRules": 0, "activeRules": 0, "totalTriggered": 0, "totalSent": 0, "totalSkipped": 0, "pendingFollowUps": 0, "sendRate": 0}/v1/transactional/logsPERF: Default 30-day date range prevents full table scan on 1M+ messages. Date filter is always applied for performance. Count is cached for 2 minutes when no search filter is applied.
Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Query Parameters
^-?(?:0|[1-9]\d*)$int3220Filter by status (e.g., "sent", "delivered", "bounced")
Search term for recipient, subject, or message ID
Start date filter
date-timeEnd date filter
date-timeWhen true, bypasses count cache and fetches fresh data
falseResponse Body
application/json
application/json
curl -X GET "https://example.com/v1/transactional/logs"{ "items": [ { "messageId": "string", "recipient": "string", "subject": "string", "status": "string", "sentAt": "2019-08-24T14:15:22Z", "deliveredAt": null, "openedAt": null, "clickedAt": null, "bounceReason": null, "platformSide": true, "attemptsExpired": true, "openCount": 0, "clickCount": 0, "deliveryStatus": "string", "statusVersion": 0, "previousStatus": null, "complaintStatus": "string", "outcomeState": "string" } ], "nextCursor": null, "hasMore": true}/v1/transactional/logs/statsAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Query Parameters
Start date for the stats query (default: 7 days ago).
date-timeEnd date for the stats query (default: now).
date-timeFilter by email type: 0 = Transactional, 1 = Marketing, null = all.
Value in
- "transactional"
- "marketing"
When true, bypasses cache and queries ClickHouse directly.
falseResponse Body
application/json
curl -X GET "https://example.com/v1/transactional/logs/stats"{ "total": 0, "accepted": 0, "sent": 0, "delivered": 0, "opened": 0, "clicked": 0, "bounced": 0, "platformRefused": 0, "attemptsExpired": 0, "complained": 0, "failed": 0, "queued": 0, "deliveryRate": 0, "openRate": 0, "clickRate": 0, "bounceRate": 0, "complaintRate": 0, "source": "string", "queryTimeMs": 0, "hasAnyData": true}/v1/transactional/logs/{messageId}Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
Response Body
application/json
curl -X GET "https://example.com/v1/transactional/logs/string"{ "fromEmail": "string", "createdAt": "2019-08-24T14:15:22Z", "bounceCategory": null, "ipAddress": null, "retryCount": 0, "smtpResponse": null, "htmlContent": null, "textContent": null, "events": null, "messageId": "string", "recipient": "string", "subject": "string", "status": "string", "sentAt": "2019-08-24T14:15:22Z", "deliveredAt": null, "openedAt": null, "clickedAt": null, "bounceReason": null, "platformSide": true, "attemptsExpired": true, "openCount": 0, "clickCount": 0, "deliveryStatus": "string", "statusVersion": 0, "previousStatus": null, "complaintStatus": "string", "outcomeState": "string"}/v1/transactional/logs/{messageId}/retryAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
Response Body
application/json
curl -X POST "https://example.com/v1/transactional/logs/string/retry"{ "message": "string"}/v1/transactional/scheduledAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Query Parameters
^-?(?:0|[1-9]\d*)$int3220Filter by status (pending, processing, sent, failed, cancelled)
Response Body
application/json
application/json
curl -X GET "https://example.com/v1/transactional/scheduled"{ "items": [ { "scheduleId": "b7b4f318-018f-4d71-ac1a-f61e4bfaefbe", "status": "string", "scheduledAt": "2019-08-24T14:15:22Z", "timeZone": null, "to": "string", "recipientCount": null, "subject": "string", "createdAt": "2019-08-24T14:15:22Z", "processedAt": null, "messageId": null, "messageIds": [ "string" ], "rejectedRecipients": [ { "email": "string", "reason": "string" } ], "reasonCode": null, "error": null } ], "nextCursor": null, "hasMore": true}/v1/transactional/scheduledAuthorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Request Body
application/json
The email scheduling request
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://example.com/v1/transactional/scheduled" \ -H "Content-Type: application/json" \ -d '{ "from": { "email": "string" }, "to": { "email": "string" }, "subject": "string", "scheduledAt": "2019-08-24T14:15:22Z" }'{ "scheduleId": "b7b4f318-018f-4d71-ac1a-f61e4bfaefbe", "status": "string", "scheduledAt": "2019-08-24T14:15:22Z", "timeZone": null, "to": "string", "recipientCount": null, "subject": "string", "createdAt": "2019-08-24T14:15:22Z", "processedAt": null, "messageId": null, "messageIds": [ "string" ], "rejectedRecipients": [ { "email": "string", "reason": "string" } ], "reasonCode": null, "error": null}/v1/transactional/scheduled/{scheduleId}Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
The schedule ID
uuidResponse Body
application/json
application/json
curl -X GET "https://example.com/v1/transactional/scheduled/497f6eca-6276-4993-bfeb-53cbbbba6f08"{ "scheduleId": "b7b4f318-018f-4d71-ac1a-f61e4bfaefbe", "status": "string", "scheduledAt": "2019-08-24T14:15:22Z", "timeZone": null, "to": "string", "recipientCount": null, "subject": "string", "createdAt": "2019-08-24T14:15:22Z", "processedAt": null, "messageId": null, "messageIds": [ "string" ], "rejectedRecipients": [ { "email": "string", "reason": "string" } ], "reasonCode": null, "error": null}/v1/transactional/scheduled/{scheduleId}Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
The schedule ID
uuidResponse Body
application/json
application/json
curl -X DELETE "https://example.com/v1/transactional/scheduled/497f6eca-6276-4993-bfeb-53cbbbba6f08"/v1/transactional/scheduled/{scheduleId}Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Path Parameters
The schedule ID
uuidRequest Body
application/json
The reschedule request
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
curl -X PATCH "https://example.com/v1/transactional/scheduled/497f6eca-6276-4993-bfeb-53cbbbba6f08" \ -H "Content-Type: application/json" \ -d '{ "scheduledAt": "2019-08-24T14:15:22Z" }'{ "scheduleId": "b7b4f318-018f-4d71-ac1a-f61e4bfaefbe", "status": "string", "scheduledAt": "2019-08-24T14:15:22Z", "timeZone": null, "to": "string", "recipientCount": null, "subject": "string", "createdAt": "2019-08-24T14:15:22Z", "processedAt": null, "messageId": null, "messageIds": [ "string" ], "rejectedRecipients": [ { "email": "string", "reason": "string" } ], "reasonCode": null, "error": null}/v1/transactional/sendSends an email to one or more recipients. The email is queued for delivery and a job ID is returned for tracking.
Possible error codes:
- SEND_FAILED: Email validation failed
- TEMPLATE_NOT_FOUND: templateId names no active template of this account
- IP_POOL_NOT_FOUND: ipPoolId names no pool assigned to this account
- TEMPLATE_VARIABLE_MISSING (422): the content has a {{placeholder}} with no value; nothing is sent (the batch endpoint skips those recipients and lists them in rejectedRecipients)
- INVALID_REQUEST: scheduledAt is more than 7 days ahead
- VALIDATION_FAILED: the request body is invalid (including attachments: more than 10, over 10 MiB decoded in total, or content that is not canonical Base64)
- DOMAIN_NOT_FOUND: Sending domain not registered
- DOMAIN_NOT_VERIFIED: Sending domain not verified
- RATE_LIMIT_EXCEEDED: Account rate limit exceeded
- QUOTA_EXCEEDED: Monthly quota exceeded
- ACCOUNT_NOT_ACTIVE: Account is suspended/disabled
- NO_ACTIVE_SUBSCRIPTION: No valid subscription
- IDEMPOTENCY_KEY_INVALID: The idempotency key is empty, malformed, over 255 characters, or the header was sent more than once
- IDEMPOTENCY_KEY_CONFLICT: The X-Idempotency-Key header and the idempotencyKey body field were both supplied and differ
- IDEMPOTENCY_KEY_REUSED (409): The key is already in use for a different endpoint on this account
Idempotency: supply X-Idempotency-Key (recommended) or the idempotencyKey body field.
Supplying both is allowed only when the values are identical. A retry with the same key
within the retention window replays the original response verbatim instead of sending again.
Keys are unique per account, so one key cannot be reused for a different operation.
Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Request Body
application/json
Cancellation token
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/transactional/send" \ -H "Content-Type: application/json" \ -d '{ "from": {}, "to": [ {} ] }'{ "success": true, "jobId": null, "messageIds": [ "string" ], "acceptedRecipients": [ "string" ], "rejectedRecipients": [ { "email": "string", "reason": "string", "suggestion": null } ], "error": null, "errorCode": null, "queuedAt": "2019-08-24T14:15:22Z", "isSandboxed": true, "sandboxReason": null, "scheduledAt": null, "scheduleId": null}/v1/transactional/send-batchSends a batch of emails to multiple recipients with the same content. Returns a batch ID for tracking all emails in the batch.
Possible error codes:
- BATCH_SEND_FAILED: Batch validation failed
- TEMPLATE_NOT_FOUND: templateId names no active template of this account
- IP_POOL_NOT_FOUND: ipPoolId names no pool assigned to this account
- TEMPLATE_VARIABLE_MISSING (422): the content has a {{placeholder}} with no value; nothing is sent (the batch endpoint skips those recipients and lists them in rejectedRecipients)
- INVALID_REQUEST: scheduledAt is more than 7 days ahead
- DOMAIN_NOT_FOUND: Sending domain not registered
- DOMAIN_NOT_VERIFIED: Sending domain not verified
- RATE_LIMIT_EXCEEDED: Account rate limit exceeded
- QUOTA_EXCEEDED: Monthly quota exceeded
- ACCOUNT_NOT_ACTIVE: Account is suspended/disabled
- NO_ACTIVE_SUBSCRIPTION: No valid subscription
- IDEMPOTENCY_KEY_INVALID: The idempotency key is empty, malformed, over 255 characters, or the header was sent more than once
- IDEMPOTENCY_KEY_CONFLICT: The X-Idempotency-Key header and the idempotencyKey body field were both supplied and differ
- IDEMPOTENCY_KEY_REUSED (409): The key is already in use for a different endpoint on this account
Idempotency: supply X-Idempotency-Key (recommended) or the idempotencyKey body field.
Supplying both is allowed only when the values are identical. A retry with the same key
within the retention window replays the original response verbatim instead of sending again.
Keys are unique per account, so one key cannot be reused for a different operation.
Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Request Body
application/json
Cancellation token
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/transactional/send-batch" \ -H "Content-Type: application/json" \ -d '{ "from": {}, "recipients": [ {} ] }'{ "success": true, "batchId": "string", "messageIds": [ "string" ], "totalRecipients": 0, "acceptedCount": 0, "rejectedCount": 0, "rejectedRecipients": [ { "email": "string", "reason": "string", "suggestion": null } ], "error": null, "errorCode": null, "queuedAt": "2019-08-24T14:15:22Z", "estimatedCompletion": null, "isSandboxed": true, "sandboxReason": null, "scheduledAt": null, "scheduleId": null}/v1/transactional/send/checkPre-flight check to verify if the user can send emails. Checks rate limits and monthly quota.
Authorization
ApiKey Your API key, created in the dashboard under API keys. Production sending keys start with ml_pet_ (transactional) or ml_pem_ (marketing); sandbox keys with ml_set_ or ml_sem_.
In: header
Query Parameters
Number of recipients to check
^-?(?:0|[1-9]\d*)$int321Response Body
application/json
application/json
application/json
curl -X GET "https://example.com/v1/transactional/send/check"{ "canSend": true, "reason": null, "rateLimitStatus": { "currentSecond": 0, "limitPerSecond": 0, "currentHour": 0, "limitPerHour": 0, "currentDay": 0, "limitPerDay": 0 }, "monthlyUsed": 0, "monthlyLimit": 0}