Webhooks
Element Pay notifies your backend when orders, customers, and accounts change. Treat webhooks as the source of truth for settlement, KYC / banking readiness, and account credits / sends — HTTP responses only confirm the request was accepted. If a webhook is delayed, poll the matching GET endpoint as a backup.Configuration
Setwebhook_url and webhook_secret on your partner API key (sandbox and production separately). The same endpoint receives order, customer, and account events.
Order events
Backup poll:
GET /partner/orders/{order_id}.
Customer events
Same signing headers and secret as orders. Backup poll:GET /partner/customers/{customer_id}.
Customer payload (example)
Deposit-account payload (example)
Fired ascustomer.deposit_account.updated:
products.deposit_account.status is ready (and can_open_deposit_account is true), you may call Accounts open/list/get. See also Customers quickstart.
Account events
Same signing headers and secret. These fire for customer deposit-account rails (and related money movement). Backup poll:GET /partner/customers/{customer_id}/accounts/{account_id} (and send/payout GET where applicable).
Use
account.credited / account GET balance before spending. For sends, prefer account.send.completed / account.send.failed; if GET stays non-terminal after debit for a long time, escalate rather than assuming destination credit.
HTTP delivery
Order payload (example)
Webhook bodies have no internal routing metadata or upstream PSP blobs. Typical order fields:client_metadata and other internal fields are not included on the public partner API.
Signature verification
ParseX-Webhook-Signature:
- Reject if
tis older than 5 minutes (replay protection). - Compute HMAC-SHA256 over
{t}.{raw_body}using yourwebhook_secret. - Compare constant-time to
v1.
Idempotency
UseX-Webhook-Id to deduplicate deliveries. Your endpoint should return 2xx quickly; heavy work can be async.