Payment States
Every payment in Ottu has two levels: a payment transaction (the top-level entity with amount, currency, customer data) and one or more payment attempts (individual interactions with the payment gateway). The payment transaction tracks the overall lifecycle — from created through paid, expired, or refunded. Each payment attempt tracks a single gateway interaction — from pending through success or failed.
This two-level model exists because a single payment transaction can involve multiple payment attempts. The customer might fail on the first try (wrong card, insufficient funds) and succeed on the second — the payment transaction stays open while individual payment attempts come and go.
For most integrations, check the state field in webhook payloads or the Checkout API response. The success states are paid, authorized, and cod. Everything else means the payment is incomplete or failed.
Payment Transaction States
| State | Description | Terminal? | Available Operations |
|---|---|---|---|
created | Payment transaction created via the Checkout API. Customer has not yet opened the payment link. | No | Cancel, Expire |
pending | Customer opened the payment link; request sent to the payment gateway. | No | Cancel, Expire |
attempted | Customer tried to pay but the payment attempt failed. Payment transaction remains open for retry (see Multi-Attempt Logic). | No | Cancel, Expire |
authorized | Funds reserved on the customer's bank account but not yet captured. Merchant must capture or void. | Yes | Capture, Void |
paid | Payment successful. Funds collected. | Yes | Refund |
cod | Cash on Delivery — payment marked as offline/cash. | Yes | Cancel |
failed | Payment failed definitively. No retry possible (multi-attempt exhausted or disabled). | Yes | — |
canceled | Administratively canceled by staff or via the Operations API. | Yes | — |
expired | Not paid before expiration date, or customer canceled on gateway page. | Yes | — |
invalided | Configuration change made the payment transaction unprocessable (missing currency, disabled gateway). | Yes | — |
refunded | Refund operation completed. This is a child payment transaction state. | Yes | — |
refund_queued | Refund sent to the payment gateway, awaiting confirmation. The gateway will send a webhook when the refund is processed. | No | Awaiting gateway confirmation |
refund_rejected | Gateway rejected the refund request. | Yes | — |
voided | Authorization reversed before the acquirer sent it for processing. Child payment transaction state. | Yes | — |
Payment Transaction Lifecycle
The diagram below shows the most common state transitions. For the complete list of all possible transitions, see the State Groups table.
Dashed arrows show that even failed and expired payment transactions can receive a delayed successful payment from the gateway (e.g., via automatic inquiry). Always handle webhook updates for payment transactions you consider "failed."
Payment Attempt States
Each payment attempt represents a single interaction with a payment gateway. A payment transaction can have one or many payment attempts.
| State | Description | Triggered By |
|---|---|---|
pending | Payment attempt created; request about to be sent to the payment gateway. | Customer initiates payment on checkout page |
success | Payment gateway confirmed the payment succeeded. | Gateway returns successful response |
failed | Payment attempt failed (insufficient funds, card declined, 3DS failure). | Gateway returns failure; or payment attempt times out |
canceled | Customer canceled on the payment gateway page (e.g., clicked "Back" on KNET). | Customer navigates away from gateway |
error | Error occurred creating the payment gateway link (connectivity, invalid config). | PSP link creation fails |
cod | Cash on Delivery payment acknowledged. | CoD gateway confirms offline payment |
How Payment Transactions and Payment Attempts Interact
When Payment Attempts Are Created
A new payment attempt is created each time the customer submits a payment on the checkout page. The payment attempt captures gateway-specific details: gateway_response, amount, fees, and reference_number. Each payment attempt belongs to exactly one payment transaction (accessed via payment_transaction.attempts).
How Payment Attempt Results Affect the Payment Transaction
Payment attempt state changes trigger payment transaction state changes, but the mapping is not 1:1. A failed payment attempt does not always mean a failed payment transaction.
| Payment Attempt Outcome | Multi-Attempt Enabled | Multi-Attempt Disabled |
|---|---|---|
success (purchase operation) | Payment transaction → paid | Payment transaction → paid |
success (authorize operation) | Payment transaction → authorized | Payment transaction → authorized |
cod | Payment transaction → cod | Payment transaction → cod |
failed | Payment transaction → attempted (retry available) | Payment transaction → failed (terminal) |
canceled | Payment transaction → attempted (retry available) | Payment transaction → expired |
error | Inquiry may resolve later | Payment transaction → failed |
Multi-Attempt Logic
Payment transactions created via the Checkout API or Invoice API support multiple payment attempts by default. When a payment attempt fails, the payment transaction moves to attempted and the customer can retry with a different card or payment method.
Multi-attempt behavior is controlled by two factors:
- How the payment transaction was created — payment transactions created via the Checkout API or Invoice API are eligible for multi-attempt. Those created via legacy APIs are not.
- MID configuration — each payment gateway has a
can_have_multiple_attemptssetting (enabled by default). If disabled, the payment transaction reaches a final state on the first payment attempt result, regardless of how it was created.
When multi-attempt is disabled (or the payment transaction was created via a legacy API), a failed or canceled payment attempt immediately transitions the payment transaction to a terminal state (failed or expired) — no retry.
The attempted state exists specifically for multi-attempt payment transactions. It signals "at least one payment attempt was made, but none succeeded yet — the customer can try again."
Payment transaction type (e.g., e_commerce, payment_request) determines the business flow. payment_type (e.g., one_off, auto_debit, save_card) determines the payment method behavior. Both types can use any payment_type — for example, both e_commerce and payment_request payment transactions can be auto_debit.
State Groups
These groupings are used by the Operations API, Webhooks, and Payment Status Query API to determine which actions are valid.
| Group | States | Used By |
|---|---|---|
| Success states | paid, authorized, cod | Trigger post-payment logic (webhooks, fulfillment) |
| Terminal states | paid, authorized, cod, failed, canceled, expired, invalided | No further customer action possible |
| Cancelable | created, pending, attempted, cod | Cancel operation |
| Expirable | created, pending, attempted | Expire operation or automatic expiration |
| Can acknowledge payment | created, pending, attempted, failed, expired | Gateway can still report success (delayed callback) |
| Inquirable | pending, attempted, failed, expired | Payment Status Query to check latest status |
| Child payment transaction states | paid, refunded, refund_queued, refund_rejected, voided | Created by operations on a parent payment transaction |
Child Payment Transactions
When an external operation (refund, capture, void) succeeds, Ottu creates a child payment transaction linked to the original parent. Child payment transactions have their own session_id, state, amount, and gateway response.
- Refund → child in
refundedstate. If the gateway queues the refund (pending confirmation), the child is created inrefund_queuedstate and transitions torefundedwhen the gateway confirms via webhook, or torefund_rejectedif the gateway rejects it. - Capture → child in
paidstate - Void → child in
voidedstate
Child payment transactions appear in the parent's webhook payload and can be retrieved via the Payment Status Query API. See Operation Events for webhook payloads.
FAQ
What's Next?
- Checkout API — Create payment transactions and track their state
- Payment Status Query — Check the latest payment transaction status with the gateway
- Operations — Refund, capture, void, cancel, and expire payment transactions
- Payment Events — Webhook payloads delivered on state changes
- Error Codes — Error responses from the API