Resolve Webhooks API
Webhooks allow you to receive real-time notifications about events in your Resolve account. When an event occurs, Resolve sends an HTTP POST request to your configured webhook endpoint with details about the event. ## Webhook Event Structure All webhook events follow a consistent structure: ```json { "id": "4ecbe7f9e8c1c9092c000027", "object": "invoice", "type": "invoice.created", "occurred_at": "2021-05-20T09:23:53+00:00", "data": { "id": "RH5fF9aeQ" } } ``` The `data.id` field contains the ID of the object related to the event. You can use this ID to fetch the full object via the corresponding API endpoint. ## Supported Event Types ### Invoice Events - **`invoice.created`** - Triggered when a new invoice record is created. - **`invoice.balance_updated`** - Triggered when the outstanding balance of an invoice changes (for example, when a payment or credit note is applied). ### Customer Events - **`customer.created`** - Triggered when a new customer record is created. - **`customer.status_updated`** - Triggered when a customer's status changes (for example, when a customer is submitted for a credit check or enrolled). - **`customer.line_amount_updated`** - Triggered when a customer's credit limit amount is updated. - **`customer.advance_rate_updated`** - Triggered when a customer's advance rate percentage is updated. - **`customer.credit_decision_created`** - Triggered when a new credit decision is created for a customer. ### Order Events - **`order.created`** - Triggered when a new order record is created. - **`order.updated`** - Triggered when an order is updated. ### Payment Events - **`payment.created`** - Triggered when a new payment record is created. - **`payment.status_changed`** - Triggered when the status of a payment changes. ### Payout Events - **`payout.created`** - Triggered when a new payout record is created. - **`payout.status_changed`** - Triggered when the status of a payout changes (for example, pending, in transit, paid). ## Verifying Webhook Signatures To ensure webhook requests are genuine and coming from Resolve, you should verify the webhook signature. Resolve includes a signature in the `x-webhook-signature` header of each webhook request. ### JavaScript Example ```javascript const crypto = require('crypto'); function verifyWebhookSignature(payload, signature, secret) { const computedSignature = crypto .createHmac('sha256', secret) .update(JSON.stringify(payload)) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(computedSignature) ); } // Usage in Express.js app.post('/webhooks', express.json(), (req, res) => { const signature = req.headers['x-webhook-signature']; const isValid = verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET); if (!isValid) { return res.status(401).send('Invalid signature'); } // Process the webhook event const event = req.body; console.log('Received event:', event.type); res.status(200).send('Webhook received'); }); ``` ## Retry Policy If your webhook endpoint doesn't respond successfully (non-2xx status code or connection error), Resolve will automatically retry sending the webhook notification. The retry schedule follows an exponential backoff pattern: - **1st retry**: 30 seconds after the initial attempt - **2nd retry**: 90 seconds after the 1st retry - **3rd retry**: 270 seconds (4.5 minutes) after the 2nd retry - **4th retry**: 810 seconds (13.5 minutes) after the 3rd retry - **5th retry**: 2430 seconds (40.5 minutes) after the 4th retry After the 5th unsuccessful attempt, Resolve will stop retrying and the webhook delivery will be marked as failed. ## Best Practices - Always verify webhook signatures to ensure the request is from Resolve - Respond with a `200` status code as quickly as possible to acknowledge receipt - Process webhook events asynchronously if they require time-intensive operations - Implement idempotency on your endpoint to handle duplicate events from retries - Use the event `id` to track which events you've already processed