New: Application API docs
Pick the API you are reading here — the Merchant API for your own store, the Application API for partner apps.
For partner applications: browse merchants and products, hand customers a checkout link, and follow the orders it creates.
Seals a checkout intent — basket, payment method, optional promo code, optional delivery address — into an opaque token. Hand it back to Gini in your deeplink or hand-off flow; only Gini's servers can read it. Tokens expire after 60 minutes.
This is a POST: the raw JSON body is part of the string to sign.
/api/third-party/v1/applications/checkout-tokens
| Field | Type | Required | Description |
|---|---|---|---|
products
|
object[] | Required | 1–100 items. Every product must belong to one of your merchants — otherwise the whole request is a 400. |
products.*.product_id
|
integer | Required | Existing product id. |
products.*.variant_id
|
integer | Optional | A variant of that product. A variant of a different product is a 400. |
products.*.quantity
|
integer | Optional | 1–1000, default 1. Checked against stock at issue time — the variant's stock when variant_id is sent, the product's otherwise. Duplicate lines are summed; pre-order products skip the check. Over-stock → 400 with the available count. |
payment_method
|
string | Required | e_payment, aqsati, cash_on_delivery, ratibi, dots, qi_payment or post_paid — and enabled for your application. A valid but not-enabled method is a 400. |
shipping_method
|
string | Optional | free, delivery or pickup. Returned to our storefront, which pre-selects and locks it. Omit to let the customer choose. |
promocode
|
string | Optional | Max 64. Sealed as-is; not validated against campaigns at issue time. |
address
|
object | Optional | The delivery address as values. When sent, it becomes the order's address and the customer is never asked for one. See Supplying the delivery address below. |
address.name
|
string | Optional | Required with address. Recipient name, max 255. Passed to the courier — the person receiving the parcel. |
address.contact_phone
|
string | Optional | Required with address. Recipient phone, max 32. The number the courier calls. |
address.alt_contact_phone
|
string | Optional | A second number for the courier, max 32. |
address.address
|
string | Optional | Required with address. Street line, max 1000 — building, street, landmark. |
address.state
|
integer | Optional | Required with address. Gini state id from /states. Load-bearing: shipping is priced from it — a wrong id gives a wrong fee, or a checkout error when the merchant does not deliver there. |
address.state_label
|
string | Optional | Display name of the state, max 255. Not used for pricing. |
address.city
|
integer | Optional | Gini district id, from /states?state_id=N. |
address.city_label
|
string | Optional | Display name of the district, max 255. |
address.latitude
|
number | Optional | −90…90. Map pin only. |
address.longitude
|
number | Optional | −180…180. Map pin only. |
external_id
|
string | Optional | Max 255. Your own reference — an order, cart or basket id from your system. Stored as sent, echoed on every order webhook, filterable at GET /orders?external_id=. Need not be unique. |
{
"products": [
{
"product_id": 266401,
"variant_id": 27884,
"quantity": 2
},
{
"product_id": 4
}
],
"payment_method": "cash_on_delivery",
"shipping_method": "delivery",
"promocode": "SUMMER10",
"address": {
"name": "Ali",
"contact_phone": "07800000000",
"address": "Street 14, House 7",
"state": 1,
"state_label": "Baghdad",
"city": 12,
"city_label": "Karrada",
"latitude": 33.3152,
"longitude": 44.3661
},
"external_id": "ORD-9001"
}
{
"token": "eyJpdiI6IjF...opaque...",
"cart_id": 4821993017,
"external_id": "ORD-9001",
"shipping_method": "delivery",
"has_address": true,
"expires_at": "2026-07-30T15:34:19+00:00"
}
| Field | Notes |
|---|---|
| token | Opaque. Do not parse or modify it — store it and pass it back whole. |
| cart_id | A random id minted with the token. It comes back on the order.created webhook only, so you can tie the order to this cart. null on order.status_updated. |
| external_id | Echoed. Prefer it over cart_id when you have your own reference — it is yours, durable, and present on every webhook. |
| shipping_method, has_address | Confirmations of what was recorded. has_address: false on a request that did send an address means it was dropped (only happens when the object was empty). |
| message | Cause |
|---|---|
Payment method not enabled for this application |
Valid method, not provisioned for you. |
One or more products are not available for this application |
A product is outside your scope, or does not exist. |
One or more variants do not belong to the given product |
variant_id belongs to another product. |
Insufficient stock for product {id} (+ available) |
Quantity above stock. |
A token is single-use and bound to one customer:
Send address when you already know where the order goes; omit it and the
customer picks from their own address book.
| Field | At checkout |
|---|---|
| products | Enforced. The cart must equal the sealed basket, or the order is rejected. |
| payment_method | Enforced. A different method is rejected. |
| promocode | Enforced. Adding, dropping or changing it is rejected. |
| address | Overrides anything the storefront sends. Ignored for pickup. |
| shipping_method | Advisory. Pre-selected and locked in the storefront, but a different value is not rejected server-side. Do not rely on it as a guarantee. |
| external_id | Not validated. Stored, echoed, filterable. |
post_paidpost_paid collects nothing at checkout — your application is billed later. It is therefore
token-only: a customer can never select it themselves, and it must be explicitly enabled for
your application (a blank configuration does not grant it).
Shown to the customer, not returned to you — useful when supporting an integration:
| Key | Meaning |
|---|---|
| errors.invalid_token | Not decryptable, tampered with, or an older token format |
| errors.token_has_expired | Older than 60 minutes |
| errors.checkout_token_already_used | Already spent on an order |
| errors.checkout_token_not_yours | Opened by a different customer |
| errors.checkout_token_mismatch | Cart, payment method or promo code no longer match |
| errors.checkout_token_products_unavailable | A product went out of stock or invisible since issue |