Idempotency Keys
This API surface is for integration partners building on top of the Rokt network. Rokt ecommerce partners integrating placements on their own checkout should use the Rokt Ecommerce developer docs instead.
Every write call to the Partnerships API requires an Idempotency-Key header. The server stores (parent_account_id, account_id, idempotency_key) as a UNIQUE constraint and returns the cached response of the first call for the lifetime of the cache window. Use a fresh UUID per logical operation; retry by re-sending the same key.
ContractDirect link to Contract
- Header is required on every write. Missing it returns
400. - Format is UUID. Use any RFC 4122 variant — UUIDv4 is fine. Pick something high-entropy; never reuse a key for a different logical write.
- Scope is per managed account. The same key on two different
account_ids does not collide. - TTL is ~24 hours. Matches the idempotency cache retention window. After expiry, the same key is treated as a fresh request.
Treat Idempotency-Key as a server-side dedup token, not as data:
- One key per logical write. A fresh retry of the same logical write reuses the same key — but a new merchant operation gets a new key.
- Never embed PII (email, name, order ID) in the key. Keys appear in server logs and audit trails.
- Keys are not secret, but they are not authorization either — possession of a key does not grant access to a write. The token +
account_idstill gate the call. - Don't reuse keys across different endpoints or different
account_ids, even though the scope guard makes it safe. Mixing scopes makes your own retry log harder to debug.
curl -X PUT https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
-H "Authorization: Bearer $ROKT_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d @mcl.json
Same key, different bodyDirect link to Same key, different body
If you reuse a key with a different body, the server returns the first call's response — it does not re-process with the new body. This is by design: Idempotency-Key collapses retries, it does not version edits.
Mutating a payload and resending under the same key is silently ignored. If you want a new write to take effect, use a new key.
Outcome tableDirect link to Outcome table
| Scenario | HTTP | What returns |
|---|---|---|
| First call | 200 / 201 | Fresh response |
| Retry, original completed | 200 / 201 | Cached response (byte-identical body) |
| Retry, original failed transiently | matches original failure | Cached failure; server retries up to 3 times internally |
| Retry, original failed with 4xx | matches original failure | Cached failure; no internal retry (client must fix payload + use new key) |
| Same key, same body, after 24h TTL | 200 / 201 | Treated as a fresh request; a new write executes. The original response is no longer cached. |
Missing Idempotency-Key header | 400 | Error envelope below |
| Same key in-flight, different body | 409 | IdempotencyConflict error envelope |
The error envelope for a missing key:
{
"error": "Idempotency-Key header is required",
"request_id": "req_01HX9F2J7M3K8N5VYBQZP4R6T2"
}
Walkthrough: retry with the same keyDirect link to Walkthrough: retry with the same key
This is the recommended retry pattern. Generate the key once, store it locally, send it on every retry.
- Generate and persist the key
IDEM_KEY=$(uuidgen)
echo "$IDEM_KEY" > /tmp/last-mcl-key - First call — server processes, returns 200
curl -X PUT https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
-H "Authorization: Bearer $ROKT_TOKEN" \
-H "Idempotency-Key: $IDEM_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Network Controls","blockedVerticals":[{"partnerVerticalId":1500,"partnerSubVerticalId":1610,"policy":"Block"}]}'Response:
200with the newmarketplaceControlsListIdandcontentHash. - Network blip — your client never sees the response
Your HTTP client throws a timeout. You don't know whether the server processed the write.
- Replay with the same key
curl -X PUT https://accounts.rokt.com/v1/partnership/accounts/<your-account-id>/marketplacecontrolslists \
-H "Authorization: Bearer $ROKT_TOKEN" \
-H "Idempotency-Key: $(cat /tmp/last-mcl-key)" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Network Controls","blockedVerticals":[{"partnerVerticalId":1500,"partnerSubVerticalId":1610,"policy":"Block"}]}'Response:
200with the samemarketplaceControlsListIdandcontentHashas step 2. Safe — no duplicate write occurred.
When the network ate the response, prefer operation pollingDirect link to When the network ate the response, prefer operation polling
Idempotency-Key replay works, but it re-runs the request body through validation each time. If you captured X-Operation-Id from the original response headers (or your client logged it before timing out), polling the operation directly recovers the response without re-validating the body.