How a payment flows
How a payment flows
A payment moves through a predictable lifecycle:
- Create a payment intent — describe amount, currency and customer.
- Start an attempt — pick a method and country; Orqex routes it to the best gateway.
- Resolve the next action — the customer may need to act (OTP, redirect, QR, approval).
- Completion — the intent reaches
completed,failedorexpired; a webhook fires.
Gateways & gateway accounts
Gateways & gateway accounts
A gateway is an integration with a payment provider (mobile money, cards, wallets,
bank transfer, crypto). A gateway account is your credentials for one provider,
configured on your project — Orqex never holds funds, it routes to your account.Each account advertises the methods and currencies it can serve, per
environment. You connect accounts in the
dashboard.
Orchestration & failover
Orchestration & failover
Routing rules map a method + country to a primary gateway account and an optional
fallback. Your project’s orchestration strategy decides how Orqex chooses among
eligible accounts (follow your rules, optimise for success, or distribute load).If the primary gateway fails for a transient reason, Orqex automatically re-runs the
payment against a suitable backup. The resulting attempt is flagged
is_fallback: true —
you just read the final status.Payment intents
Payment intents
A payment intent is the money you want to collect. It carries the amount, currency,
customer and metadata, and moves through
pending → completed / failed / expired
(and refunded / partially_refunded). Create one, then drive it with attempts.Amounts are sent in major units (e.g. 50) and returned as an amount object whose
value is in minor units (e.g. 5000).Payment attempts
Payment attempts
A payment attempt is one execution of an intent against a gateway account. An intent
can have several (a new method, a retry, or an automatic failover). Each attempt has a
status (processing, action_required, completed, failed, cancelled), the
method used, the gateway transaction, and a failure object when it fails.A failed attempt is not an API error — the request succeeds and the failure is
reported on the attempt.Next actions
Next actions
When a method needs the customer to act, the attempt exposes a
next_action whose
type tells you what to render:type | What to do |
|---|---|
redirect_to_url | Send the customer to url. |
embed_iframe | Embed url in an iframe. |
collect_otp | Collect an OTP, then call confirm. |
approve_on_phone | Ask the customer to approve on their phone. |
scan_qr_code | Display content / image_url as a QR code. |
display_payment_instructions | Show the listed fields. |
complete_with_sdk | Hand off to a client-side SDK. |
none | Nothing to do; poll the status. |
Idempotency
Idempotency
Send an
X-Idempotency-Key header (8-128 chars) on writes so a retried request is never
processed twice — replays return the original response with X-Idempotent-Replayed: true.
The PHP SDK generates and reuses a key automatically across its retries.Pagination
Pagination
List endpoints are cursor paginated. Each response carries a
pagination object with
next_cursor / next_page_url and has_more_pages. Pass next_cursor as the cursor
query parameter (max per_page is 100) to fetch the next page.Errors
Errors
The API uses conventional HTTP status codes with a JSON body; validation failures include
a per-field
errors map. A declined payment is reported on the attempt’s failure object
(code + human-readable message), not as an HTTP error.