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). |
| aggregateType | string | Domain of the affected resource (e.g. resident, activity, notification). |
| 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. |
Authenticating deliveries
Every delivery carries your integration's configured key in the X-API-KEY header. Check it before trusting the request. If no key is configured for your tenant, the header is not sent.
crypto.timingSafeEqual (Node.js) or hmac.compare_digest (Python) rather than plain string equality.Responding to webhooks
Any 2xx response means the event was delivered; the body is ignored. LifeLoop waits up to 5 seconds to connect and 10 seconds for a response.
A delivery is retried when there is no response (connection error or timeout) or the response is 5xx, 408 or 429. Any other response, including 3xx redirects and other 4xx codes, is final.
| Attempt | Delay after previous |
|---|---|
| Initial delivery | — |
| 1st retry | ~30 seconds |
| 2nd retry | ~1 minute |
| 3rd retry | ~2 minutes |
| 4th retry | ~4 minutes |
eventId — use it to skip events you have already processed. Delivery order is not guaranteed: order events by occurredAt and treat each event as a signal to re-read the resource.Event catalog
A resident record was created, updated, or removed
A family member or connection was added, updated, or removed
A calendar activity was created, changed, or deleted
A registration was created, waitlisted, or deleted
A new message thread was opened
A message was posted, edited, or deleted
An announcement was sent to residents or connections
A newsletter was sent
A photo was uploaded, updated, or deleted
A user-facing notification was triggered (reminders, new messages, cancellations)
A transportation request was created, updated, deleted, or commented on
A work request was created, updated, deleted, or commented on
{
"eventId": "f3a91bc2-4d12-4e88-a1c3-8f2901dd7c94",
"eventType": "resident.created",
"aggregateType": "resident",
"tenant": "sunrise-001",
"occurredAt": "2026-06-18T10:30:00Z",
"resourceId": "res-001"
}// Express handler
app.post('/lifeloop/webhook', express.json(), (req, res) => {
const key = req.get('X-API-KEY');
if (key !== process.env.LIFELOOP_WEBHOOK_KEY) {
return res.sendStatus(401);
}
if (alreadyProcessed(req.body.eventId)) return res.sendStatus(200);
queue.push(req.body); // re-read the resource asynchronously
res.sendStatus(200); // acknowledge fast (any 2xx)
});