Skip to content
Loading keys…

Payments

Initialize, retrieve, list and cancel payments via the Payments API.

The Payment (transaction) object represents a payment collection attempt. Its lifecycle goes from pending to succeeded (or failed). All routes share the base https://api.wajub.com.

Before you begin

Create a payment from your server with your private key (sk. or sk_test.), or from a browser with your public key (pk. or pk_test.). Both are in the Wajub dashboard.

Marketplaces: acting on behalf of a subaccount

Platforms can attribute a payment to a connected subaccount by sending an X-Sync header alongside their own key. See Subaccounts for the rules and error cases.

Endpoints

MethodPathDescription
POST/paymentsInitialize a payment
POST/payments/{id}Charge a payment from your server
POST/payments/{id}/confirmConfirm a step of a charge (code, PIN, provider window)
POST/payments/{id}/splitsCharge the next instalment (Mobile Money in live)
POST/payments/{id}/closeClose a payment paid in part in instalments
GET/payments/{id}Retrieve a payment
GET/paymentsList payments
DELETE/payments/{id}Cancel a payment
GET/payments/{id}/refundsList refunds for a payment
PATCH/payments/{id}Change a prepared payment's amount
POST/payments/{id}/activateCreate a prepared payment once the order is placed

Prepared payments

A payment created with deferred: true is only prepared. It exists for payment fields mounted on your checkout before the order does, and it stays out of everything else until you activate it.

PreparedActivated
In GET /payments and the dashboardNoYes
GET /payments/{id}Reads as pending, then expired or cancelled; answers 404 an hour after it expired or was cancelledThe payment
payment.createdNot sentSent on activation
Amount and currencyPATCH /payments/{id}Fixed
Can be chargedNoYes
DELETE /payments/{id}Ends the session, no webhookCancels, sends payment.cancelled

Activation keeps the id and the session token you already handed to the browser. A prepared payment that is never activated expires with its session, and no trace of it reaches your payments or your webhook endpoint, as long as you sent no customer while preparing it: that customer is created, with its customer.created.

The Payment object

Create response vs. retrieval response

The POST /payments (create) response includes two additional fields, authorization_url and authorization_token. That are not present on subsequent retrieval responses. These are the two most important fields in the create response.

A field with no value is left out of the response rather than sent as null.

idstringoptional
Unique transaction identifier: trx_ followed by 20 characters, trx_test_ in sandbox. This is the identifier to use in every API call (GET /payments/{id}, POST /refunds body, etc.).
authorization_urlstringoptional
**Returned by POST /payments only.** The hosted payment page URL to redirect your customer to. An opaque session URL, do not parse or construct it manually.
authorization_tokenstringoptional
**Returned by POST /payments only.** Browser-safe session token scoped to this payment. Pass as sessionId to Wajub Components for embedded checkout.
referencestringoptional
The reference you sent on POST /payments: your own order reference, stored and returned as is. It is not an API identifier, and Wajub never checks that it is unique.
statusenumoptional
Current state: pending, processing, succeeded, failed, cancelled, expired, partial, refunded, partially_refunded.
amountnumberoptional
Amount in the major unit of the currency (e.g. 25000 = 25 000 XAF).
amount_paidnumberoptional
What the payer has paid so far. Below amount while a payment paid in instalments is partial, and on such a payment closed before its last instalment (POST /payments/{id}/close).
currencystringoptional
ISO 4217 code of any currency Wajub has active. Which channels can collect it, and in which currency they settle, is on [Coverage](/resources/coverage); Sierra Leone is SLL.
channelstring?optional
Payment channel used (e.g. cm.mtn, cm.orange, sn.wave).
payment_methodobject?optional
Resolved payment method: { channel, account }.
descriptionstring?optional
Label visible to the customer on the payment page.
itemsarray?optional
Line items passed at initialization, each with name, description and quantity. Displayed on the payment page, they carry no price and never change amount. On a payment made on an invoice's page, they are the invoice's lines, each with its unit_price and its total, net of its discount and tax included; from API version 2026-10-12, an invoice-wide discount closes the list as an item with kind: discount, name: Discount, a negative total, and quantity and unit_price at null.
taxobject?optional
Tax details when tax was applied to a live payment: { amount, taxable_amount, rate, name, country, inclusive }. Never present in sandbox.
failure_reasonstring?optional
Why the payment failed: the code of the provider that refused the last attempt, passed through, or a code of Wajub's own (see [Failure Reasons](/api/failure-reasons#failed-payments)). Present only when status=failed.
failure_messagestring?optional
One sentence explaining failure_reason, for your logs and your support team. Present only when status=failed.
receipt_urlstring?optional
A permanent, signed link to the payer's receipt. Present once the payment has succeeded, unless you turned receipts off in the Dashboard.
customerobject?optional
The customer: { id, name, email, phone }.
shipping_addressobject?optional
The customer's shipping address: { address_line1, address_line2, city, state, postal_code, country }.
billing_addressobject?optional
The customer's billing address, same fields.
metadataobject?optional
Free-form data you passed at creation.
invoicestring?optional
The id of the invoice this payment settles, when it was made on an invoice's page. Absent otherwise.
linkstring?optional
The id of the [payment link](/api/payment-links) this payment was made through. Absent otherwise.
clientobject?optional
Where the payer paid from, as their app or page reports it: { name, version, platform, os_version }. name is hosted-checkout, wajub-js, wajub-android, wajub-ios, wajub-flutter, wajub-react-native or the name another app reports, and platform one of android, ios, web, macos, windows or linux. version, platform and os_version may be null. Set by the payer's first attempt, never by a charge from your server, and for information only. Not returned to a publishable key.
callbackstring?optional
Redirect URL after payment.
bearerstringoptional
Who bears the Wajub fee: merchant, or customer when the payer pays it on top of amount.
expires_atdatetime?optional
Until when the payer can pay, set with expires.in at creation. Past it the payment turns expired, unless a charge is under way: the payment then waits for that charge's outcome. See [Expiry](/payments/lifecycle#expiry).
sandboxbooleanoptional
true for test-mode transactions.
credited_atdatetime?optional
When the funds were credited to your balance.
created_atdatetimeoptional
ISO 8601 creation timestamp, in UTC (+00:00).
updated_atdatetimeoptional
ISO 8601 timestamp of the last change.

Lifecycle

Events

EventTrigger
payment.createdPayment initialized, or a prepared payment activated
payment.processingPayment submitted to the provider
payment.succeededPayment successfully validated
payment.failedPayment failed (see failure_reason)
payment.attempt_failedAn attempt was refused at once and the payment is pending again
payment.expiredThe payment's deadline (expires_at) passed before it was paid
payment.cancelledPayment cancelled with DELETE /payments/{id} or the Cancel button of the hosted page
payment.split.processingAn instalment was sent to the payer
payment.split.succeededAn instalment was paid, and credited to your balance
payment.split.failedAn instalment was declined; the next call charges it again

See the full event catalog for refund-specific events. A refund on a payment does not re-emit a payment.* event, it emits refund.* events instead.

What did you think of this content?