Webhooks
LifeLoop sends webhook events to notify your application when data changes. Rather than polling the API for updates, you register a webhook URL and receive a notification the moment something happens — a resident is created, an activity is updated, a photo is uploaded.
How it works
Event envelope
Every webhook delivery uses this envelope regardless of event type.
| Field | Type | Description |
|---|---|---|
| eventId | string (UUID) | Unique ID for this event. Use for deduplication. |
| eventType | string | The event that occurred (see event catalog below). |
| tenant | string | The tenant this event belongs to. |
| occurredAt | string (ISO 8601) | When the event occurred in LifeLoop. |
| resourceId | string | ID of the resource that changed. Use this to fetch the full object. |
Signature verification
Every webhook delivery includes an X-LifeLoop-Signature header. Always verify it before processing the payload.
===) is vulnerable to timing attacks. Use crypto.timingSafeEqual (Node.js) or hmac.compare_digest (Python).Responding to webhooks
Your endpoint must return an HTTP 200 within 5 seconds. LifeLoop considers any other response (or a timeout) a delivery failure and will retry.
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th retry | 8 hours |
After 5 failed attempts the event is sent to a dead-letter queue. Contact support to replay failed events.
Event catalog
A facility was created or its details changed
A resident record was created, updated, or removed
A family member or connection was added, updated, or removed
A facility calendar activity was created, changed, or deleted
A resident or connection registered for or cancelled an activity
A new message thread was opened or a message was posted
An announcement was sent to residents or connections
A photo was uploaded or deleted
{
"eventId": "evt-f3a91bc2-4d12-4e88-a1c3-8f2901dd7c94",
"eventType": "resident.created",
"tenant": "sunrise-001",
"occurredAt": "2026-06-18T10:30:00Z",
"resourceId": "res-001"
}const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}