Webhooks are the backbone of a real-time OwnPay integration. Instead of polling the API to check payment status, OwnPay pushes an HTTP POST to your server the moment a payment event occurs — when a payment is confirmed, fails, is refunded, or when a payment link is paid. This guide covers everything from configuring your endpoint to writing resilient, idempotent handlers in PHP and Node.js.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/own-pay/OwnPay-Documentation/llms.txt
Use this file to discover all available pages before exploring further.
How Webhooks Work
| Attempt | Delay After Previous Failure |
|---|---|
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
| 6 (final) | 12 hours |
failed in the delivery log.
Configuring an Endpoint
Log in to your OwnPay admin panel and navigate to Admin Panel → Developer Hub → Webhooks. Click Add Endpoint.
OwnPay only delivers webhooks to
https:// endpoints. For local development, use ngrok to expose a local port over a public HTTPS URL, then register that URL as your endpoint.Choose which events should trigger delivery to this endpoint. You can select individual events or choose All events to receive everything. See the Event Types table below for the full list.
After saving the endpoint, OwnPay generates a Webhook Signing Secret. Copy it immediately — it is shown only once and cannot be retrieved again.
Webhook Request Format
Every webhook delivery is an HTTP POST with the following headers and a JSON body: Headers:payment.completed example:
Signature Verification
The signature algorithm:sha256= in the X-OwnPay-Signature header. The timestamp included in the computation is the Unix epoch value from the X-OwnPay-Timestamp header.
Event Types
| Event | Description |
|---|---|
payment.pending | Intent created; customer has not paid yet |
payment.processing | Gateway confirmed receipt; settlement in progress |
payment.paid | Payment fully confirmed and settled |
payment.completed | Alias for payment.paid used by some gateway integrations |
payment.failed | Payment attempt failed |
payment.cancelled | Customer or merchant cancelled the intent |
payment.refunded | Full refund issued |
payment.partial_refunded | Partial refund issued |
link.visited | A payment link was opened by a customer |
link.paid | A payment via payment link was completed |
Retry Behavior and Delivery Logs
Viewing Delivery History
Inspect the 50 most recent webhook delivery attempts — including the payload sent, the HTTP status received, retry count, and final status:Testing Webhooks
Fire a Test Event via API
Send a samplepayment.completed payload to your configured webhook endpoint to verify reachability and confirm your handler returns 200:
Expose a Local Server with ngrok
For active development, tunnel your local server to a public HTTPS URL:Idempotency
Webhook delivery is at-least-once — in rare cases (network timeouts, server restarts before your handler returned200), OwnPay may deliver the same event more than once. Make every handler idempotent:
Best Practices
Return 200 Immediately
Acknowledge the webhook immediately, then process asynchronously in a background queue. Slow handlers cause retries and duplicate delivery.
Always Verify Signatures
Never process an event without verifying the HMAC-SHA256 signature. Skip this step and any bad actor can forge payment confirmations.
Verify Before Fulfilling
After receiving a
payment.paid event, confirm status by calling GET /payments/{id} or GET /transactions/{trx_id} before fulfilling orders.Handle Unknown Events
Your handler will receive new event types as OwnPay adds them. Default branches should return
200 silently rather than 400 or 500.Webhook events include a
metadata field that mirrors the metadata you passed when creating the payment intent. Use this to carry your internal order_id, user_id, or any other identifiers through the payment flow without additional lookups.Next Steps
PHP Integration
Full PHP client for payment intents, payment links, and transactions.
Node.js Integration
Full TypeScript/Node.js client with type definitions and Express examples.
API Reference
Complete OpenAPI spec including all webhook payload schemas.
Developer Quickstart
Go from zero to a working integration in five minutes.