Send an email
Sends one email to one contact. The contact is found by contactId, or found or created by contactEmail.
Content comes from exactly one source: a transactional message (transactionalMessageId), a template (templateId, filled with data), or inline html with subject and fromAddress.
Sends by template or inline HTML default to the marketing lane, which honours unsubscribes and the frequency cap. Set "lane": "transactional" for mail the recipient asked for. Pass idempotencyKey to make a retry safe.
Requires the sending:write scope.
ApiKeyAuthorization<token>Api-Key mc_... — a workspace API key.
application/json- body
lane?stringmarketing honours unsubscribes, subscription groups and the frequency cap; transactional does not. Defaults to transactional for a transactional message and to marketing for everything else.
"marketing""transactional"subscriptionGroupId?stringTag the send with a subscription group; recipients who opted out of it are suppressed.
uuidcontactId?stringThe recipient's contact id or external identifier. Required unless contactEmail is set.
contactEmail?stringThe recipient's address; the contact is created if it does not exist. Required unless contactId is set.
emailtransactionalMessageId?stringSend through a transactional message. Required unless templateId or html is set.
templateId?stringThe id or slug of an email template in this workspace.
html?stringInline HTML body. Required when neither transactionalMessageId nor templateId is set.
subject?stringSubject line. Required with html.
preHeaderText?stringPreview text shown after the subject in most inboxes. Only with html.
cc?stringCopy the message to this address. Only with html; ignored for template and transactional message sends.
emailbcc?stringBlind-copy the message to this address. Only with html; a template or transactional message uses the BCC from its own settings.
emailreplyTo?stringWhere replies go. Only with html; a template or transactional message uses the reply-to from its own settings.
emailfromAddress?stringA verified sender identity, optionally with a display name (Acme <hello@acme.com>). Required with html. Optional with templateId, where it overrides the template's sender. Ignored with transactionalMessageId.
emaildata?Values for the template's variables; each key is available as {{ key }}. Ignored with inline html, which is sent as is.
contactProperties?Properties to set on the contact as part of the send.
requiresApproval?booleanHold the delivery until someone approves it. The response then carries approvalUrl.
attachments?array<string>Files to attach: at most 20, 10 MB each and 25 MB in total.
items <= 20inReplyToInboundMessageId?stringReply to a received inbound message, threading the send under it.
idempotencyKey?stringA retry with the same key (per workspace) returns the original delivery instead of sending again.
1 <= length <= 255application/json- response
id*stringThe delivery id. Look it up with GET /public/delivery/{id}.
status*stringThe delivery's status, such as sending, pending-approval or suppressed.
lane?stringThe lane the send went out on.
suppressionReason?|Set when the recipient was suppressed instead of sent to, such as unsubscribed or frequency-cap.
approvalUrl?stringPresent when the delivery is waiting for approval.
curl -X POST 'https://api.mailcrate.io/public/sending/mail' \ -H 'Authorization: Api-Key <api_key>' \ -H 'Content-Type: application/json' \ -d '{ "contactEmail": "ada@example.com", "templateId": "password-reset", "lane": "transactional", "data": { "resetUrl": "https://app.example.com/reset/8f2c" }, "idempotencyKey": "reset-8f2c"}'{ "id": "string", "status": "string", "lane": "string", "suppressionReason": "string", "approvalUrl": "string"}Send a batch of emails POST
Sends up to 500 messages in one request, each shaped exactly like a single send. Messages are processed in order and independently: one that fails (unknown template, unverified sender, suppressed recipient) is reported in its own result entry and the others still go out. A structurally invalid payload is rejected as a whole with `400` before anything is sent. Requires the `sending:write` scope.
Add a sending domain POST
The response lists the DNS records to publish. Then call check-verification. Requires the `sending-domain:write` scope.