Creates an instalment order and returns the hosted payment URL to redirect the customer to.
This is the first call of every online checkout. Requires scope orders:write.
The journey. The order is created awaiting checkout (status: "AwaitingCheckout") and the
customer completes it on the hosted page: phone verification, identity (Nafath), the credit decision,
plan choice, contract and the first instalment. Nothing is decided at this call — a first-time
customer is never refused here. The page opens in the language of your Accept-Language header
(Arabic by default). When the customer finishes, the order is Confirmed, your webhook fires
(order.confirmed), and the customer is sent to your merchantUrl.success; a decline, an expiry (the
page is valid for two hours) or a cancellation goes to failure / cancel.
Store the returned installmentId (the Qasimha order id) against your own orderReferenceId —
all later order operations (capture, fulfil, refund) use it.
Example request (abridged):
{
"orderReferenceId": "MERCHANT-ORDER-12345",
"totalAmount": 1200.00,
"currencyCode": "SAR",
"countryCode": "SA",
"description": "Order #12345",
"paymentType": "pay_by_instalments",
"instalments": 4,
"items": [
{ "referenceId": "SKU-1", "name": "Wireless Headphones", "type": "physical",
"quantity": 1, "unitPrice": 1200.00, "totalAmount": 1200.00 }
],
"consumer": { "firstName": "Noura", "lastName": "Al-Shammari",
"phoneNumber": "+9665XXXXXXXX", "email": "[email protected]" }
}Example response (201):
{
"success": true,
"code": "SESSION_CREATED",
"data": {
"installmentId": "0d3f...e823",
"providerSessionId": "sess_...",
"paymentUrl": "https://.../checkout/...",
"status": "AwaitingCheckout"
}
}Return URLs (optional): merchantUrl { success, failure, cancel, notification } — where the
hosted checkout sends the shopper afterwards. Each URL must be absolute, at most 1024 characters
and carry no fragment; https, http only on localhost / 127.0.0.1, or a custom app scheme
(myshop://…) for a mobile app. success and failure go together; cancel defaults to
failure; notification is reserved and refused. The page appends orderId, orderReferenceId
and status (confirmed on success; declined, expired or failed on failure; cancelled) to
the URL's own query string. A return is a navigation, not a proof — confirm with
GET /merchant/orders/{orderId} before treating the order as paid.
The basket has to add up. Every line is stored as you send it — sku, type, imageUrl,
taxAmount and discountAmount included — and the amounts are reconciled before anything is
financed:
item.totalAmount=quantity × unitPrice − item.discountAmounttotalAmount= Σitem.totalAmount+taxAmount+shippingAmount−discountAmount
Both to the halala. quantity must be at least 1, no amount may be negative, and currencyCode
must be SAR.
Idempotency: send an Idempotency-Key header (a fresh UUID v4 per order attempt) and reuse it
on retries — a retry replays the original answer (Idempotent-Replay: true) instead of creating a
second order. 409 REQUEST_IN_PROGRESS while the first attempt is still running (retry shortly);
422 IDEMPOTENCY_KEY_REUSED if the same key is sent with a different body.
Errors: 400 VALIDATION_ERROR (field details in errors, including which line failed),
401 missing/invalid key, 403 key lacks orders:write, 409 MERCHANT_SUSPENDED,
429 rate limited.
400 MERCHANT_REQUIRED — the order is always created against a merchant and assessed by that
merchant's policy. An API key or a portal token identifies its own merchant, so any merchantId
in the body is ignored. A back-office admin token carries no merchant and must name one.
409 DUPLICATE_ORDER_REFERENCE — orderReferenceId is already in use. This is the double-submit
answer: when the existing order is yours, data carries its installmentId and paymentUrl, so
send the shopper back to the checkout already open rather than creating a second order.
422 ORDER_DECLINED — only on a deployment still running the earlier external-provider journey,
where the decision was made at creation: the order was created but not approved, so there is no
session to pay. On the hosted journey the decision is made on the page, so 201 always carries a
paymentUrl.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
