Webhooks
Webhooks allow you to receive HTTP callbacks when events occur in your Snaapi application. Configure webhook subscriptions with event pattern matching, custom headers, field filtering, and automatic retry with exponential backoff.
Subscriptions
A webhook subscription defines where and how event notifications are delivered:
| Field | Type | Description |
|---|---|---|
id |
string |
UUID identifier |
name |
string |
Display name (1–255 characters) |
url |
string |
Delivery URL (max 2048 characters) |
eventPattern |
string |
Pattern to match events |
headers |
Record<string, string> | null |
Custom HTTP headers to include |
enabled |
boolean |
Whether the webhook is active |
retryConfig |
RetryConfig | null |
Custom retry configuration |
fieldIds |
string[] | null |
Field IDs to include in the payload |
createdAt |
string |
ISO 8601 creation timestamp |
updatedAt |
string |
ISO 8601 last-updated timestamp |
Event Patterns
Event patterns use wildcards to match one or more event types:
| Pattern | Matches |
|---|---|
* |
All events from all resources |
posts.* |
All events for the posts resource |
*.created |
All created events across all resources |
posts.created |
Only posts.created events |
Pattern names must match the regex ^[a-zA-Z0-9_.*]+$.
Custom Headers
Add custom HTTP headers to webhook deliveries for authentication or routing:
{
"headers": {
"Authorization": "Bearer my-secret-token",
"X-Custom-Header": "custom-value"
}
}
The following headers are always included automatically:
| Header | Value |
|---|---|
Content-Type |
application/json |
User-Agent |
Snaapi-Webhooks/1.0 |
X-Snaapi-Event |
Event type (e.g., posts.created) |
X-Snaapi-Event-Id |
Event UUID |
X-Snaapi-Delivery-Id |
Delivery UUID |
X-Snaapi-Delivery-Attempt |
Attempt number |
Field Filtering
Use fieldIds to limit which fields are included in the webhook payload. When
specified, only the listed fields (by ID) are included in a fields object:
{
"fields": {
"title": {
"id": "field-id",
"type": "string",
"value": "Hello World"
}
}
}
If fieldIds is null or omitted, no fields object is included in the
payload.
Webhook Payload
The full payload delivered to your endpoint:
{
"id": "event-uuid",
"event": {
"type": "posts.created",
"resource": "posts",
"resourceId": "post-123",
"createdAt": "2026-01-01T00:00:00Z",
"data": {
"old": null,
"new": { "id": "post-123", "title": "Hello World" },
"changes": { "added": ["id", "title"], "updated": [], "removed": [] }
},
"sessionVariables": { "userId": "user-1", "role": "editor" },
"traceContext": { "traceId": "abc", "requestId": "req-1" }
},
"delivery": {
"id": "delivery-uuid",
"attempt": 1
}
}
Delivery timeout is 30 seconds.
Retry Configuration
Webhooks use exponential backoff for failed deliveries. Customize retry behavior per webhook or use the defaults:
| Property | Type | Min | Max | Default |
|---|---|---|---|---|
maxAttempts |
number |
1 | 100 | 5 |
backoffMultiplier |
number |
1 | 10 | 2 |
initialDelayMs |
number |
100 ms | 60,000 ms | 1,000 ms |
maxDelayMs |
number |
1,000 ms | 3,600,000 ms | 300,000 ms |
The delay between retries is calculated as:
delay = min(initialDelayMs * backoffMultiplier ^ (attempt - 1), maxDelayMs)
Delivery Tracking
Each webhook delivery attempt is recorded as a WebhookDelivery:
| Field | Type | Description |
|---|---|---|
id |
string |
Delivery UUID |
webhookId |
string |
Parent webhook ID |
eventId |
string |
Associated event ID |
status |
string |
pending, success, or failed |
httpStatus |
number | null |
HTTP response status code (100–599) |
requestPayload |
string |
JSON request body sent |
responseBody |
string | null |
Response body received |
responseHeaders |
Record<string, string> | null |
Response headers received |
error |
string | null |
Error message (if failed) |
deliveredAt |
string | null |
Timestamp of successful delivery |
attemptNumber |
number |
Attempt number (starts at 1) |
nextRetryAt |
string | null |
Scheduled time for next retry |
createdAt |
string |
ISO 8601 creation timestamp |
Delivery Statuses
| Status | Description |
|---|---|
pending |
Delivery is queued or awaiting retry |
success |
Endpoint responded with a successful HTTP status |
failed |
All retry attempts exhausted or a non-retryable error occurred |