The request
| Part | Value |
|---|---|
| Route | POST https://api.maqetin.com/v1/public/messages |
| Key | A secret key in Authorization: Bearer mq_sec_…, made with the messages:send scope. |
| Idempotency-Key | Optional. Letters, digits and _ . : -, at most 100 characters. |
The body
| Field | Required | What it holds |
|---|---|---|
| channel | Yes | email, the one channel built today. |
| templateId | Yes | The id of a template in your workspace. |
| to | Yes | { "userId": "…" } for a person you identified, or { "email": "…" } for an address with no profile. |
| from | Yes | Name <local@domain> or local@domain. Without a name, Maqetin uses the workspace name. The domain must be a verified sending domain of the workspace. |
| subject | No | Replaces the subject of the template. |
| data | No | Merge data for the template, at most 16 KB. It goes over the traits of the person but never over email or user_id. |
{
"channel": "email",
"templateId": "tpl_receipt",
"to": { "email": "ada@example.com" },
"from": "Receipts <receipts@mail.harbourmoney.co.uk>",
"subject": "Your receipt",
"data": { "order": { "id": "o_42", "total": 12.5 } }
}Replace the sample values with your own: templateId names one of your templates, and the domain of from is a verified sending domain of your workspace.
Send it
HTTP
curl https://api.maqetin.com/v1/public/messages \
-H 'Authorization: Bearer mq_sec_…' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-42:receipt' \
-d '{
"channel": "email",
"templateId": "tpl_receipt",
"to": { "email": "ada@example.com" },
"from": "Receipts <receipts@mail.harbourmoney.co.uk>",
"subject": "Your receipt",
"data": { "order": { "id": "o_42", "total": 12.5 } }
}'Node
import { MaqetinServer } from '@maqetin/sdk-js/server';
const mq = new MaqetinServer({ secretKey: process.env.MAQETIN_SECRET_KEY });
const { messageId } = await mq.messages.send({
channel: 'email',
templateId: 'tpl_receipt',
to: { userId: 'u_42' }, // or { email: 'guest@example.com' }
from: 'Harbour Money <receipts@mail.harbourmoney.co.uk>',
data: { order: { id: 'o_42', total: 12.5 } },
idempotencyKey: 'order-42:receipt',
});The Node call is the server entry of the SDK. It makes an idempotency key when you give none.
Send a retry safely
Send the same Idempotency-Key on a retry and Maqetin sends the message once. The first body sent with a key is the one that counts.
The SDK retries after a 5xx, a 429 or a network error with the same key. It gives up on a request that does not answer after requestTimeoutMs, 15 seconds by default.
What comes back
A reply of the API holds success and data. The answer of a 202 is in data: { messageId, status: "queued" }.
| Status | Meaning |
|---|---|
| 400 | The body or a header does not parse. |
| 401 | The request has no secret key. |
| 403 | The key has no messages:send scope. |
| 404 | The userId has no profile, or the profile has no address, or the template is not there. |
| 409 | The send is refused. The reason is one of sending_disabled, workspace_inactive, sending_not_approved and sender_domain_invalid. |
| 429 | Over 300 sends a minute for the key, or over its request limit. |
What a transactional message does
- It reaches a person who unsubscribed from marketing.
- It never reaches a suppressed address.
- It has no unsubscribe link.