New: Application API docs
Pick the API you are reading here — the Merchant API for your own store, the Application API for partner apps.
Everything you need to integrate with the Gini v2 Third-Party API.
List your orders, fetch a single order in full detail, and move an order through its lifecycle — every route is scoped to the calling signed merchant, so an integration only ever sees and mutates its own orders. Writes made through this API do not re-trigger the merchant's own outbound order webhook.
Returns the calling merchant's orders as a paginated collection, newest first. All query parameters are optional filters. List rows eager-load the customer, delivery address, and promo code only — order items and the influencer name are omitted from the list payload and appear on the single-order detail endpoint instead.
/api/v2.0/third-party/orders
| Field | Type | Required | Description |
|---|---|---|---|
search
|
string | Optional | Fuzzy match against the order number or numeric id (max 255 chars). |
status
|
string | Optional | Filter by order status. One of: pending, accepted, delivery_handoff, rejected, on_the_way, delivered, cancelled, refunded, returned, delayed, rwa, expired, temp_cancelled, received, in_warehouse. |
date
|
date | Optional | Filter by creation date (YYYY-MM-DD), matched against created_at. |
payment_method
|
string | Optional | Filter by payment method. One of: e_payment, aqsati, cash_on_delivery, qi_payment, ratibi, ishtrelk, post_paid, dots. |
state
|
integer | Optional | Filter by the state id of the delivery address frozen on the order. |
product_slug
|
string | Optional | Return only orders that contain an item whose product has this slug. |
late_orders
|
string | Optional | Set to 'enabled' to return only orders pending for more than 12 hours. Forces status to pending and overrides the status filter. Accepts enabled or disabled. |
shipping_method
|
string | Optional | Filter by shipping method. One of: free, delivery, pickup. |
delivery_company
|
integer | Optional | Filter by carrier id. 0 means self delivery and also matches orders with no carrier assigned yet, since a null carrier id is self delivery. |
handoff
|
string | Optional | handed (handed to the delivery company) or not_handed (still with the merchant). |
pre_order
|
string | Optional | only to return just pre-order orders, exclude to leave them out. |
per_page
|
integer | Optional | Results per page, 1-100. Defaults to 15. |
{
"data": [
{
"id": 5021,
"address": {
"id": 812,
"name": "Home",
"contact_phone": "+9647701234567",
"alt_contact_phone": null,
"city": 1,
"city_label": "Baghdad",
"state": 14,
"state_label": "Karrada",
"address": "Building 5, Floor 2, Street 14",
"latitude": "33.315000",
"longitude": "44.366000",
"created_at": "2026-02-10 18:22:41"
},
"customer": {
"id": 318,
"name": "Ahmed Ali",
"phone": "+9647701234567",
"email": "ahmed@example.com",
"avatar": "https://cdn.gini.iq/avatars/318.jpg",
"phone_verified_at": "2025-11-02T10:00:00.000000Z",
"is_verified": 1,
"is_active": 1
},
"is_pre_order": false,
"total_amount": "67500.00",
"promo_code": {
"promo_code_id": null,
"promo_code_created_by": "no promo code applied",
"code": "none",
"amount": "IQD 0",
"raw_amount": null
},
"discount_total_amount": "0.00",
"difference_amount": 67500,
"final_amount": 67500,
"shipping_cost": "5000.00",
"total_amount_with_shipping_cost": 72500,
"formatted_amounts": {
"final_amount": "IQD 67,500",
"total_amount": "IQD 67,500",
"discount_total_amount": "IQD 0",
"difference_amount": "IQD 67,500",
"shipping_cost": "IQD 5,000",
"total_amount_with_shipping_cost": "IQD 72,500",
"promo_code_amount": "IQD 0",
"total_after_promo_code": "IQD 67,500"
},
"status": "pending",
"status_label": "Pending",
"number": "5021",
"code": null,
"payment_method": "e_payment",
"payment_status": "pending",
"shipping_method": "delivery",
"shipped_date": null,
"completed_date": null,
"canceled_date": null,
"notes": null,
"months": null,
"aqsati_details": [
null
],
"created_at": "Feb 11, 2026 09:15"
}
],
"links": {
"first": "https://merchant.gini.iq/api/v2.0/third-party/orders?page=1",
"last": "https://merchant.gini.iq/api/v2.0/third-party/orders?page=12",
"prev": null,
"next": "https://merchant.gini.iq/api/v2.0/third-party/orders?page=2"
},
"meta": {
"current_page": 1,
"last_page": 12,
"per_page": 15,
"total": 173
}
}
Returns the full detail for a single order owned by the calling merchant, including line items with their product, discount and variant attributes, plus the influencer name. The {id} path segment is the numeric order id (there is no route-model binding — the order is looked up manually and scoped to the caller).
/api/v2.0/third-party/orders/{id}
{
"data": {
"id": 5021,
"influencer_name": "Sara Q",
"address": {
"id": 812,
"name": "Home",
"contact_phone": "+9647701234567",
"alt_contact_phone": null,
"city": 1,
"city_label": "Baghdad",
"state": 14,
"state_label": "Karrada",
"address": "Building 5, Floor 2, Street 14",
"latitude": "33.315000",
"longitude": "44.366000",
"created_at": "2026-02-10 18:22:41"
},
"customer": {
"id": 318,
"name": "Ahmed Ali",
"phone": "+9647701234567",
"email": "ahmed@example.com",
"avatar": "https://cdn.gini.iq/avatars/318.jpg",
"phone_verified_at": "2025-11-02T10:00:00.000000Z",
"is_verified": 1,
"is_active": 1
},
"items": [
{
"discount": null,
"product_id": 142,
"product_variant_id": 1167,
"product": {
"id": 142,
"name": "Wireless Headphones",
"slug": "wireless-headphones",
"sku": "WH-2026-001",
"price": 45000,
"final_price": 45000
},
"id": 8901,
"quantity": 1,
"unit_price": "45000.00",
"discount_unit_price": "45000.00",
"total_price": "45000.00",
"final_amount": 45000,
"discount_total_price": "45000.00",
"is_installment_same_price": 0,
"formatted_amounts": {
"unit_price": "IQD 45,000",
"discount_unit_price": "IQD 45,000",
"total_price": "IQD 45,000",
"discount_total_price": "IQD 45,000",
"final_amount": "IQD 45,000"
},
"additional": null,
"details": [
{
"label": "Color",
"value": "Red"
},
{
"label": "Size",
"value": "M"
}
]
}
],
"is_pre_order": false,
"total_amount": "67500.00",
"promo_code": {
"promo_code_id": null,
"promo_code_created_by": "no promo code applied",
"code": "none",
"amount": "IQD 0",
"raw_amount": null
},
"discount_total_amount": "0.00",
"difference_amount": 67500,
"final_amount": 67500,
"shipping_cost": "5000.00",
"total_amount_with_shipping_cost": 72500,
"formatted_amounts": {
"final_amount": "IQD 67,500",
"total_amount": "IQD 67,500",
"discount_total_amount": "IQD 0",
"difference_amount": "IQD 67,500",
"shipping_cost": "IQD 5,000",
"total_amount_with_shipping_cost": "IQD 72,500",
"promo_code_amount": "IQD 0",
"total_after_promo_code": "IQD 67,500"
},
"status": "pending",
"status_label": "Pending",
"number": "5021",
"code": null,
"payment_method": "e_payment",
"payment_status": "pending",
"shipping_method": "delivery",
"shipped_date": null,
"completed_date": null,
"canceled_date": null,
"notes": null,
"months": null,
"aqsati_details": [
null
],
"created_at": "Feb 11, 2026 09:15"
}
}
Transitions an order to a new status. The set of legal target statuses depends on the order's current status AND its fulfilment mode (pickup, gini delivery company, or merchant own delivery). An illegal transition returns 400 without mutating the order. Required body fields vary by target status: rejecting needs a reason, delivering needs the verification code. On success the endpoint returns a plain confirmation message rather than the order.
/api/v2.0/third-party/orders/{id}
| Field | Type | Required | Description |
|---|---|---|---|
status
|
string | Required | Target status. Accepted enum values: pending, accepted, delivery_handoff, rejected, on_the_way, delivered, cancelled, refunded, returned, delayed, rwa, expired, temp_cancelled, received, in_warehouse. The value must also be a legal transition from the order's current status (see the transition matrices in notes) or the request is rejected with 400. received and in_warehouse are reported by delivery courier scans: they can be filtered on, but not set through this endpoint. |
reject_reason_id
|
integer | Optional | Id from the reject_order_reasons table. Required when status is rejected; must reference an existing reason. |
reject_reason_notes
|
string | Optional | Free-text note (max 1000 chars). Required only when reject_reason_id is 8 (the 'other' reason); optional otherwise. |
{
"status": "rejected",
"reject_reason_id": 3,
"reject_reason_notes": "Item damaged in warehouse"
}
{
"data": {
"message": "Order status updated successfully."
}
}
Returns a printable HTML page for an order (receipt, invoice, or sticker) — meant to be opened in a browser or embedded in an iframe, not parsed as JSON. Because a browser navigation cannot send custom headers, this endpoint signs in the query string with a scheme distinct from the rest of the API, and it lives on the web host, not the api/v2.0/third-party base.
https://merchant.gini.iq/print/receipt/{order}
| Field | Type | Required | Description |
|---|---|---|---|
api_key
|
string | Required | Your API Client ID. |
timestamp
|
integer | Required | Unix time in seconds. Must be within 300 seconds of server time. |
signature
|
string | Required | HMAC-SHA256 of GET + PATH + TIMESTAMP (no body), keyed with your API secret. This differs from the header scheme, which also signs the request body. |
type
|
string | Optional | Which layout to render: receipt (default), invoice, or sticker. |
https://merchant.gini.iq/print/receipt/5021?api_key={api_client_id}×tamp=1739270400&signature={hmac_sha256_hex}
The valid reasons for rejecting an order — use an id here as the reject_reason_id when you transition an order to rejected. requires_note flags the reason that needs reject_reason_notes.
/api/v2.0/third-party/orders/rejection-reasons
Stamp an accepted, non-pickup order as handed to the delivery captain. 400 if the order is not accepted or is a pickup order.
/api/v2.0/third-party/orders/{id}/handoff
Retired: once an order is handed to delivery, the handoff cannot be undone. This endpoint always answers 400 with the message A handoff cannot be undone, or 404 if the order is not yours. It is kept so existing calls get a clear refusal.
/api/v2.0/third-party/orders/{id}/handoff/reset
Ask the delivery network to cancel an accepted or in-transit order. The order's status does not change here — Gini's delivery team reviews the request and resolves it through the normal flow.
/api/v2.0/third-party/orders/{id}/request-cancellation
| Field | Type | Required | Description |
|---|---|---|---|
reason
|
string | Required | Why the cancellation is being requested, max 1000 chars. |