Transforms
Transforms modify webhook payloads using JavaScript before delivery.
Overview
Transforms modify webhook payloads before delivery using one of four supported languages. Use them to:
- Reshape data to match your application's format
- Extract specific fields
- Add computed values
- Convert between data formats (JSON, XML, text)
- Mask sensitive data
Transform Types
Hookbase supports four transform engines:
| Type | Language | Best For |
|---|---|---|
jsonata | JSONata | Declarative JSON-to-JSON mapping (default) |
javascript | JavaScript | Complex logic, conditionals, string manipulation |
liquid | Liquid | Template-based output, generating text/HTML |
xslt | XSLT | XML-to-XML or XML-to-JSON transformations |
Creating a Transform
Fields
| Field | Description |
|---|---|
name | Human-readable name |
code | Transform code |
type | Transform type: jsonata (default), javascript, liquid, xslt |
inputFormat | Expected input format: json (default), xml, text |
outputFormat | Output format: json (default), xml, text |
JSONata (Default)
JSONata is a lightweight query and transformation language for JSON. It's the recommended approach for straightforward mappings.
{
"eventType": action,
"repository": repository.full_name,
"sender": sender.login,
"timestamp": $now()
}See the JSONata documentation for the full expression reference.
JavaScript
JavaScript transforms receive the payload as an argument and return the transformed result.
function transform(payload) {
return {
// Your transformed data
};
}Liquid
Liquid templates are useful for generating formatted text or HTML output.
New event from {{ payload.repository.full_name }}
Action: {{ payload.action }}
By: {{ payload.sender.login }}XSLT
XSLT transforms are designed for XML payloads. Set inputFormat: "xml" when using XSLT.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<event>
<type><xsl:value-of select="/webhook/action"/></type>
<source><xsl:value-of select="/webhook/repository/name"/></source>
</event>
</xsl:template>
</xsl:stylesheet>Code Validation
When creating or updating a transform, Hookbase validates the code:
- JSONata: Parses the expression and reports syntax errors
- JavaScript: Checks for syntax errors and unsafe operations (no
eval,Function,require) - Liquid: Validates template syntax
- XSLT: Validates XML and stylesheet structure
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: "hookbase",
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
# JavaScript transform
curl -X POST https://api.hookbase.app/api/transforms \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "GitHub to Slack",
"type": "javascript",
"code": "function transform(payload) { return { text: payload.action }; }"
}'
# JSONata transform (default type)
curl -X POST https://api.hookbase.app/api/transforms \
-H "Authorization: Bearer whr_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Extract Fields",
"type": "jsonata",
"code": "{ \"event\": action, \"repo\": repository.full_name }"
}'List Transforms
curl https://api.hookbase.app/api/transforms \
-H "Authorization: Bearer whr_your_api_key"Update Transform
curl -X PATCH https://api.hookbase.app/api/transforms/{transformId} \
-H "Authorization: Bearer whr_your_api_key" \
-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.hookbase.app/api/transforms/{transformId} \
-H "Authorization: Bearer whr_your_api_key"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;
}
}