data field specific to each event.| Header | Value | Description |
Content-Type | application/json | Payload encoding |
User-Agent | Shaf-Webhook/2.0 | Identifies the sender |
X-Shaf-Event | e.g. link.clicked | The event type string |
X-Shaf-Delivery | UUID | Unique delivery attempt identifier |
X-Shaf-Signature | HMAC-SHA256 hex | Signature of the raw JSON body |
1234567{ "id": "evt_9823471029384", "event": "link.clicked", "createdAt": "2026-09-19T20:25:00.000Z", "organizationId": "org_789xyz", "data": { } }
| Field | Type | Description |
id | string | Unique event identifier (for deduplication) |
event | string | Event type constant (see catalog below) |
createdAt | string | ISO 8601 timestamp of when the event occurred |
organizationId | string | The workspace that generated the event |
data | object | Event-specific payload (see each event below) |
123456789101112131415{ "id": "evt_abc123", "event": "link.created", "createdAt": "2026-09-19T20:00:00.000Z", "organizationId": "org_789xyz", "data": { "slug": "summer-deal", "domain": "link.yourbrand.com", "destinationUrl": "https://yourbrand.com/summer", "tags": ["sale", "email"], "createdBy": "user_456", "expiresAt": null, "passwordProtected": false } }
id field is a stable unique identifier per event. In rare cases of network retries, your endpoint may receive the same event twice. Store processed event IDs and skip duplicates:123456789const processedEvents = new Set<string>() function handleWebhook(event: ShafEvent) { if (processedEvents.has(event.id)) { return // Already processed } processedEvents.add(event.id) // Process event... }