تاجر جني
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
Getting started
Idempotency

API documentation

Everything you need to integrate with the Gini v2 Third-Party API.

Idempotency

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.

Why it matters

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.

Endpoints that accept a key
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.
Notes
  • The header is optional. A request without one behaves exactly as it always has, so nothing you have already built needs to change.
  • Endpoints that only read, update or delete do not need a key — repeating them has the same effect as sending them once.
  • POST /products/variants/generate takes no key either: it calculates combinations and stores nothing.
Sending a key

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.

cURL
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"
Notes
  • The Idempotency-Key header is not part of the signing string. Sign exactly what you signed before — METHOD, PATH, BODY, TIMESTAMP.
  • A retry needs a fresh X-TIMESTAMP and a fresh signature, because the original timestamp expires after 300 seconds. Only the idempotency key stays the same.
What each case returns
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.
Replayed response
HTTP/1.1 201 Created
Idempotency-Replayed: true
Content-Type: application/json

{
    "data": { "id": 412, "name": "Size", "type": "select" }
}
Rules worth knowing
  • A key can be replayed for 24 hours. After that it is forgotten and the same key would run as a fresh request, so do not use idempotency as a long-term deduplication store.
  • Keys are scoped to your merchant account. Another integrator using the same key never collides with yours.
  • Only a successful response is stored, which is enough — a call that did not return 2xx did not create anything.
  • Check for the Idempotency-Replayed header when you need to know whether your retry did the work or collected an earlier answer. It is absent on a normal response.
  • Generate the key before the first attempt, not on the retry. A key created after a timeout is a new key, and a new key is a new request.