Justt Webhook Transformations

This guide explains how to write and implement webhook transformations in the Justt system, allowing you to modify webhook behavior, payloads, and routing before delivery.

navigation

under the advanced ta,b enable the transformation tuggel

Once it anable you can write your transformation


How to Write a Transformation

Justt expects a Transformation to declare a function named handler. Justt will pass a WebhookObject to this function as its only argument, and expects the function to always return a WebhookObject.

WebhookObject Structure

WebhookObject is a JSON object containing 4 properties:

  • method - A string representing the HTTP method the webhook will be sent with. It is always "POST" by default, and its only valid values are "POST" or "PUT"
  • url - A string representing the endpoint's URL. It can be changed to any valid URL
  • payload - Contains the webhook's payload as a JSON object. It can be changed as needed
  • cancel - A Boolean which controls whether or not to cancel the dispatch of a webhook. This value defaults to false. Note that canceled messages appear as successful dispatches

Important: The Transformation will only work if the handler function returns the modified WebhookObject.

Basic Example

Suppose that sometimes, your customer wants to redirect webhooks to a custom URL instead of the endpoint's defined URL. They only want to do this redirect if a custom URL is present in the webhook payload. They can write a transformation like this:

function handler(webhook) {
    if (webhook.payload.customUrl) {
        webhook.url = webhook.payload.customUrl;
    }
    return webhook;
}

Great! The webhook is redirected to the custom URL if the customUrl property exists on the payload. Otherwise, it is sent to the endpoint's defined URL.


function handler(webhook) {
    // Transform Justt payload to match external system format
    const transformedPayload = {
        transaction_id: webhook.payload.chargeback_id,
        dispute_amount: webhook.payload.amount,
        currency_code: webhook.payload.currency,
        merchant_reference: webhook.payload.reference_id,
        status: mapJusttStatusToExternal(webhook.payload.status),
        created_at: webhook.payload.created_date,
        metadata: {
            justt_id: webhook.payload.id,
            original_event: webhook.payload.event_type
        }
    };
    
    webhook.payload = transformedPayload;
    return webhook;
}

function mapJusttStatusToExternal(justtStatus) {
    const statusMap = {
        'waiting_for_data': 'pending',
        'building_evidence': 'in_progress',
        'pending_psp_results': 'submitted',
        'not_represented': 'closed'
    };
    return statusMap[justtStatus] || 'unknown';
}

Best Practices

Error Handling

Always include error handling in your transformations:

function handler(webhook) {
    try {
        // Your transformation logic here
        if (webhook.payload && webhook.payload.amount) {
            webhook.payload.formatted_amount = `$${webhook.payload.amount.toFixed(2)}`;
        }
        
        return webhook;
    } catch (error) {
        // Log error and return original webhook to prevent delivery failure
        console.error('Transformation error:', error);
        return webhook;
    }
}

Validation

Validate webhook structure before transforming:

function handler(webhook) {
    // Validate required properties
    if (!webhook || !webhook.payload) {
        return webhook;
    }
    
    // Validate required payload fields
    if (!webhook.payload.chargeback_id || !webhook.payload.event_type) {
        console.warn('Missing required fields in webhook payload');
        return webhook;
    }
    
    // Proceed with transformation
    webhook.payload.processed_at = new Date().toISOString();
    return webhook;
}

Performance Considerations

Keep transformations lightweight and efficient:

function handler(webhook) {
    // Avoid complex operations or external API calls
    // Use simple object manipulation and built-in functions
    
    const payload = webhook.payload;
    
    // Quick property checks
    if (payload.priority_level === 'urgent') {
        webhook.url = 'https://api.example.com/urgent-endpoint';
    }
    
    return webhook;
}

Testing Transformations

Before deploying transformations to production:

  1. Test with sample webhook payloads
  2. Validate that the returned WebhookObject has the correct structure
  3. Check edge cases (null values, missing properties)
  4. Verify that transformations don't break downstream systems
  5. Monitor transformation performance and error rates

Common Pitfalls

  • Forgetting to return the webhook object - Always return the modified WebhookObject
  • Mutating the original object unsafely - Consider using object spread or deep cloning for complex transformations
  • Not handling edge cases - Check for null/undefined values before accessing nested properties
  • Complex logic - Keep transformations simple and focused on single responsibilities