Custom payload configuration
You can configure exactly which fields are included in your webhook payload, on a per-alias basis. Strip what you don't need, keep what you do.
There are two separate mechanisms, and they are gated differently:
| What it does | Plan | |
|---|---|---|
| Field toggles | Switch whole blocks of the standard payload on or off — HTML body, text body, envelope, attachments, Markdown, reply parsing | Every plan, including Free |
| Payload templates | Define your own JSON shape with {{path}} placeholders, so the payload matches your endpoint's schema exactly |
Business+ |
Field toggles reshape our payload. Templates replace it.
Why customise your payload
Minimise PII exposure
Every field you forward is a field that could end up in logs, error reports, or third-party systems. If your pipeline only needs the sender address and subject line to route a support ticket, there is no reason to forward the full email body.
Stripping unnecessary fields reduces your data footprint and simplifies GDPR compliance — you can't leak data you never received.
Reduce overhead
Smaller payloads mean faster webhook delivery, lower bandwidth, and less processing on your end. At high volumes the difference adds up: a metadata-only payload can be an order of magnitude smaller than one carrying the full HTML body and inline attachments.
Match rigid endpoints
Some webhook receivers — Zapier, Make, or internal microservices — expect a specific schema. If the endpoint has no flexibility for extra fields, a trimmed payload avoids parsing errors and simplifies your integration.
Compliance and audit
Regulated industries often require data minimisation by design. Custom payloads let you enforce this at the source: forward only the metadata you need, and leave everything else behind.
Field toggles — available on every plan
In your alias settings, switch these blocks on or off. All of them work on every plan, Free included.
| Toggle | What it controls | Default |
|---|---|---|
includeText |
message.content.text — the plain-text body |
On |
includeHtml |
message.content.html — the raw HTML body |
On |
allowAttachments |
message.attachments[] — file metadata plus inline content or a downloadUrl |
On |
includeEnvelope |
The whole envelope block — headers, allRecipients, returnPath, processed |
Off |
includeMarkdown |
message.content.markdown — HTML converted to clean Markdown |
Off (and Maker+) |
includeReplyParsing |
message.content.reply — the new text of a reply, with the quoted thread stripped |
Off (and Maker+) |
Two things to know about the defaults:
includeEnvelopeis off by default, and turning it off does not remove the envelope entirely — it is reduced to{ messageId }.messageIdalways survives, because it is the key you pass toDELETE /api/v1/emails/{messageId}and the value you deduplicate on.includeMarkdownandincludeReplyParsingare off by default and gated at Maker+. Turning the toggle on is necessary but not sufficient — on Free the field is stripped regardless.
Blocks the toggles do not control: message.sender, message.recipient (including tag), message.subject, message.date, message.content.links, classification, spam, integrity, security, domainId and aliasId. These are governed by your plan, not by a per-alias switch. To drop them from the payload, use a template.
Payload templates — Business+
A template is a JSON object you define, in which any string of the form {{path}} is replaced with a value from the email. The rendered object becomes the webhook body — nothing else is sent.
{
"ticket": {
"from": "{{message.sender.email}}",
"queue": "{{message.recipient.tag}}",
"title": "{{message.subject}}",
"body": "{{message.content.text}}"
},
"received_at": "{{envelope.processed.timestamp}}",
"source": "email"
}
Two kinds of reference
- Bare reference — the string is exactly
"{{path}}"and nothing else. The value keeps its original type:"{{spam.score}}"renders as the number-0.99, not the string"-0.99", and"{{message.attachments}}"renders as a real JSON array. - Interpolation — a
{{path}}embedded in a longer string, e.g."[{{classification.type}}] {{message.subject}}". The result is always a string.
Values that contain no {{ at all are passed through as literals, so you can hard-code constants like "source": "email" above.
Missing values
- A bare reference that resolves to nothing has its key omitted from the output entirely — you get no key, rather than a
null. - An interpolated reference that resolves to nothing becomes an empty string.
Design your endpoint to tolerate a missing key: a plan-gated field (spam.score on Free) or an unset one (message.recipient.tag on untagged mail) will simply not appear.
The system.* context
Beyond the email itself, templates can address a system object describing the delivery. These fields exist only inside templates — they are not part of the standard payload.
| Path | Type | What it is |
|---|---|---|
system.event |
string | The event that triggered the delivery |
system.timestamp |
string | Delivery time, ISO 8601 |
system.timestampUnix |
number | The same instant as a Unix timestamp |
system.alias.email |
string | The alias address that matched |
system.alias.name |
string | The alias's display name |
system.domain.name |
string | The domain that received the email |
system.webhook.name |
string | The webhook's display name |
system.webhook.id |
string | The webhook's ID |
These are what you reach for when your endpoint needs to know which of your aliases or webhooks fired, without inferring it from the recipient address:
{
"event": "{{system.event}}",
"at": "{{system.timestampUnix}}",
"routed_by": "{{system.alias.email}}",
"webhook": "{{system.webhook.id}}",
"subject": "{{message.subject}}"
}
Addressable paths
Templates are validated when you save them: an unknown path is a hard error, and a plan-gated path is a warning. The addressable paths are:
message — message.sender.email, message.sender.name, message.recipient.email, message.recipient.name, message.recipient.tag, message.subject, message.date, message.content.text, message.content.html, message.content.links, message.attachments
· Maker+: message.content.markdown, message.content.reply, message.content.links.anchorText, message.content.links.source, message.attachments.metadata
· Business+: message.attachments.virusScan
envelope — envelope.messageId, envelope.xMailer, envelope.xOriginalTo, envelope.returnPath, envelope.allRecipients, envelope.headers, envelope.processed.timestamp, envelope.processed.domain, envelope.processed.alias, envelope.processed.originalSize
spam (Maker+) — spam.score, spam.engine, spam.symbols, spam.authentication, spam.report. There is deliberately no spam.isSpam — the cut-off is your policy, not ours, so compare spam.score against your own threshold.
classification — classification.type, classification.confidence, classification.signals. All three are available on every plan.
integrity (Maker+) — integrity.contentHash, integrity.rawEmailHash
security (Business+) — security.virusScan
routing — domainId, aliasId
system — as listed above.
You can address a parent path to pull the whole object: "{{spam.authentication}}" returns the full DKIM/SPF/DMARC object as a bare reference.
Example: metadata-only payload (template)
A support ticketing system that only needs routing information. The template:
{
"message": {
"sender": {
"name": "{{message.sender.name}}",
"email": "{{message.sender.email}}"
},
"recipient": {
"email": "{{message.recipient.email}}",
"tag": "{{message.recipient.tag}}"
},
"subject": "{{message.subject}}"
}
}
…and what your endpoint receives:
{
"message": {
"sender": {
"name": "Alice Martin",
"email": "alice@acme.com"
},
"recipient": {
"email": "support+billing@yourcompany.com",
"tag": "billing"
},
"subject": "Order #1042 — delivery question"
}
}
No email body, no attachments, no HTML. Just enough to create a ticket and notify the right team.
Because this email was addressed to support+billing@, recipient.tag arrives as "billing" — enough to drop the ticket straight into the right queue without parsing the address or reading the body. Plus-addressed mail is still delivered to the webhook on your support@ alias, so a tag costs you nothing to set up.
Example: attachments only (template)
A document processing pipeline that extracts invoices from emails. "{{message.attachments}}" is a bare reference, so the array arrives as a real JSON array rather than a stringified one:
{
"message": {
"sender": { "email": "{{message.sender.email}}" },
"subject": "{{message.subject}}",
"attachments": "{{message.attachments}}"
}
}
Delivered as:
{
"message": {
"sender": {
"email": "billing@vendor.com"
},
"subject": "Invoice #4821",
"attachments": [
{
"filename": "invoice-4821.pdf",
"contentType": "application/pdf",
"size": 48210,
"downloadUrl": "https://app.emailconnect.eu/attachments/.../download"
}
]
}
}
The email body is irrelevant — only the PDF matters.
Availability
| Plan | |
|---|---|
Field toggles (includeText, includeHtml, allowAttachments, includeEnvelope, includeMarkdown, includeReplyParsing) |
All plans, including Free |
Payload templates ({{path}} syntax and the visual payload builder) |
Business and Platform |
Two caveats on the toggles, since they trip people up:
- Turning a toggle on does not defeat a plan gate.
includeMarkdownandincludeReplyParsingstill require Maker+; on Free the field is stripped even with the toggle enabled. - The defaults are not "everything on".
includeEnvelope,includeMarkdownandincludeReplyParsingall start off — if you expectedenvelope.headersormessage.content.markdownand they are not in your payload, that is why.
Related topics
- Alias options explained — all alias configuration options
- Webhook payload reference — full payload field documentation
- Data retention — how long data is stored