Skip to main content

Using Transformations

This guide walks you through creating, testing, and managing transformations for your webhook connections.

Prerequisites

Before you begin, ensure you have:

  • A Hooklistener account on the Team or Enterprise plan
  • API access token (available in your account settings)
  • At least one Connection created
  • Basic JavaScript knowledge

Creating Your First Transformation

Step 1: Write Your Transformation Code

Start with a simple transformation that adds a timestamp to your webhook:

addHandler('transform', async (request, context) => {
// Add a processing timestamp
return {
...request,
body: {
...request.body,
processed_at: new Date().toISOString(),
processor: 'Hooklistener'
}
};
});

Step 2: Create the Transformation via API

Use the Transformations API to create your transformation:

curl -X POST https://api.hooklistener.com/api/v1/transformations \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transformation": {
"name": "Add Processing Timestamp",
"description": "Adds timestamp and processor info to webhooks",
"code": "addHandler('\''transform'\'', async (request, context) => { return { ...request, body: { ...request.body, processed_at: new Date().toISOString(), processor: '\''Hooklistener'\'' } }; });"
}
}'

The API will return:

{
"data": {
"id": "trans_abc123",
"name": "Add Processing Timestamp",
"description": "Adds timestamp and processor info to webhooks",
"organization_id": "org_xyz789",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}

Step 3: Attach to a Connection

Once created, attach the transformation to a Connection destination through the Connection management interface or API.

Testing Transformations

Using the Test Endpoint

Before deploying a transformation to production, test it with sample data:

curl -X POST https://api.hooklistener.com/api/v1/transformations/test \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transformation": {
"code": "addHandler('\''transform'\'', (req) => ({ ...req, body: { ...req.body, test: true } }));"
},
"request": {
"method": "POST",
"url": "https://example.com/webhook",
"headers": {
"content-type": "application/json"
},
"body": {
"event": "user.created",
"user_id": 12345
}
}
}'

Response:

{
"data": {
"result": {
"method": "POST",
"url": "https://example.com/webhook",
"headers": {
"content-type": "application/json"
},
"body": {
"event": "user.created",
"user_id": 12345,
"test": true
}
}
}
}

Debugging with Console Logs

Use console.log() to debug your transformation:

addHandler('transform', async (request, context) => {
console.log('Incoming request:', JSON.stringify(request));
console.log('Organization:', context.organizationId);

// Your transformation logic
const modified = {
...request,
body: {
...request.body,
debug: 'transformation applied'
}
};

console.log('Modified request:', JSON.stringify(modified));
return modified;
});

Console output appears in transformation logs for debugging.

Managing Transformations

List All Transformations

Get all transformations for your organization:

curl -X GET https://api.hooklistener.com/api/v1/transformations \
-H "Authorization: Bearer YOUR_API_TOKEN"

Get Transformation Details

Retrieve a specific transformation including its code:

curl -X GET https://api.hooklistener.com/api/v1/transformations/trans_abc123 \
-H "Authorization: Bearer YOUR_API_TOKEN"

Update a Transformation

Modify an existing transformation:

curl -X PATCH https://api.hooklistener.com/api/v1/transformations/trans_abc123 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transformation": {
"name": "Enhanced Timestamp Transform",
"code": "addHandler('\''transform'\'', async (request, context) => { /* new code */ });"
}
}'

Delete a Transformation

Remove a transformation (cannot be undone):

curl -X DELETE https://api.hooklistener.com/api/v1/transformations/trans_abc123 \
-H "Authorization: Bearer YOUR_API_TOKEN"

Working with Secrets

Setting Up Secrets

First, create secrets for your organization through the Secrets API:

curl -X POST https://api.hooklistener.com/api/v1/secrets \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"secret": {
"name": "SLACK_TOKEN",
"value": "xoxb-your-slack-token"
}
}'

Using Secrets in Transformations

Access secrets via process.env:

addHandler('transform', async (request, context) => {
// Access your organization's secrets
const slackToken = process.env.SLACK_TOKEN;
const apiKey = process.env.API_KEY;

if (!slackToken) {
console.log('Warning: SLACK_TOKEN not configured');
}

return {
...request,
headers: {
...request.headers,
'Authorization': `Bearer ${slackToken}`
}
};
});

Monitoring Transformation Execution

View Execution Logs

Get logs for a specific transformation:

curl -X GET https://api.hooklistener.com/api/v1/transformations/trans_abc123/logs \
-H "Authorization: Bearer YOUR_API_TOKEN"

Response includes:

{
"data": [
{
"id": "log_def456",
"transformation_id": "trans_abc123",
"status": "success",
"execution_time_ms": 45,
"memory_used_mb": 12,
"input_size_bytes": 1024,
"output_size_bytes": 1156,
"executed_at": "2024-01-15T11:00:00Z"
}
]
}

Get Detailed Log Entry

Retrieve full details including input/output:

curl -X GET https://api.hooklistener.com/api/v1/transformations/trans_abc123/logs/log_def456 \
-H "Authorization: Bearer YOUR_API_TOKEN"

Best Practices

1. Validate Input Data

Always validate incoming data:

addHandler('transform', async (request, context) => {
// Validate required fields
if (!request.body || typeof request.body !== 'object') {
console.log('Invalid body, returning original request');
return request;
}

if (!request.body.event_type) {
console.log('Missing event_type, skipping transformation');
return request;
}

// Proceed with transformation
return {
...request,
body: {
...request.body,
validated: true
}
};
});

2. Handle Errors Gracefully

Use try-catch blocks for robust error handling:

addHandler('transform', async (request, context) => {
try {
// Potentially error-prone transformation
const parsed = JSON.parse(request.body.data);
return {
...request,
body: {
...request.body,
parsed_data: parsed
}
};
} catch (error) {
console.log('Error parsing data:', error.message);
// Return original request on error
return request;
}
});

3. Optimize for Performance

Keep transformations lightweight:

addHandler('transform', async (request, context) => {
// Avoid expensive operations
// ❌ Don't do this:
// for (let i = 0; i < 1000000; i++) { /* ... */ }

// ✅ Do this instead:
const filtered = request.body.items
?.filter(item => item.active)
?.slice(0, 100); // Limit processing

return {
...request,
body: {
...request.body,
filtered_items: filtered || []
}
};
});

4. Use Meaningful Logging

Add contextual logging for debugging:

addHandler('transform', async (request, context) => {
const startTime = Date.now();

console.log(`Processing ${request.method} request for org ${context.organizationId}`);

// Transformation logic
const result = {
...request,
body: transformPayload(request.body)
};

const duration = Date.now() - startTime;
console.log(`Transformation completed in ${duration}ms`);

return result;
});

Common Issues and Solutions

Issue: "No handler registered"

Solution: Ensure you call addHandler('transform', ...) in your code.

Issue: Timeout errors

Solution: Optimize your code or break complex transformations into simpler ones.

Issue: Memory limit exceeded

Solution: Reduce data processing or filter large arrays before processing.

Issue: Secrets not available

Solution: Verify secrets are created for your organization and named correctly.

Next Steps

Now that you understand how to use transformations:

  1. Explore real-world examples for inspiration
  2. Review the API reference for complete endpoint documentation
  3. Set up monitoring for production transformations
  4. Learn about advanced patterns for complex use cases

Transformations are a powerful tool for webhook automation. Start simple, test thoroughly, and gradually build more complex transformations as needed.