Receive real-time notifications when events happen in your Expereon account.
Instead of polling the API for changes, configure webhook endpoints to receive HTTP POST requests whenever invoices, payments, or other resources change state.
Create a webhook endpoint via the API or the Expereon dashboard:
curl -X POST "https://api.expereon.com/api/v1/settings/webhooks" \
-H "X-API-Key: exp_prod_xxxxxxxxxxxx" \
-H "X-API-Secret: your-secret-key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/expereon",
"events": ["invoice.created", "invoice.approved", "payment.settled"],
"authMethod": "SIGNING_SECRET",
"signingSecret": "whsec_your_secret_here"
}'
2xx status within 10 seconds| Event | Description |
|---|---|
invoice.created | A new invoice was created |
invoice.submitted | Invoice submitted to buyer for review |
invoice.approved | Buyer approved the invoice |
invoice.disputed | Buyer raised a dispute on the invoice |
invoice.cancelled | Invoice was cancelled by either party |
invoice.settled | Invoice payment has been completed |
payment.settled | A payment was successfully processed |
payment.failed | A payment attempt failed |
connection.created | New business connection established |
connection.suspended | A connection was suspended |
withdrawal.approved | Withdrawal request was approved |
withdrawal.rejected | Withdrawal request was rejected |
refund.approved | Refund request was approved |
refund.rejected | Refund request was rejected |
Every webhook delivery is a JSON POST request with this structure:
{
"id": "evt_abc123def456",
"type": "invoice.approved",
"timestamp": "2024-03-15T14:30:00Z",
"data": {
"invoiceId": "inv_xyz789",
"invoiceNumber": "INV-2024-001",
"status": "APPROVED",
"amount": "1500.00",
"currency": "USD",
"buyerOrganizationId": "org_buyer_1",
"sellerOrganizationId": "org_seller_1"
}
}
Every webhook request includes an X-Webhook-Signature header containing an
HMAC-SHA256 signature of the request body using your signing secret.
// Node.js example
const crypto = require('crypto');
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
app.post('/webhooks/expereon', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhook(req.rawBody, signature, 'whsec_your_secret');
if (!isValid) {
return res.status(401).send('Invalid signature');
}
const event = req.body;
switch (event.type) {
case 'invoice.approved':
// Handle approved invoice
break;
case 'payment.settled':
// Handle settled payment
break;
}
res.status(200).send('OK');
});
If your endpoint fails to respond with 2xx, Expereon retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 12 hours |
After 5 failed attempts, the delivery is marked as failed. You can view failed deliveries and manually retry them from the dashboard.
Use the test endpoint to send a sample event to your webhook:
curl -X POST "https://api.expereon.com/api/v1/settings/webhooks/{webhookId}/test" \
-H "X-API-Key: exp_prod_xxxxxxxxxxxx" \
-H "X-API-Secret: your-secret-key"
This sends a test event with "type": "webhook.test" to your endpoint.
Use this to verify your handler and signature validation work correctly.
200 OK immediately, then process the event asynchronouslyid for idempotency; the same event may be delivered more than onceX-Webhook-Signature before processing