API DOCUMENTATION
    Try Unleashed Now Sandbox

    Set up Webhooks

    Unleashed Webhooks API Documentataion


    Table of Contents

    1. Introduction
    2. Getting Started
    3. Webhook Concepts
    4. Available Events
    5. Setting Up Webhooks
    6. Webhook Event Structure
    7. Verifying Webhook Signatures
    8. Managing Subscriptions
    9. Monitoring Deliveries
    10. Best Practices
    11. Error Handling
    12. Troubleshooting
    13. Complete Example
    14. Send us your feedback

    1. Introduction Subscribe to Webhooks to receive real-time notifications when specific events occur in your Unleashed account, such as new product creation or customer updates. This provides a more efficient way to keep your integrated applications synchronized with Unleashed data compared to continuously polling the API.

    2. Getting Started

    What you will need

    • An active Unleashed account (trial accounts can also access the Webhooks API)
    • API ID and Key from your Unleashed account
    • A publicly accessible HTTPS endpoint with a valid SSL certificate
    • Maximum of 5 webhook subscriptions per account

    Authentication

    Webhook API requests use the same authentication as the standard Unleashed API. Each request must include these HTTP headers:
    Content-Type: application/json
    Accept: application/json
    api-auth-id: YOUR_API_ID
    api-auth-signature: CALCULATED_SIGNATURE
    client-type: your_company/your_app
    Important: The Accept: application/json header is required to receive API responses. Missing this header is a common cause of request failures.

    3. Webhook Concepts
    • Webhook Subscription: Configuration that defines which events to monitor and where to send notifications
    • Webhook Event: The data payload sent to your endpoint when a subscribed event occurs
    • Event Delivery: A record of each delivery attempt, including success/failure status
    • Signature Verification: Security mechanism to verify that webhook events originated from Unleashed

    4. Available Events
    Object Event Types Description
    Customer created, updated, deleted Customer record changes
    Product created, updated, deleted Product record changes
    Purchase Order created, updated, deleted Purchase Order changes
    Sales Order created, updated, deleted, completed Sales Order changes
    Sales Shipment created, deleted Shipment record changes
    Credit Note created, deleted Credit Note changes
    Supplier Return created, updated, deleted Supplier Return changes
    Note: Not all events are available for every object. Check the specific object documentation for available events.

    5. Setting Up Webhooks

    Step 1: Create a Webhook Subscription

    POST /webhooks/subscriptions

    Request Example:
    { 
        "description": "Monitor customer and product changes", 
        "notificationUrl": "https://your-domain.com/webhook", 
        "eventTypes": [ "customer.created", "customer.updated", "product.created" ] 
    }
    Response Example:
    { 
        "subscriptionId": "123e4567-e89b-12d3-a456-426614174000",
        "description": "Monitor customer and product changes", 
        "notificationUrl": "https://your-domain.com/webhook", 
        "active": true, 
        "eventTypes": [ "customer.created", "customer.updated", "product.created" ], 
        "createdOn": "2025-06-23T10:30:00Z", 
        "signatureKey": "base64_encoded_key_save_this_value" 
    }
    ⚠️ Important: Save the signatureKey from the response - this is required for verifying webhook events and is only shown once.

    Step 2: Implement Your Webhook Endpoint

    Your endpoint must:
    • Accept POST requests
    • Respond with a 2XX status code quickly
    • Verify the webhook signature for security
    Example Implementation:
    app.post('/webhook', (req, res) => { 
        const signature = req.headers['x-unleashed-signature']; 
        const timestamp = req.headers['x-unleashed-timestamp']; 
        
        // Verify signature (see verification section below) 
        if (verifySignature(signature, timestamp, req.body)) { 
            // Respond quickly 
            res.status(200).send('OK'); 
            // Process webhook asynchronously 
            processWebhookEvent(req.body); 
        } else { 
            res.status(401).send('Unauthorized'); 
        } 
    });

    6. Webhook Event Structure When an event occurs, Unleashed sends a POST request to your endpoint:
    { 
        "subscriptionId": "123e4567-e89b-12d3-a456-426614174000", 
        "eventNotificationId": "987fcdeb-51a2-43d1-b789-123456789000", 
        "eventType": "customer.created", 
        "createdOn": "2025-06-23T10:30:00Z", 
        "data": "{\"customerGuid\":\"456e7890-e12b-34c5-d678-901234567890\"}" 
    }

    Event Data Objects

    Customer Events:

    {"customerGuid": "456e7890-e12b-34c5-d678-901234567890"}

    Product Events:

    {"productGuid": "789e0123-e45f-67g8-h901-234567890123"}

    Sales Order Events:

    {"salesOrderGuid": "012e3456-e78f-90g1-h234-567890123456"}

    7. Verifying Webhook Signatures Always verify webhook signatures to ensure events originated from Unleashed:
    function verifySignature(signature, timestamp, body, signatureKey) {
        const crypto = require('crypto'); 
    
        // Check timestamp (reject if older than 5 minutes) 
        const currentTime = Math.floor(Date.now() / 1000); 
        
        if (currentTime - parseInt(timestamp) > 300) { 
            return false; 
        } 
        
        // Create signed payload: timestamp + body 
        const signedPayload = `${timestamp}.${JSON.stringify(body)}`; 
        // Calculate expected signature 
        const expectedSignature = crypto
            .createHmac('sha256', signatureKey)
            .update(signedPayload)
            .digest('base64'); 
        
        // Secure comparison 
        return crypto.timingSafeEqual( Buffer.from(signature, 'base64'), Buffer.from(expectedSignature, 'base64') ); 
    }

    8. Managing Subscriptions

    List Subscriptions

    GET /webhooks/subscriptions

    Update Subscription

    PUT /webhooks/subscriptions/{subscriptionId}

    {
        "description": "Updated description", 
        "active": true, 
        "eventTypes": ["customer.created", "customer.updated"] 
    }

    Delete Subscription

    DELETE /webhooks/subscriptions/{subscriptionId}


    9. Monitoring Deliveries

    List Delivery Attempts

    GET /webhooks/subscriptions/{subscriptionId}/deliveries

    Query Parameters:
    • pageSize: Items per page (default: 200, max: 1000)
    • successful: Filter by success status (true/false)

    Get Delivery Details

    GET /webhooks/deliveries/{deliveryId}


    10. Best Practices

    Handle Duplicate Events

    Webhooks may be delivered multiple times. Use the eventNotificationId to detect duplicates:
    const processedEvents = new Set(); 
    function handleWebhook(event) { 
        if (processedEvents.has(event.eventNotificationId)) { 
            return; // Already processed 
        } 
        
        processedEvents.add(event.eventNotificationId);
        processEvent(event);
    }

    Handle Failed Deliveries

    • Unleashed retries failed deliveries for 72 hours with exponential backoff
    • Webhooks are disabled after repeated failures
    • Use the update subscription API to reactivate disabled webhooks
    • Monitor delivery status regularly

    Respond Quickly

    • Return a 2XX status code as soon as possible
    • Process webhook data asynchronously to avoid timeouts
    • Webhook requests have a short timeout period

    IP Whitelisting

    For additional security, whitelist these Unleashed IP addresses:
    • 13.236.30.20
    • 3.105.186.32
    • 3.104.150.228

    11. Error Handling Common HTTP status codes returned by the Webhooks API:
    Status Code Description
    200 OK Request successful
    400 Bad Request Invalid request format or parameters
    401 Unauthorized Invalid API credentials or signature
    403 Forbidden Access denied
    404 Not Found Subscription not found
    500 Internal Server Error Server error

    12. Troubleshooting

    Webhook Not Triggered

    • Verify your endpoint is publicly accessible via HTTPS
    • Check SSL certificate validity
    • Confirm subscription is active and includes the correct event types

    Signature Verification Fails

    • Ensure you saved the signature key from subscription creation
    • Verify timestamp parsing (Unix timestamp in seconds)
    • Check payload format: {timestamp}.{body}

    API Requests Failing

    • Include the Accept: application/json header in all requests
    • Verify API credentials and signature generation
    • Check that all required headers are

    13. Complete Example: Webhook Handler
    const express = require('express'); 
    const crypto = require('crypto'); 
    const app = express(); 
    
    app.use(express.json()); 
    const SIGNATURE_KEY = 'your_signature_key_from_subscription'; 
    const processedEvents = new Set(); 
    
    app.post('/webhook', (req, res) => { 
        try { 
            const signature = req.headers['x-unleashed-signature']; 
            const timestamp = req.headers['x-unleashed-timestamp']; 
            
            // Verify signature 
            if (!verifySignature(signature, timestamp, req.body, SIGNATURE_KEY)) { 
                return res.status(401).send('Unauthorized'); 
            } 
            
            // Respond immediately 
            res.status(200).send('OK'); 
            
            // Check for duplicates 
            if (processedEvents.has(req.body.eventNotificationId)) { 
                return; 
            } 
            
            processedEvents.add(req.body.eventNotificationId); 
            
            // Process event asynchronously 
            processEvent(req.body); 
        } catch (error) { 
            console.error('Webhook error:', error); 
            res.status(500).send('Internal Server Error'); 
        } 
    }); 
    
    async function processEvent(event) { 
        console.log(`Processing ${event.eventType} event`); 
        const data = JSON.parse(event.data); 
        switch (event.eventType) { 
            case 'customer.created': 
                await handleCustomerCreated(data.customerGuid); 
                break; 
            
            case 'product.updated': 
                await handleProductUpdated(data.productGuid); 
                break; 
            
            // Handle other event types... 
        } 
    } 
    
    function verifySignature(signature, timestamp, body, key) { 
        const currentTime = Math.floor(Date.now() / 1000); 
        if (currentTime - parseInt(timestamp) > 300) 
            return false; 
        
        const payload = `${timestamp}.${JSON.stringify(body)}`; 
        const expected = crypto.createHmac('sha256', key)
            .update(payload)
            .digest('base64');
    
        return crypto.timingSafeEqual(
            Buffer.from(signature, 'base64'),
            Buffer.from(expected, 'base64')
        ); 
    } 
    
    app.listen(3000, () => { 
        console.log('Webhook server running on port 3000');
    });

    14. Send us your feedback If you have an idea for a new webhook, please click on the link below and send us your feedback.

    Product Feedback

    Use the API Sandbox to see how the object is rendered in JSON or XML.

    Note: An Unleashed account is required before you can use the API Sandbox.

    Trial accounts are also allowed to connect to the API.
    You can register a new account here: Register.