IA

insp.ac API

Developer platform

Idempotency

Write operations that support idempotency (including POST, PATCH, and selected DELETE routes) accept an Idempotency-Key header so retries do not execute the same mutation twice.

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

Idempotency keys are scoped to your API key. Two different API keys can use the same idempotency key value without conflict.

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

A 409 from idempotency conflict is a client error, not a transient failure. Do not retry it — investigate why the payload differs from the original request.

Supported methods

MethodIdempotency-KeyNaturally idempotent
GETNot neededYes — reads are always safe to retry
POSTRecommendedNo — retries may create duplicates without a key
PATCHRecommendedPartially — some updates are safe, others are not
DELETEOptional (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

Same key + same payload replays the original result and includes 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" }
);