Webhook events
EagraΓ Clainne can send signed HTTP POST requests to endpoints that an admin registers. Each webhook record holds a name, a URL, an HMAC secret and a list of event patterns. When an event occurs, the server delivers it to every webhook whose patterns match. ADR-0024 records the design: envelope shape, signature scheme, retry schedule and ordering guarantees.
This page lists every event the server can send.
Event families
Event names have three families:
| Family | Shape | Source |
|---|---|---|
| Notification | notify.<kind> |
The in-app notification seam |
| Mutation | mutation.<entity>.<action> |
The audit log |
| Test | webhook.test |
The TestWebhook RPC |
Notification events
These seven events fire when the server emits the matching in-app notification. Each carries the same context fields as the notification.
notify.job_completedβ a member completed a job.notify.job_up_for_grabsβ a job became available to claim.notify.job_assignedβ a job was assigned to a member.notify.reward_grantedβ a member received a reward.notify.reward_claimedβ a member claimed a reward.notify.meal_assignedβ a member was assigned to cook a meal.notify.meal_reminderβ a reminder for an upcoming meal duty.
Mutation events
Every audited create, update or delete becomes a
mutation.<entity>.<action> event. Coverage is structural: the
dispatcher taps the audit sink, so any entity that mutates through the
service layer produces events without extra wiring. A new entity type
joins this list automatically.
The <action> segment is create, update or delete. Audit entries
that record other activity, such as data exports, do not become webhook
events.
The <entity> segment is the lowercase protobuf message name. The
current entity types:
usereventitemitemlistrewardmealmealrotamealdayoverridemealweekapikeypushsubscriptionwebhook
The notification entity is excluded. Notification rows churn on every
fan-out and mark-read, and would flood consumers without information.
Test event
webhook.test fires only when an admin presses the test button or calls
the TestWebhook RPC. The server sends it synchronously to that one
webhook and reports the delivery result in the response.
Pattern matching
A webhook's patterns match event names in two ways:
- An exact name:
notify.job_completed. - A prefix that ends in
*:notify.*,mutation.item.*, or a bare*for everything.
Delivery headers
Each delivery carries these headers:
X-Eagrai-Clainne-Eventβ the event name.X-Eagrai-Clainne-Timestampβ the send time, in unix seconds.X-Eagrai-Clainne-Signatureβsha256=plus the hex HMAC-SHA256 of<timestamp>.<body>, keyed with the webhook's secret.
Consumers must verify the signature before they trust the body. The timestamp is inside the signed content, so a captured delivery cannot replay outside the receiver's tolerance window.
Delivery body
The body is a JSON envelope of hand-picked scalars. It never contains
entity payloads β a consumer that needs the full record reads it back
through the API. A notify.job_completed delivery looks like this:
{
"event": "notify.job_completed",
"timestamp": "2026-08-09T20:14:03Z",
"actor": {
"uid": "0198a2f4-6c1e-7d3a-b2c8-9f41e5d0a7b3",
"name": "Fiadh"
},
"entity_type": "item",
"entity_uid": "0198a2f4-8b2d-7e4f-a1c9-3d57b6e2f8c4",
"entity_label": "Empty the dishwasher",
"context": { "points": 5 }
}
| Field | Meaning |
|---|---|
event |
The event name, exactly as in X-Eagrai-Clainne-Event. |
timestamp |
When the event was built, RFC3339 UTC. |
actor |
Who did it: uid and display name. Zero-valued ("" for both) when nobody did, such as a board reminder. |
entity_type |
What kind of thing it happened to, in the audit log's vocabulary. |
entity_uid |
The uid of that thing. Empty when the event has no stored record, such as a meal reminder. |
entity_label |
A human-readable label for that thing. May be empty. |
context |
The event family's extra scalars. Omitted when the event has none. |
Context fields per event
| Event | Context fields |
|---|---|
notify.job_completed |
points |
notify.job_up_for_grabs |
none |
notify.job_assigned |
target_uid |
notify.reward_granted |
target_uid, value |
notify.reward_claimed |
cost |
notify.meal_assigned |
target_uid, date |
notify.meal_reminder |
cook_uid |
mutation.<entity>.<action> |
none |
webhook.test |
none |
For notify.meal_assigned the actor is the assigner and the target is
the cook. For notify.meal_reminder no member acted, so the actor is
zero-valued and cook_uid names the cook. Mutation events carry the
audit entry's actor and entity fields with no context map. The test
event carries only the admin who pressed the button.