Webhooks
Webhooks allow you to receive real-time notifications when events occur in MediLoop. Instead of polling the API, webhooks push data to your server as events happen.
Setting Up Webhooks
- Go to the Developer Portal
- Navigate to Webhooks settings
- Add your endpoint URL (must be HTTPS)
- Select the events you want to receive
- Copy your webhook signing secret
Webhook Payload
All webhook payloads follow this structure:
Webhook Payload Structure
json
{
"id": "evt_1234567890",
"event": "notification.delivered",
"timestamp": "2024-01-15T10:00:05Z",
"api_version": "2024-01-01",
"data": {
"notification_id": "notif-550e8400-e29b-41d4",
"notification_number": "NOTIF-20240115-0001",
"channel": "SMS",
"status": "DELIVERED",
"delivered_at": "2024-01-15T10:00:05Z"
}
}Available Events
| Event | Description |
|---|---|
notification.sent | Notification sent to delivery provider |
notification.delivered | Notification confirmed delivered |
notification.failed | Notification delivery failed |
notification.bounced | Email bounced |
appointment.created | New appointment booked |
appointment.cancelled | Appointment cancelled |
appointment.rescheduled | Appointment rescheduled |
appointment.checked_in | Patient checked in |
lab.result_ready | Lab results available |
lab.critical_value | Critical lab value detected |
delivery.status_changed | Delivery status updated |
Verifying Webhook Signatures
All webhooks include a signature header to verify authenticity. Always verify signatures before processing webhook data.
Signature Verification (Python)
python
import hmac
import hashlib
def verify_webhook(payload: str, signature: str, secret: str) -> bool:
"""Verify webhook signature."""
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
# In your webhook handler
@app.post("/webhooks/mediloop")
def handle_webhook(request):
signature = request.headers.get("X-MediLoop-Signature")
payload = request.body.decode()
if not verify_webhook(payload, signature, WEBHOOK_SECRET):
return Response(status=401)
# Process the webhook
data = json.loads(payload)
handle_event(data["event"], data["data"])
return Response(status=200)Signature Verification (Node.js)
javascript
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(`sha256=${expected}`),
Buffer.from(signature)
);
}
// Express handler
app.post('/webhooks/mediloop', (req, res) => {
const signature = req.headers['x-mediloop-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhook(payload, signature, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process the webhook
handleEvent(req.body.event, req.body.data);
res.status(200).send('OK');
});Responding to Webhooks
Your endpoint must respond within 30 seconds with a 2xx status code:
- 200 OK - Webhook received and processed
- 202 Accepted - Webhook received, will process asynchronously
- Any other status code triggers a retry
Retry Policy
If your endpoint fails to respond or returns an error, we retry with exponential backoff:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 | 8 hours |
After 6 failed attempts, the webhook is marked as failed and no further retries are attempted.
Best Practices
- Respond quickly - Return 200 immediately, process asynchronously
- Handle duplicates - Use the event ID to deduplicate
- Verify signatures - Always verify before processing
- Use HTTPS - Webhook URLs must use HTTPS
- Log events - Keep logs for debugging
- Handle all events - Gracefully ignore unknown event types
Testing Webhooks
You can test webhooks in the Developer Portal:
- Go to Webhooks settings
- Click "Send test event"
- Select an event type
- View the delivery status and response
In sandbox mode, webhooks are delivered immediately after API calls to help with testing.