Skip to content

Idempotency ​

POST /api/v1/merchant/orders requires:

http
Idempotency-Key: <deterministic-caller-key>

The key is scoped to your API key and this operation. Store a hash of the request body with it.

Callers must reuse the same key for retries of the same logical request. Do not generate a random UUID on every attempt.

RetryResult
Same key, same body, completedOriginal successful response
Same key, different body409 MERCHANT_API_IDEMPOTENCY_CONFLICT
Concurrent same key, fresh STARTEDOne execute; the other waits (~2s) and replays or gets 409 MERCHANT_API_IDEMPOTENCY_IN_PROGRESS
Stale STARTED (lease expired), same hashAtomic reclaim; request runs again
Failed request (4xx/5xx after start)The STARTED row is deleted; you may retry

externalOrderId is a second safety net. The same id on this API client cannot create two Chuchu orders. A later request with the same id and incompatible commercial data returns 409 EXTERNAL_ORDER_CONFLICT.

You may use your order number as the idempotency key, but it is a request-retry key, not a substitute for externalOrderId.

Crash recovery ​

A process crash can leave STARTED. Each STARTED row has startedAt, lastAttemptAt, and leaseExpiresAt (30 seconds from the last attempt).

Reclaim is a single UPDATE ... WHERE status = STARTED AND leaseExpiresAt <= now AND requestHash = :hash. Two retries cannot both win.

Retention ​

Completed records and abandoned (lease-expired) STARTED rows are kept for 7 days, then may be deleted. Fresh STARTED rows whose lease has not expired are never deleted.

bash
pnpm merchant-api:idempotency-cleanup -- --dry-run
pnpm merchant-api:idempotency-cleanup -- --retention-days=7

Do not delete rows with ad-hoc SQL.

Public documentation. No login.