Why idempotency matters
Network failures, timeouts, and retries are unavoidable in distributed systems. Without idempotency, retrying a failed POST could create a duplicate resource even though the first request actually succeeded. The Idempotency-Key header solves this by letting the API recognize repeated requests and return the original result instead of processing the operation again.
How it works
Include an Idempotency-Key header with a unique value on any write request that supports idempotency. If the API receives a second request with the same key and the same payload, it returns the stored result from the first request.
Creating a resource with an idempotency key
curl -X POST https://api.insp.ac/v1/issues \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: issue-creation-abc-123" \
-d '{
"title": "Safety observation",
"status": "open"
}'Note
Key generation
The idempotency key can be any string up to 128 characters. Best practices for generating keys:
- Use a UUID v4 for general-purpose uniqueness.
- Use a deterministic key derived from your domain data when you want natural deduplication (e.g.,
import-batch-42-row-17). - Do not reuse keys across logically distinct operations.
Key generation examples
// Random UUID (good for general use)
const key = crypto.randomUUID();
// Deterministic key (good for batch imports)
const key = `import-${batchId}-row-${rowIndex}`;Conflict detection
If a request reuses an idempotency key but sends a different payload than the original request, the API returns a 409 Conflict to prevent accidental data corruption.
409 Conflict response
{
"error": "Idempotency key already used with a different payload",
"code": "IDEMPOTENCY_KEY_REUSED"
}If the original request with the same key is still in progress, the API also returns 409 with IDEMPOTENCY_IN_PROGRESS.
Important
Supported methods
| Method | Idempotency-Key | Naturally idempotent |
|---|---|---|
GET | Not needed | Yes — reads are always safe to retry |
POST | Recommended | No — retries may create duplicates without a key |
PATCH | Recommended | Partially — some updates are safe, others are not |
DELETE | Optional (when endpoint supports it) | Yes — repeated deletes are safe; a key can replay the first delete response |
DELETE retry behavior
For delete endpoints that support idempotency (for example, DELETE /v1/assets/:id), reuse the same key when retrying the same delete request after a timeout.
Idempotent delete retry example
curl -X DELETE https://api.insp.ac/v1/assets/asset_123 \ -H "Authorization: Bearer sk_live_..." \ -H "Idempotency-Key: asset-delete-asset_123-2026-02-18"
Note
Idempotent-Replayed: true. Retrying without the original key may return 404 after the asset has been deleted.Key lifecycle
Idempotency keys and their stored results are retained for 24 hours. After that window, the key can be reused for a new operation. Within the window:
- Same key + same method + same payload = returns the original response.
- Same key + different payload = returns 409 with IDEMPOTENCY_KEY_REUSED.
- If the original request is still processing, retry returns 409 with IDEMPOTENCY_IN_PROGRESS.
SDK support
Official SDKs accept an idempotency key as an option on write methods.
TypeScript SDK
const issue = await client.issues.create(
{ title: "Safety observation", status: "open" },
{ idempotencyKey: "issue-creation-abc-123" }
);