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.
Manage the attribute-combination SKUs of a product — preview the cartesian-product matrix, upsert variants non-destructively, and read or delete individual variants. Every endpoint is HMAC-signed and scoped to your own catalog: the product is resolved by SKU or numeric id from the caller's own products, and any submitted attribute must belong to the same merchant. The v2 API exposes only the attribute-based variant system; the legacy colors/sizes endpoint from v1 does not exist here.
Takes a set of attributes with their values and returns every possible combination (cartesian product) as unsaved variant rows with null sku/price/quantity. Use it to preview the matrix before filling in prices/stock and posting back to the save endpoint. Nothing is persisted.
/api/v2.0/third-party/products/variants/generate
| Field | Type | Required | Description |
|---|---|---|---|
attributes
|
array | Required | Array of attribute definitions to combine (min 1). |
attributes.*.attribute_id
|
integer | Required | ID of an existing product attribute (must exist in product_attributes). |
attributes.*.name
|
string | Required | Display name of the attribute, echoed back on each combination (e.g. Color). |
attributes.*.values
|
array | Required | The values to combine for this attribute (min 1). |
attributes.*.values.*
|
string | Required | A single attribute value (e.g. Red). |
{
"attributes": [
{
"attribute_id": 1,
"name": "Color",
"values": [
"Red",
"Blue"
]
},
{
"attribute_id": 2,
"name": "Size",
"values": [
"S",
"M"
]
}
]
}
{
"data": [
{
"sku": null,
"price": null,
"quantity": null,
"attributes": [
{
"attribute_id": 1,
"value": "Red",
"name": "Color"
},
{
"attribute_id": 2,
"value": "S",
"name": "Size"
}
]
},
{
"sku": null,
"price": null,
"quantity": null,
"attributes": [
{
"attribute_id": 1,
"value": "Red",
"name": "Color"
},
{
"attribute_id": 2,
"value": "M",
"name": "Size"
}
]
},
{
"sku": null,
"price": null,
"quantity": null,
"attributes": [
{
"attribute_id": 1,
"value": "Blue",
"name": "Color"
},
{
"attribute_id": 2,
"value": "S",
"name": "Size"
}
]
},
{
"sku": null,
"price": null,
"quantity": null,
"attributes": [
{
"attribute_id": 1,
"value": "Blue",
"name": "Color"
},
{
"attribute_id": 2,
"value": "M",
"name": "Size"
}
]
}
]
}
Create and update multiple variants for a product in one request. To create a variant, omit the id (image required). To update, include the id (image optional — omitted keeps the existing one). Variants not present in the payload are left unchanged (non-destructive — unlike the dashboard's full-matrix reconcile). The product is resolved by SKU or numeric id from the caller's catalog.
/api/v2.0/third-party/products/{sku}/variants
| Field | Type | Required | Description |
|---|---|---|---|
variants
|
array | Required | Array of variant objects to create or update (min 1). |
variants.*.id
|
integer | Optional | Existing variant ID — include to update, omit to create. Unknown IDs on this product are silently skipped. |
variants.*.sku
|
string | Required | Variant SKU. Must be unique within your account, across your own products and product_variants — ignoring this variant on update, and ignoring its own parent product, so a single-variant product may reuse its parent SKU. Spaces are normalized to hyphens. |
variants.*.price
|
numeric | Required | Variant price. Minimum is config services.product.min_price (PRODUCT_MIN_PRICE, default 0). |
variants.*.quantity
|
numeric | Required | Available stock quantity (0 or greater). |
variants.*.b2b_price
|
numeric | Optional | Optional B2B/wholesale price (0 or greater). Stored as decimal:2. |
variants.*.image
|
file | Optional | Variant image. Required when creating (no id); optional on update where omitting keeps the current image. Must be an uploaded file: jpg, jpeg, png, or webp, max 5120 KB (5MB). |
variants.*.attributes
|
array | Required | Attribute assignments for this variant (min 1). Every attribute must belong to the product's merchant. |
variants.*.attributes.*.attribute_id
|
integer | Required | Product attribute ID (must exist in product_attributes and be owned by the merchant). |
variants.*.attributes.*.value
|
string | Required | The attribute value for this variant (e.g. Red). |
// multipart/form-data — send as POST with _method=PUT because file uploads are involved.
// JSON-equivalent of the fields:
{
"variants": [
{
"id": 58,
"sku": "WH-RED-S-V2",
"price": 47000,
"quantity": 25,
"b2b_price": 42000,
"image": "<binary file — optional on update>",
"attributes": [
{ "attribute_id": 1, "value": "Red" },
{ "attribute_id": 2, "value": "S" }
]
},
{
"sku": "WH-BLUE-M",
"price": 48000,
"quantity": 30,
"image": "<binary file — required on create>",
"attributes": [
{ "attribute_id": 1, "value": "Blue" },
{ "attribute_id": 2, "value": "M" }
]
}
]
}
{
"data": {
"created": 1,
"updated": 1,
"variants": [
{
"id": 59,
"product_id": 142,
"image": "https://s3.amazonaws.com/qi/product_variants/9f2c1b.jpg",
"sku": "WH-BLUE-M",
"price": 48000,
"b2b_price": null,
"formatted_amounts": {
"price": "IQD 48,000",
"discounted_price": "IQD 0"
},
"quantity": 30,
"attributes": [
{
"id": 1,
"product_variant_id": 59,
"product_attribute_id": 1,
"value": "Blue",
"name": "Color"
},
{
"id": 2,
"product_variant_id": 59,
"product_attribute_id": 2,
"value": "M",
"name": "Size"
}
]
},
{
"id": 58,
"product_id": 142,
"image": "https://s3.amazonaws.com/qi/product_variants/abc123.jpg",
"sku": "WH-RED-S-V2",
"price": 47000,
"b2b_price": "42000.00",
"formatted_amounts": {
"price": "IQD 47,000",
"discounted_price": "IQD 42,300"
},
"quantity": 25,
"attributes": [
{
"id": 1,
"product_variant_id": 58,
"product_attribute_id": 1,
"value": "Red",
"name": "Color"
},
{
"id": 2,
"product_variant_id": 58,
"product_attribute_id": 2,
"value": "S",
"name": "Size"
}
]
}
]
}
}
Returns a paginated list of the product's variants, newest first. The product can be identified by SKU or numeric ID and must belong to the caller. Each variant includes its image URL, price, optional B2B price, formatted amounts, stock, and pivoted attributes.
/api/v2.0/third-party/products/{sku}/variants
| Field | Type | Required | Description |
|---|---|---|---|
page
|
integer | Optional | Page number to retrieve (default 1). |
{
"data": [
{
"id": 58,
"product_id": 142,
"image": "https://s3.amazonaws.com/qi/product_variants/abc123.jpg",
"sku": "WH-RED-S",
"price": 45000,
"b2b_price": "40000.00",
"formatted_amounts": {
"price": "IQD 45,000",
"discounted_price": "IQD 40,500"
},
"quantity": 30,
"attributes": [
{
"id": 1,
"product_variant_id": 58,
"product_attribute_id": 1,
"value": "Red",
"name": "Color"
},
{
"id": 2,
"product_variant_id": 58,
"product_attribute_id": 2,
"value": "S",
"name": "Size"
}
]
}
],
"links": {
"first": "https://api.qi.iq/api/v2.0/third-party/products/WH-001/variants?page=1",
"last": "https://api.qi.iq/api/v2.0/third-party/products/WH-001/variants?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://api.qi.iq/api/v2.0/third-party/products/WH-001/variants",
"per_page": 15,
"to": 6,
"total": 6
}
}
Returns a single variant of the given product by its numeric variant ID, including its attributes and discount-formatted amounts. Both the product (by SKU or ID) and the variant must belong to the caller.
/api/v2.0/third-party/products/{sku}/variants/{variant}
{
"data": {
"id": 58,
"product_id": 142,
"image": "https://s3.amazonaws.com/qi/product_variants/abc123.jpg",
"sku": "WH-RED-S",
"price": 45000,
"b2b_price": "40000.00",
"formatted_amounts": {
"price": "IQD 45,000",
"discounted_price": "IQD 40,500"
},
"quantity": 30,
"attributes": [
{
"id": 1,
"product_variant_id": 58,
"product_attribute_id": 1,
"value": "Red",
"name": "Color"
},
{
"id": 2,
"product_variant_id": 58,
"product_attribute_id": 2,
"value": "S",
"name": "Size"
}
]
}
}
Permanently deletes a variant of the given product (by numeric variant ID). Detaches its attribute pivots first. Blocked when the variant has been sold in any order.
/api/v2.0/third-party/products/{sku}/variants/{variant}
{
"message": "Variant deleted successfully."
}