Webhooks
Receive real-time notifications when events happen in your account.
Real-time Event Notifications
Webhooks allow you to build integrations that react to events as they happen, rather than polling the API for changes.
How Webhooks Work
- Register a webhook endpoint URL in your Portal or via the API
- Select the events you want to receive
- We send an HTTP POST request to your URL when events occur
- Your server validates the signature and processes the event
- Return a 2xx status code to acknowledge receipt
Retry Policy
Failed deliveries are retried up to 5 times with exponential backoff (5min, 30min, 2hr, 12hr, 24hr)
Timeout
Your endpoint must respond within 30 seconds or the delivery will be marked as failed
Ordering
Events are sent in order, but your handler should be idempotent in case of retries
Webhook Payload
All webhook payloads follow a consistent structure:
{
"id": "evt_abc123def456",
"type": "order.created",
"timestamp": "2026-04-18T14:30:00Z",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"orderNumber": "ORD-1713456789-ABCD12",
"status": "PENDING",
"totalAmount": 1520.00,
"currency": "USD",
"items": [
{
"productId": "prod_123",
"productName": "Premium CBD Oil",
"quantity": 5,
"unitPrice": 99.99
}
],
"shippingAddress": {
"firstName": "John",
"lastName": "Smith",
"city": "Austin",
"state": "TX",
"country": "US"
},
"createdAt": "2026-04-18T14:30:00Z"
},
"tenant": {
"id": "ten_abc123",
"name": "Acme Wellness"
}
}| Field | Type | Description |
|---|---|---|
| id | string | Unique event identifier |
| type | string | Event type (e.g., order.created) |
| timestamp | datetime | When the event occurred (ISO 8601) |
| data | object | Event-specific payload data |
| tenant | object | Tenant information (id and name) |
Signature Verification
All webhook payloads are signed using HMAC-SHA256. Always verify signatures to ensure requests are from Regen Therapy.
Security Requirement
Never process webhook payloads without verifying the signature first. This prevents attackers from sending fake events to your endpoint.
Signature Header
The signature is sent in the X-Regen-Signature header:
t=1713451800,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bdt= Unix timestamp when the signature was generatedv1= HMAC-SHA256 signature
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const timestamp = signature.split(',')[0].split('=')[1];
const receivedSig = signature.split(',')[1].split('=')[1];
const signedPayload = `${timestamp}.${payload}`;
const expectedSig = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(receivedSig),
Buffer.from(expectedSig)
);
}
// Express.js example
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-regen-signature'];
const payload = req.body.toString();
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
switch (event.type) {
case 'order.created':
handleOrderCreated(event.data);
break;
case 'order.shipped':
handleOrderShipped(event.data);
break;
// ... handle other events
}
res.status(200).send('OK');
});Events Catalog
Complete list of webhook events you can subscribe to:
Orders Events
| Event | Description |
|---|---|
order.created | A new order has been placed |
order.updated | An order has been modified |
order.confirmed | Order has been confirmed (payment received) |
order.processing | Order is being prepared for shipment |
order.shipped | Order has been shipped |
order.delivered | Order has been delivered |
order.cancelled | Order has been cancelled |
order.refunded | Order has been refunded |
Inventory Events
| Event | Description |
|---|---|
inventory.adjusted | Inventory quantity was manually adjusted |
inventory.low_stock | Product fell below reorder point |
inventory.out_of_stock | Product is out of stock |
inventory.restocked | Product was restocked |
Commissions Events
| Event | Description |
|---|---|
commission.accrued | Commission was earned on an order |
commission.adjusted | Commission amount was adjusted |
commission.payout.scheduled | Payout has been scheduled |
commission.payout.completed | Payout has been sent |
commission.payout.failed | Payout failed to process |
Shipping Events
| Event | Description |
|---|---|
shipment.created | Shipment has been created |
shipment.picked_up | Shipment was picked up by carrier |
shipment.in_transit | Shipment is in transit |
shipment.delivered | Shipment was delivered |
shipment.exception | Delivery exception occurred |
Returns Events
| Event | Description |
|---|---|
return.requested | Return has been requested |
return.approved | Return has been approved |
return.received | Returned items received |
return.completed | Return has been completed |
Tenant Events
| Event | Description |
|---|---|
tenant.created | New tenant account created |
tenant.activated | Tenant account activated |
tenant.suspended | Tenant account suspended |
tenant.updated | Tenant settings updated |
Best Practices
Return 200 Quickly
Acknowledge receipt immediately and process events asynchronously. Use a queue for heavy processing.
Handle Duplicates
Use the event ID to detect and handle duplicate deliveries. Your handlers should be idempotent.
Use HTTPS
Always use HTTPS endpoints. We do not send webhooks to HTTP URLs.
Monitor Failures
Set up monitoring for webhook failures. Check the delivery logs in your portal regularly.
Related Resources