Callbacks
A callback is an HTTPS request from the Gregor server to your service, sent when someone acknowledges an alert. Use it to close an incident, stop an escalation, or record who took the alert, without polling receipts.
The person acknowledging decides whether the callback is sent. It is never sent from their device.
Set up the channel
Section titled “Set up the channel”Callbacks are configured per channel by its owner or an administrator.
- On the Channels page, open the channel’s Send URLs.
- Under Acknowledgement callback, choose Configure callback.
- Enter the Callback URL. It must be a publicly reachable
httpsURL. Fixed query parameters are kept. - Save. The section shows Callback enabled and a Callback signing key.
- Choose Reveal key, copy the key, and store it in your service’s secret storage. Do not put it in scripts, logs, or clients.
Request a callback
Section titled “Request a callback”Add "callback": true to the alert. The alert must be one that can be acknowledged, so it is either urgent, sets require_ack, or sets receipt; a callback on any other alert makes it require acknowledgement.
curl -X POST "$SEND_URL" \ -H 'Content-Type: application/json' \ -d '{"alert": {"title": "Database unavailable"}, "level": "urgent", "callback": true}'The request is rejected with callback_not_configured if the channel has no enabled callback, so a callback that could never fire is not accepted.
When someone acknowledges the alert, the app asks: Acknowledge only, or Acknowledge and send Callback. Only the first acknowledgement counts; acknowledging again on another device changes nothing.
What your service receives
Section titled “What your service receives”POST /talaria/ack HTTP/1.1Content-Type: application/jsonUser-Agent: Receipt-Callback/1X-Webhook-Event-Id: cb1…X-Webhook-Key-Id: ck1…X-Webhook-Timestamp: 1792311330X-Webhook-Attempt: 1X-Webhook-Signature: v1=5d41402abc4b2a76b9719d911017c592…{ "event_id": "cb1…", "type": "receipt.acknowledged", "occurred_at": "2026-10-27T08:15:30Z", "channel_id": "ch1…", "receipt_id": "rcp_9a02…", "message_id": "msg_4f1c…", "status": "acked", "acknowledged": true, "acknowledged_at": "2026-10-27T08:15:30Z", "acknowledged_by": { "user_id": "…", "device_address": "dv1…" }}The body never contains the alert’s title, body, or payload. Match it to your own records with message_id or receipt_id.
Verify the signature
Section titled “Verify the signature”Before trusting a callback:
- Look up the key for
X-Webhook-Key-Id. - Reject it if
X-Webhook-Timestampis more than five minutes from your clock. - Compute HMAC-SHA256 over
timestamp + "." + raw body, using the key exactly as copied from the app, and compare it in constant time with the hex value afterv1=. - Ignore an
X-Webhook-Event-Idyou have already processed. - Respond with any
2xxstatus only after you have stored the event.
import hashlib, hmac, time
def verify(headers, raw_body: bytes, key: str) -> bool: timestamp = headers["X-Webhook-Timestamp"] if abs(time.time() - int(timestamp)) > 300: return False expected = hmac.new(key.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest() received = headers["X-Webhook-Signature"].removeprefix("v1=") return hmac.compare_digest(expected, received)Compute the signature over the bytes you received, before parsing the JSON.
Retries
Section titled “Retries”Delivery is at least once, so the same event can arrive more than once; deduplicate by event ID.
- Network errors, timeouts,
408,429, and5xxresponses are retried, starting after one minute and backing off up to one hour between attempts. ARetry-Afterheader is respected. - Other
4xxresponses stop the retries, because they usually mean the endpoint is misconfigured. - Retries stop 24 hours after the acknowledgement.
The receipt shows the callback’s status, attempt_count, and delivered_at.
Rotate or disable
Section titled “Rotate or disable”- Rotate key creates a new signing key. New callbacks use it immediately; callbacks already queued keep the key they were created with, and the previous key keeps working for 24 hours. Deploy the new key to your service, keyed by
X-Webhook-Key-Id, within that time. - Disable callback stops new alerts from requesting callbacks. Callbacks already queued are still delivered.