Repository navigation
Webhooks
Syed Ahmer Shah edited this page Oct 25, 2026
·
1 revision
An organization admin can add webhooks in the organization's settings. HolidayOps then sends a
signed POST to your URL whenever a calendar changes. Full design:
docs/design/m4-subscriptions.md.
calendar.updated, calendar.deleted, custom_day.created, custom_day.updated,
custom_day.deleted, and ping (sent when you press "Send test").
{
"id": "<delivery uuid>",
"event": "custom_day.created",
"created_at": "2027-03-01T09:00:00Z",
"org": "acme",
"data": {
"calendar": {"id": "<uuid>", "name": "Karachi office", "slug": "karachi-office"},
"custom_day": {"id": "<id>", "date": "2027-03-23", "name": "Office closed", "kind": "closure"}
}
}| Header | Value |
|---|---|
X-HolidayOps-Event |
the event name |
X-HolidayOps-Delivery |
a unique id per delivery; use it to ignore duplicates |
X-HolidayOps-Signature |
t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>"> |
The secret starts with whsec_ and is shown once, when you create or rotate the webhook. Sign
the raw request body, not a re-encoded copy, and reject timestamps older than 5 minutes.
import hashlib, hmac, time
def verify(secret: str, body: bytes, header: str, tolerance: int = 300) -> bool:
parts = dict(item.split("=", 1) for item in header.split(","))
timestamp = int(parts["t"])
if abs(time.time() - timestamp) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])- Your URL must be
httpson a public address; private and local addresses are refused. - Answer with any
2xxwithin 10 seconds. Redirects are not followed. - Network errors,
429and5xxare retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours (6 attempts at most). Other4xxanswers fail at once. - After 20 failed deliveries in a row the webhook is turned off; turn it back on in settings.
- The settings page shows the last 50 deliveries with their status and response.
- An organization can have up to 10 webhooks. Admins and owners manage them.
HolidayOps by Syed Ahmer Shah · MIT License · support@ahmershah.dev · The repository's docs/ are the source of truth.
Use it
Run it
Build it
Repository