Transaction state diagram
State descriptions
Created
The payment intent exists in the database but the customer hasn’t interacted with it yet. This is the initial state for API-created payments and freshly generated payment links. No webhook is fired. TransitionalPending
The customer has visited the checkout page and sees the payment form. No funds have been authorized. The payment sits in this state until the customer submits payment details or the auto-expiry timer fires. TransitionalProcessing
The customer has submitted their payment details and OwnPay has sent the authorization request to the gateway. The customer sees a loading indicator. OwnPay is waiting for the gateway’s response. TransitionalCompleted
The gateway approved the payment. OwnPay records the transaction in the double-entry ledger, fires thepayment.completed event, and delivers a webhook to your configured URL. The customer sees the success page.
Terminal: Yes
Failed
The gateway declined the payment - insufficient funds, invalid card, fraud detection, or a temporary network error. Apayment.failed webhook is delivered. The customer can retry from the Pending state.
Terminal: Yes
Expired
The payment link or checkout session timed out without customer action. The configurable auto-expiry timer fires a scheduled job that moves the payment to Expired. No webhook is sent. Terminal: YesCancelled
A merchant or staff member manually cancelled the payment before it was completed. Apayment.cancelled webhook is delivered.
Terminal: Yes
Refunded
A previously completed payment was refunded (full or partial). The gateway returned the funds to the customer and OwnPay recorded reversing ledger entries. Apayment.refunded webhook is delivered.
Terminal: Yes
Webhook events per state
Pending, Processing, and Expired states do not trigger webhooks. Your integration should rely on the terminal states (Completed, Failed, Cancelled, Refunded) to confirm payment outcomes.
Auto-expiry
Unpaid payments are automatically moved to Expired after a configurable timeout (default: 24 hours). The cron job (php public/index.php cron) runs every minute and checks for stale pending payments. Adjust the expiry window in System > Settings.
If you need real-time status updates during the Processing phase, use polling or rely on the gateway’s own callback. OwnPay only fires webhooks on terminal states.
Related pages
- Transactions - view and filter transaction history in the dashboard
- Webhooks - configure webhook URLs and verify HMAC-SHA256 signatures
- Gateways - understand how gateway routing affects processing
- Developer quickstart - integrate webhooks into your application
- Common errors - troubleshoot payment failures