Payload Transformations
Payload transformations let you reshape the URL, headers and body of a webhook before Mittr delivers it. Each endpoint can have its own transformation, written in JavaScript.
How it works
Section titled “How it works”- An event is routed to an endpoint with a transformation configured
- On each delivery attempt, Mittr calls your
transformfunction with the delivery as input - The returned values are used for that attempt’s request
- Mittr delivers the modified request
The transformation shapes what is sent, not what is stored: the event keeps the payload your producer sent, and every attempt (including retries and replays) transforms that original again.
Transformations run in a sandboxed environment with a 1-second timeout and a 128 MB memory limit.
Configure a transformation
Section titled “Configure a transformation”Set the transformation field when creating or updating an endpoint:
curl -X POST https://app.mittr.io/api/v1/endpoints \ -H "X-API-Key: mtr_your_key" \ -H "Content-Type: application/json" \ -d '{ "url": "https://api.example.com/orders", "eventTypes": ["order.*"], "transformation": "function transform(webhook) { return { payload: { orderId: webhook.payload.id, total: webhook.payload.amount / 100, currency: \"usd\" } }; }" }'Transformation API
Section titled “Transformation API”Your code must define a function named transform. It receives one argument describing the delivery and must return an object.
| Field | Type | Description |
|---|---|---|
webhook.payload | object | The event payload |
webhook.headers | object | The event’s delivery headers |
webhook.url | string | The endpoint URL |
webhook.method | string | Always POST |
The event type is not part of the input. If you route on it, include it in the payload.
Return object
Section titled “Return object”| Field | Type | Description |
|---|---|---|
payload | any JSON value | Replaces the body for this attempt |
url | string | Replaces the endpoint URL for this attempt. The usual delivery protections (SSRF blocking, IP allow/block lists) still apply |
headers | object | Replaces the event’s headers for this attempt. To add a header, return { ...webhook.headers, "X-New": "value" } |
cancel | boolean | true skips the delivery. The event is marked delivered and no request is sent |
All fields are optional: an omitted field keeps the input’s value. Deliveries are always sent as POST; a returned method is ignored. Signature headers are added after the transformation, over the transformed body.
Examples
Section titled “Examples”Reshape a payload
Section titled “Reshape a payload”function transform(webhook) { const p = webhook.payload; return { payload: { id: p.orderId, customer: p.customerEmail, items: p.lineItems.map(i => ({ sku: i.sku, qty: i.quantity })), total: p.totalCents / 100 } };}Add a header
Section titled “Add a header”function transform(webhook) { return { headers: { ...webhook.headers, "X-Tenant-ID": webhook.payload.tenantId } };}Conditionally cancel delivery
Section titled “Conditionally cancel delivery”// Only deliver high-value ordersfunction transform(webhook) { if (webhook.payload.amount < 10000) { return { cancel: true }; } return { payload: { ...webhook.payload, priority: "high" } };}Route to a different URL
Section titled “Route to a different URL”function transform(webhook) { const routes = { "order.created": "https://api.example.com/orders", "customer.created": "https://api.example.com/customers" }; // The event type has to travel in the payload: it is not an input field. return { url: routes[webhook.payload.type] || webhook.url };}Limits and failures
Section titled “Limits and failures”| Limit | Value |
|---|---|
| Execution timeout | 1 second |
| Memory limit | 128 MB |
If the script throws, times out, exceeds the memory limit, or returns something other than an object, the error is logged and the attempt is sent with the original, untransformed request.