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.
Retry a creating request safely. Send the same Idempotency-Key on the retry and Gini returns the original response instead of creating a second product, attribute, export or order.
When a connection drops you cannot tell whether the request never arrived or the response was lost on the way back. Retrying is the only sensible move, and on a creating endpoint that retry is a duplicate. An idempotency key removes the guess: the second call returns the first call's answer, and nothing is created twice.
| Endpoint | What a duplicate would cost you |
|---|---|
| POST /products | A second product with a second SKU. |
| POST /products/bulk | The whole batch imported twice. |
| POST /products/stock-updates | The same prices, quantities and switches queued and written twice. |
| POST /products/bulk-delete | A second run, and a second webhook reporting nothing deleted. |
| POST /attributes | A duplicate attribute, or a 422 on the unique name. |
| POST /products/{sku}/addons | A duplicate add-on on the product. |
| POST /discounts | A duplicate discount. |
| POST /collections | A duplicate collection. |
| POST /influencers | A duplicate influencer, or a 422 on the unique code. |
| POST /branches | A duplicate branch. |
| POST /operators | A duplicate operator, or a 422 on the unique name/email. |
| POST /exports/orders | A second export job and a second file. |
| POST /exports/products | A second export job and a second file. |
| POST /exports/abandoned-carts | A second export job and a second file. |
| POST /exports/wholesale-orders | A second export job and a second file. |
| POST /exports/stock-template | A second export job and a second file. |
| POST /wholesale/cart | The quantity added to your cart twice. |
| POST /wholesale/orders/buyer | A duplicate wholesale order. |
Generate one key per request you intend to make — a UUID is ideal — and reuse it only when retrying that same request. The key is 8 to 255 printable ASCII characters.
TIMESTAMP=$(date +%s)
BODY='{"name":"Size","type":"select","values":["S","M","L"]}'
IDEMPOTENCY_KEY=$(uuidgen)
SIGNING_STRING="POST/api/v2.0/third-party/attributes${BODY}${TIMESTAMP}"
SIGNATURE=$(echo -n "$SIGNING_STRING" | openssl dgst -sha256 -hmac "$API_CLIENT_SECRET" | cut -d' ' -f2)
curl -X POST https://app.gini.iq/api/v2.0/third-party/attributes \
-H "X-API-KEY: $API_CLIENT_ID" \
-H "X-SIGNATURE: $SIGNATURE" \
-H "X-TIMESTAMP: $TIMESTAMP" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d "$BODY"
| Situation | Response |
|---|---|
| A key you have not used before | The request runs normally. |
| The same key, the same request, after the first one succeeded | The original response, byte for byte, with the header Idempotency-Replayed: true. Nothing runs a second time. |
| The same key while the first request is still running | 409 Request already in progress. Wait a moment and retry to collect the original response. |
| The same key with a different body | 422 Idempotency-Key already used. This almost always means a key was not rotated between two different requests. |
| The same key after the first attempt failed | The request runs normally. A failed call does not spend the key, so you can correct the payload and retry with the same one. |
| A key shorter than 8 characters, or with a space in it | 400 Invalid Idempotency-Key. |
HTTP/1.1 201 Created
Idempotency-Replayed: true
Content-Type: application/json
{
"data": { "id": 412, "name": "Size", "type": "select" }
}