Skip to content

Webhooks

Webhooks push event notifications to your server when asynchronous state changes occur. Rather than polling the API to check payment status, configure a webhook endpoint and let ElasticPay notify you.

Webhook endpoints are configured by ElasticPay — there is no self-serve webhook screen in the dashboard. To add or change one, contact support with:

  • the endpoint URL (publicly reachable, HTTPS, not localhost)
  • the event types you want to receive
  • whether it is for your sandbox or live account

Sandbox and live accounts have separate subscriptions, each with its own signing secret. Sandbox events are only delivered to sandbox endpoints, and live events only to live endpoints. Secret rotation also goes through support.

Once events are flowing, the delivery status of an individual event is shown in the Events panel on the payment intent, payment plan, or customer detail page.

Every webhook event has the same structure:

{
"version": "1",
"event_id": "evt_0abc123def456ghi789jkl",
"event_type": "payment_intent.succeeded",
"biller_id": "biller_abc123",
"livemode": false,
"emitted_at": "2025-01-15T10:05:00Z",
"data": {
"id": "pi_0abc123def456ghi789jkl012mn",
"status": "succeeded",
"amount": 5000,
"currency": "AUD"
}
}
Field Description
version Envelope schema version
event_id Unique event identifier — use for deduplication
event_type Event name (see table below)
biller_id Account that generated the event
livemode true for live events, false for sandbox
emitted_at ISO 8601 timestamp
data The resource at the time of the event
Event Description
payment_intent.succeeded Payment completed successfully
payment_intent.failed Payment declined or failed
payment_intent.processing Submitted to PSP, awaiting result
payment_intent.canceled Payment intent was canceled
payment_intent.refunded Full refund succeeded
payment_intent.partially_refunded Partial refund succeeded
payment_intent.refund_failed Refund attempt failed
setup_intent.succeeded Payment method saved successfully
setup_intent.failed Setup intent failed
automation_rule.triggered One of your automation rules with a webhook action fired (below)
test_clock.created Sandbox test clock created
test_clock.advancing Test clock advance accepted (includes target_time)
test_clock.ready Test clock advance completed (includes effects_manifest)
test_clock.deleted Test clock deleted, manually or at expiry

Bank debits send payment_intent.succeeded when they clear, and payment_intent.failed when they’re returned, before or after clearing.

Sent when an automation rule with a webhook action fires. It names the rule and the payment. For the payment’s own details, fetch the payment intent or use the payment_intent.* events. Its data:

Field Description
automation_rule_id The rule (auto_...)
action_type webhook
trigger_type every_payment, first_payment, payment_count, total_collected, or lead_days (a reminder)
reference_type PaymentPlan or Customer: what the rule is for
reference_id The plan (pp_...) or customer (cus_...)
payment_intent_id The payment the rule fired for
custom_data Always null today

Every webhook request includes an X-Webhook-Signature header. Verify it to confirm the request came from ElasticPay.

The signature is computed as v1=HMAC-SHA256(secret, "<timestamp>.<raw_body>") where <timestamp> is the value of the X-Webhook-Timestamp header.

Header Description
X-Webhook-Signature v1=<hex HMAC-SHA256>
X-Webhook-Timestamp ISO 8601 timestamp of when the event was signed
X-Webhook-Key-Id Identifies which signing key was used

Reject requests where the timestamp is more than 5 minutes from your server clock to prevent replay attacks.

Terminal window
# Webhook requests include these headers:
#
# X-Webhook-Signature v1=<hex HMAC-SHA256>
# X-Webhook-Timestamp ISO 8601 timestamp
# X-Webhook-Key-Id signing key identifier
#
# The signature is computed as:
# HMAC-SHA256(secret, "<timestamp>.<raw_body>")
#
# Reject requests where the timestamp is more than 5 minutes
# from your server clock to prevent replay attacks.
  • Respond 200 immediately. Process events asynchronously — do not make slow API calls inside the handler.
  • Make handlers idempotent. Events may be delivered more than once. Use event_id to deduplicate.
  • Verify livemode. Match the flag to your environment to avoid processing test events in production.
  • Expect retries. If your endpoint returns a non-2xx status, ElasticPay retries delivery with exponential backoff.