Eventlayer / API & operations
Webhooks
Receive real-time notifications for API events.
Eventlayer publishes webhook events whenever resources change. Use them to keep your CRM, lifecycle email, analytics, and internal services aligned with what is happening at an event.
Why use webhooks?
Webhooks let your application react to events in real time without polling the API. Common use cases include:
- Creating or enriching a CRM contact when a ticket is assigned
- Triggering confirmation, reminder, or post-event email flows
- Sending ticket and check-in activity to your analytics pipeline
- Updating your own product when an attendee arrives
How it works
When a lifecycle event occurs—for example, a ticket is assigned or checked in—Eventlayer creates an independent signed delivery for every matching endpoint. Delivery happens separately from the API request, so an unavailable CRM or analytics service does not make your Eventlayer API call fail.
Event types
| Event | Triggered when |
|---|---|
event.created | A new event is created. |
event.updated | An event is updated. |
event.deleted | An event is deleted. |
attendee.created | A new attendee is added to an event. |
attendee.updated | An attendee is updated. |
attendee.deleted | An attendee is removed. |
ticket_type.created | A new ticket type is created. |
ticket_type.updated | A ticket type is updated. |
ticket_type.deleted | A ticket type is deleted. |
ticket.created | A new ticket is issued. |
ticket.updated | A ticket is updated. |
ticket.deleted | A ticket is deleted. |
ticket.assigned | A ticket is assigned to an attendee. |
ticket.checked_in | An attendee checks in. |
Webhook payload
Each webhook delivery includes a JSON body with the event type and the resource data:
{
"id": "whk_35d400aab1a52a2f",
"event_type": "ticket.checked_in",
"timestamp": "2026-09-15T08:55:01Z",
"attempt": 1,
"data": {
"id": "tkt_35d400aab1a52a2f",
"ticket_type_id": "tt_35d400aab1a52a2f",
"attendee_id": "atd_35d400aab1a52a2f",
"status": "checked_in",
"checked_in_at": "2026-09-15T08:55:00Z",
"created_at": "2026-07-21T12:00:00Z",
"updated_at": "2026-09-15T08:55:00Z"
}
}The data field contains the full response object for the affected resource — the same shape as the corresponding API response. Events are delivered independently, so consumers must not rely on delivery order.
Every request also includes Webhook-Id, Webhook-Delivery-Id,
Idempotency-Key, and Webhook-Attempt headers. The webhook and delivery IDs
remain unchanged across automatic retries.
Retry behavior
Network failures, timeouts, rate limits, and server errors are retried with
backoff. Redirects and most other client errors are treated as permanent
failures. Retryable HTTP responses are 408, 425, 429, and 5xx.
Retries are scheduled after 5 seconds, 5 minutes, 30 minutes, 2 hours, 5 hours,
and 10 hours, for up to seven attempts in total. Worker availability may delay
an attempt beyond its scheduled time. After the retry schedule is exhausted,
the delivery is marked failed.
Your endpoint should return a 2xx status code to acknowledge receipt.
Retryable failures may cause the same delivery to be sent more than once.
Delivery guarantees
Webhook delivery can happen more than once. Store the Idempotency-Key header
(which equals Webhook-Delivery-Id) to avoid repeating side effects when a
delivery is retried. Successful receipt is not guaranteed if the endpoint keeps
failing or the delivery is cancelled.
Verify signatures
Each request includes Webhook-Timestamp (Unix seconds) and
Webhook-Signature (v1=<hex HMAC>). Verify the HMAC-SHA256 using your endpoint's
signing secret over Webhook-Timestamp + "." + raw_request_body. Use the exact
request bytes before parsing JSON, compare signatures in constant time, and
reject timestamps more than five minutes from the current time.
During the 24-hour secret-rotation overlap, the signature header contains
multiple comma-separated v1 values. Accept the request if any value matches a
trusted secret. The signing secret is returned only when the endpoint is
created or its secret is rotated; store it securely.
View deliveries in the dashboard
Open Dashboard → Webhooks → Delivery log to see deliveries newest first. Filter by status or endpoint, use Older and Newer to page through history, and select View for a delivery's details. The log and open detail view refresh every five seconds while the page is active; the log also has a manual Refresh button.
| Status | Meaning |
|---|---|
queued | Waiting for its first attempt or a scheduled retry |
delivering | A worker has claimed the delivery |
succeeded | The endpoint returned a 2xx response |
failed | A permanent failure occurred or retries were exhausted |
cancelled | The endpoint was deleted before delivery completed |
The log shows attempt counts, the last HTTP response or error, the next queued attempt time, and creation time. View includes IDs, timestamps, the event payload, and each recorded attempt's target URL, HTTP status, duration, error, and response body. Response bodies are limited to the first 500 bytes. An unattempted delivery has no attempt history; a network failure may have no HTTP status or response body.
Deleting an endpoint cancels its pending deliveries. Its history remains available through the All endpoints (including deleted) filter.
Delivery API and SDK
These routes require a dashboard access token from an authenticated, email-verified user session. API keys cannot access them.
GET /v1/webhook-deliveries
GET /v1/webhook-deliveries/{delivery_id}
POST /v1/webhook-deliveries/{delivery_id}/replayThe TypeScript SDK exposes webhookDeliveries.list(filters) and
webhookDeliveries.get({ deliveryId: deliveryId }); webhookDeliveries.replay({ deliveryId: deliveryId }) queues
a new delivery. See the SDK package README
for authentication and examples.
The list accepts status, endpoint_id, limit (1–100, default 50), and either
after or before. Its result contains items and meta.has_more, ordered
newest first. Pass the last item's ID as after to fetch older deliveries with
the same filters. Omit endpoint_id to include history from deleted endpoints.
List items include attempt_count, response_status, error,
next_attempt_at, last_attempted_at, completed_at, and created_at, but their
attempts arrays are empty. Fetch an individual delivery to load its attempt
history. For queued deliveries, next_attempt_at is the scheduled attempt
time; for delivering records, it is the worker lease deadline.
A replay uses the original event ID and resource payload with the endpoint's current URL, but creates a new delivery ID. The original outcome remains unchanged. Replays require an endpoint that has not been deleted.
Choose Retry for a failed delivery or Resend for another completed
delivery, from the log or detail view. The new delivery opens automatically so
you can follow its progress. These buttons are disabled while a delivery is
queued or in progress, while a resend request is pending, or when its endpoint
is unavailable. The SDK's replay() request does not automatically retry; after
an uncertain network result, check history before sending again.
Select View response in the log to open the last recorded response. The Last response panel shows the body directly, along with the HTTP status, error, duration, and timestamp. Attempt history is ordered newest first.