Webhooks Overview
What are Webhooks?
Webhooks allow vitalera to send real-time HTTP POST notifications to your application when events occur in the platform. Instead of polling the API for changes, webhooks push data to your endpoint as soon as events happen.
How It Works
- Configure a webhook URL in your vitalera organization settings
- Select the event types you want to receive
- Set a secret for signature verification
- vitalera sends HTTP POST requests to your URL when matching events occur
Event Types
| Event Type | Trigger |
|---|---|
observation.created | A new observation is recorded for a patient |
alarm.triggered | An alarm rule is triggered by an observation |
alarm.resolved | A previously triggered alarm is resolved |
consent.granted | A patient grants data-sharing consent |
consent.revoked | A patient revokes consent |
questionnaire_response.submitted | A patient submits a questionnaire response |
care_plan.activated | A care plan is activated |
care_plan.completed | A care plan reaches its end date or is completed |
Webhook Payload
All webhook payloads follow a consistent structure:
{
"event_type": "observation.created",
"timestamp": "2024-01-15T10:30:00Z",
"organization_id": 42,
"data": {
"id": 810,
"resourceType": "Observation",
"observation_definition": {
"observation_name": "heart_rate",
"observation_method": "device"
},
"category": "physiological_data",
"value": "72",
"value_type": "int",
"value_unit": "bpm",
"issued": "2024-01-15T10:30:00Z",
"effective_datetime": "2024-01-15T10:30:00Z",
"source_id": 1
}
}
Alarm Triggered Example
{
"event_type": "alarm.triggered",
"timestamp": "2024-01-15T10:31:00Z",
"organization_id": 42,
"data": {
"alarm_id": 55,
"alarm_name": "High Heart Rate",
"severity": "high",
"patient_id": 123,
"triggering_observation": {
"observation_name": "heart_rate",
"value": "145",
"value_unit": "bpm"
}
}
}
Signature Verification
All webhook calls include an x-webhook-signature header containing an HMAC-SHA256 signature of the request body, computed using your webhook secret.
To verify a webhook:
- Extract the
x-webhook-signatureheader value - Compute HMAC-SHA256 of the raw request body using your webhook secret
- Compare the computed signature with the header value (use constant-time comparison)
Python Example
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Node.js Example
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto.createHmac('sha256', secret).update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
Security Best Practices
- Always use HTTPS endpoints
- Set a unique secret per webhook configuration
- Verify the signature on every incoming request before processing
- Respond with
200 OKquickly and process the payload asynchronously - Store the webhook secret securely (e.g., environment variable, secrets manager)
Retry Policy
If your endpoint returns a non-2xx response or times out, vitalera retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | ~1 minute |
| 2nd retry | ~5 minutes |
| 3rd retry | ~30 minutes |
| 4th retry | ~2 hours |
After all retries are exhausted, the event is marked as failed. You can review failed deliveries in your organization settings.
Need Help?
Contact support@vitalera.io to configure webhooks for your organization.