For the complete documentation index, see llms.txt. This page is also available as Markdown.

Event Webhooks

Event Webhooks

Event Webhooks deliver real-time HTTP callbacks when subscriber events occur. Configure one or more endpoints per domain to receive structured event data as it happens.

Configuration

Navigate to Domain Settings → Event Webhooks to create, edit, or archive webhook endpoints.

Each webhook specifies:

  • URL: the destination endpoint

  • Headers: custom headers, with optional Liquid macros for secrets

  • Events: one or more event types to subscribe to

All deliveries are POST with a JSON body containing the full event payload.

Supported Events

Group
Event
Description

Notification

notification.displayed

A subscriber's device renders a notification

Notification

notification.clicked

A subscriber clicks a notification

Each event fires once per subscriber per action. A notification sent to 10,000 subscribers produces up to 10,000 individual events.

Payload Structure

Fixed envelope with event-specific data. Null fields are omitted.

Envelope

Field
Type
Description

version

int

Payload schema version

event_type

string

Dot-namespaced event identifier (e.g. notification.clicked)

event_id

string (UUID)

Stable identifier for this event. Use as your deduplication key.

event_timestamp

string (ISO 8601, UTC)

When the event occurred

domain

object

The Pushly domain the event belongs to

user

object

The subscriber who triggered the event

data

object

Event-specific content. Contains exactly one key matching the event subject.

The data object contains a single key matching the event's subject. For notification.* events, that key is notification.

All timestamps are ISO 8601 UTC with millisecond precision.

Header Macros

Custom header values support Liquid template syntax for referencing stored domain secrets:

Only secrets explicitly referenced in header templates are loaded. System-managed secrets (aliases starting with _) are not accessible in templates.

Headers

Every delivery includes:

Header
Description

X-Pushly-Webhook-Id

UUID identifying which webhook config produced this delivery

X-Pushly-Event-Id

The unique event ID from the payload. Use for deduplication.

X-Pushly-Signature

HMAC-SHA256 signature of the request body (see below)

X-Pushly-Delivery-Timestamp

Unix timestamp (seconds) when the delivery was initiated

X-Pushly-Attempt-Number

1-indexed attempt number

Content-Type

application/json

Reserved header names (Content-Type, Host, Content-Length, Transfer-Encoding, anything starting with X-Pushly-) cannot be overridden by custom headers in your webhook configuration.

Signature Verification

Every delivery includes an X-Pushly-Signature header for authenticity verification.

Format: sha256=<hex_digest>

Verification algorithm:

  1. Encode your signing secret as UTF-8 bytes

  2. Compute HMAC-SHA256 over the raw request body using the secret as the key

  3. Hex-encode the digest

  4. Compare to the value after sha256= in the header using constant-time comparison

Important: Verify against the raw request body, not a parsed and re-serialized version. JSON key ordering and whitespace affect the digest.

Replay prevention (optional): Compare X-Pushly-Delivery-Timestamp to your server's current time. Reject deliveries older than your tolerance window (e.g. 5 minutes).

Your signing secret is available in Domain Settings → Event Webhooks → Signing Secret.

Idempotency

Pushly produces one event per subscriber per action. Events may be delivered more than once if your endpoint fails or times out — use event_id for deduplication, and use a durable queue on your side if processing happens asynchronously after acknowledgment.

Delivery

Timeout

Your endpoint must respond within 5 seconds. Acknowledge immediately and process asynchronously if your logic takes longer.

Retries

Attempt
Delay

1

Immediate

2

4 seconds after first failure

3

16 seconds after second failure

After 3 attempts, the event moves to a dead-letter queue.

Retried: HTTP 5xx, timeouts, connection errors. Not retried: HTTP 4xx, SSRF blocks.

Ordering

Events may arrive out of order. Use event_timestamp for chronological ordering, not delivery order.

Network Security

The primary authentication mechanism for webhook deliveries is HMAC signature verification (above). Every delivery includes an X-Pushly-Signature header you can validate against the request body using your signing secret. This is cryptographic proof the request came from Pushly — independent of network origin and resilient to infrastructure changes on our side.

IP Allowlisting

We don't publish a static list of egress IPs. If your security or compliance policy requires IP-based network controls, contact your Pushly account manager to discuss your requirements.

TLS

Webhook endpoints must be reachable over HTTPS. Pushly does not deliver to plain HTTP URLs. We require TLS 1.2 or higher and validate your endpoint's certificate against standard public certificate authorities. Self-signed certificates are not supported.

SSRF Protection

Pushly validates every destination URL against private and reserved IP ranges before connecting. Requests to private (RFC 1918), loopback, link-local, and instance-metadata addresses are rejected.

Versioning

New fields and event types are added without incrementing version. Ignore unknown fields in your handlers.

Breaking changes (field removals or renames) increment version with a deprecation window.

Last updated