Send Email
POST/email/campaign
Send emails to contacts for business campaigns or automated emails.
Metadata
You can optionally attach a metadata object to the send. Metadata is echoed back on every webhook event generated for that send, allowing you to associate webhook events with your own entities such as order IDs, tenant IDs, or internal campaign identifiers.
Example:
{
"subject": "Your order shipped",
"body": "<html>...</html>",
"sender": {
"from": {
"name": "Shop",
"email": "orders@shop.com"
}
},
"recipients": {
"to": [
{
"email": "ann@example.com"
}
]
},
"campaignId": "order_shipped_SO-1001",
"metadata": {
"order_id": "SO-1001",
"tenant_id": "acme"
}
}
The metadata is available in every webhook event generated for the send.
Per-recipient metadata
A batch that shares one subject, body and sender but needs a different identifier per message sets metadata on the recipient as well. The two maps are merged and the recipient's keys win:
{
"subject": "Your order shipped",
"body": "<html>Hi [FIRST_NAME]</html>",
"sender": {
"from": {
"name": "Shop",
"email": "orders@shop.com"
}
},
"campaignId": "order_shipped",
"metadata": {
"tenant_id": "acme",
"app": "checkout"
},
"recipients": {
"to": [
{
"email": "ann@example.com",
"attributes": { "FIRST_NAME": "Ann" },
"metadata": { "order_id": "SO-1" }
},
{
"email": "bob@example.com",
"attributes": { "FIRST_NAME": "Bob" },
"metadata": { "order_id": "SO-2" }
}
]
}
}
Ann's webhook events carry {"tenant_id": "acme", "app": "checkout", "order_id": "SO-1"} and Bob's the same with SO-2. A recipient that omits metadata inherits the request-level map unchanged, so the two shapes can be mixed in one request.
The merged map must not exceed 10 keys, and at most 500 recipients per request may carry their own metadata. Requests that break either rule are rejected with 412 before any email is sent.
Metadata is scoped to the campaignId. If the same campaignId is used by multiple requests, they share the same metadata and the latest value replaces the previous value — including every per-recipient entry, so reusing a campaignId across batches discards the earlier batch's recipient metadata. To keep metadata isolated, use a unique campaignId for each batch or omit campaignId and use the generated requestId.
Request
Header Parameters
When set to true, tracking links in the email hide the destination inside an opaque, tamper-proof token instead of exposing it as a readable redirectUrl query parameter. This keeps destination URLs out of the message body where blocklist scanners can read them. Defaults to the account setting when the header is omitted.
- application/json
Body
required
- Array [
- ]
headers object
Additional headers to be added to the email.
Unsubscribe header for the email. This will override the default unsubscribe header generated by TinyEmail. It must support POST requests. For more information, visit email sender guidelines
metadata object
Optional metadata to associate with the send. The metadata is returned in every webhook event generated for the send.
Metadata is scoped to the campaignId. If campaignId is not provided, the generated requestId is used instead. Every recipient in the request shares this map; a recipient that needs its own values sets metadata on itself as well, and the two are merged with the recipient's keys winning.
Maximum 10 key/value pairs. Keys can be up to 64 characters and values up to 256 characters. Values must be flat strings, numbers, or booleans; numbers and booleans are converted to strings. Nested objects, arrays, and null values are not supported.
Keys are normalized to lowercase snake_case. For example, OrderID becomes order_id. Keys that normalize to the same name are rejected.
sender object
from object
replyTo object
recipients object
to object[]
attributes object
metadata object
Optional metadata for this recipient only, merged over the request-level metadata in every webhook event generated for this recipient. Where both define the same key, the recipient's value wins.
Use this when one request sends the same email to many people who each need a different identifier — one order_id per recipient, for example. A recipient that omits metadata receives the request-level map unchanged.
This is not attributes: attributes are merge tags rendered into the email body and are never echoed on webhooks, while metadata is never rendered into the email and is always echoed.
The same limits apply as to the request-level map, and the merged result must not exceed 10 keys — 10 in total, not 10 per level. At most 500 recipients in one request may carry their own metadata; recipients relying only on the request-level map are not counted.
when enabled, prevents from automatically tracking links in emails
Responses
- 202
- 400
- 401
- 405
Successful operation
- application/json
- Schema
- Example (from schema)
Schema
{
"requestId": "833c5151-5a98-4bad-a30f-7cc816352b7a",
"message": "SUCCESS"
}
Bad Request
- application/json
- Schema
- Example (from schema)
Schema
{
"message": "Some error message"
}
API key is missing or invalid
Method Not Allowed