Transforms
Transforms modify webhook payloads using JavaScript before delivery.
Overview
Transforms are JavaScript functions that receive the original webhook payload and return a modified version. Use them to:
- Reshape data to match your application's format
- Extract specific fields
- Add computed values
- Convert between data formats
- Mask sensitive data
Creating a Transform
Required Fields
| Field | Description |
|---|---|
name | Human-readable name |
code | JavaScript transform function |
The Transform Function
Your transform code must export a function that:
- Receives the original
payloadobject - Returns the transformed payload
function transform(payload) {
return {
// Your transformed data
};
}Examples
Extract Specific Fields
function transform(payload) {
return {
eventType: payload.action,
repository: payload.repository?.full_name,
sender: payload.sender?.login,
timestamp: new Date().toISOString()
};
}Format for Slack
function transform(payload) {
return {
text: `New event from ${payload.repository?.full_name}`,
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `*${payload.action}* by ${payload.sender?.login}`
}
}
]
};
}Add Metadata
function transform(payload) {
return {
...payload,
_meta: {
processedAt: new Date().toISOString(),
source: "webhookrelay",
version: "1.0"
}
};
}Filter and Reshape Array
function transform(payload) {
const items = payload.items || [];
return {
count: items.length,
items: items
.filter(item => item.status === "active")
.map(item => ({
id: item.id,
name: item.name
}))
};
}Mask Sensitive Data
function transform(payload) {
return {
...payload,
email: payload.email?.replace(/(.{2}).*(@.*)/, "$1***$2"),
creditCard: payload.creditCard ? "****" + payload.creditCard.slice(-4) : null
};
}Testing Transforms
Use the Testing page to verify your transform works correctly:
- Navigate to Testing in the sidebar
- Select your source and route
- Enter a sample payload
- Click Send Test
- View the transformed output
Or use the Transforms page directly:
- Navigate to Transforms in the sidebar
- Click on a transform to edit
- Enter a sample payload in the test section
- Click Test Transform
- View the result
API Usage
Create Transform
curl -X POST https://api.webhookrelay.com/api/organizations/{orgId}/transforms \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "GitHub to Slack",
"code": "function transform(payload) { return { text: payload.action }; }"
}'List Transforms
curl https://api.webhookrelay.com/api/organizations/{orgId}/transforms \
-H "Authorization: Bearer YOUR_TOKEN"Update Transform
curl -X PATCH https://api.webhookrelay.com/api/organizations/{orgId}/transforms/{transformId} \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "function transform(payload) { return { text: payload.action, repo: payload.repository.name }; }"
}'Delete Transform
curl -X DELETE https://api.webhookrelay.com/api/organizations/{orgId}/transforms/{transformId} \
-H "Authorization: Bearer YOUR_TOKEN"Best Practices
Keep it simple: Transforms run on every webhook; keep code efficient
Handle missing data: Use optional chaining (
?.) and default valuesTest thoroughly: Test with various payload shapes before deploying
Don't make external calls: Transforms should be pure functions; no HTTP requests
Return valid JSON: Ensure your transform returns serializable data
Version your transforms: Include version info in names or metadata
Limitations
- Execution time: Transforms must complete within 50ms
- Memory: Limited to 128KB of memory
- No external access: Cannot make HTTP requests or access external resources
- No persistent state: Each execution is independent
Error Handling
If a transform fails:
- The original payload is used (no transformation)
- An error is logged
- Delivery continues to destinations
To debug transform errors:
- Check the Event Debugger for error messages
- Test with the exact payload that caused the error
- Add defensive coding (null checks, try/catch)
function transform(payload) {
try {
return {
data: payload.nested?.deeply?.value || "default"
};
} catch (error) {
// Return original on error
return payload;
}
}