تاجر جني
Which API?
Merchant API For merchants: manage your own catalogue, orders and finances through the v2 Third-Party API. Application API For partner apps: browse Gini merchants and products, send customers to checkout and follow their orders.

New: Application API docs

Pick the API you are reading here — the Merchant API for your own store, the Application API for partner apps.

Merchant dashboard
API reference
Checkout tokens

Application API

For partner applications: browse merchants and products, hand customers a checkout link, and follow the orders it creates.

Checkout tokens

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.

Create checkout token

This is a POST: the raw JSON body is part of the string to sign.

POST /api/third-party/v1/applications/checkout-tokens
Signed
Request body (JSON)
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.
Request
{
    "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"
}
Response 201 Created
{
    "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).
400 responses
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.
Token lifecycle

A token is single-use and bound to one customer:

From link to order
  • First, the customer opens the link. Gini validates the token and fills their cart with exactly the basket you sealed. The token is now bound to that customer.
  • Then the customer checks out. Gini re-verifies the cart, payment method and promo code against the token, then spends it.
Notes
  • One token = at most one order. A spent token is rejected. Issue one per checkout attempt.
  • The first customer to open it owns it. Treat the link as a per-customer secret and deliver it privately.
  • Editing the cart invalidates it — adding, removing or re-quantifying an item, swapping a variant, or changing the payment method or promo code.
Supplying the delivery address

Send address when you already know where the order goes; omit it and the customer picks from their own address book.

When you send it
  • The storefront hides its address picker and shows your values read-only.
  • The order's delivery address is built from exactly these values.
  • Shipping is priced from address.state.
  • shipping_method: pickup ignores it — a pickup order is not delivered anywhere.
We do not accept an address id
A token is not bound to a customer when it is issued — the customer is whoever opens the link — so there is no one to check an id against. Sending values means the address is yours and validated on its own terms.
Notes
  • You own correctness. We do not verify the address exists or matches the state id.
  • It is frozen at issue. To change it, issue a new token.
  • name and contact_phone reach the courier. Send the recipient's details when they differ from the account holder's.
What the token enforces
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_paid

post_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).

Redemption errors

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