Idempotency-Key header to prevent that.
How it works
- Generate a unique key for each logical operation — UUIDv4 is recommended.
- Send it on
POST /v1/analyzeorPOST /v1/batch:
- AcreLens hashes
<key>:<your-customer-id>with SHA-256 and uses that as the cache lookup. The original response gets stored alongside a hash of your request body. - On retry, AcreLens compares your new request body (canonical JSON, keys sorted) to the stored hash:
- Same key + same body → returns the original
202response. No new report created. No charge. - Same key + different body → returns
409 idempotency_conflict. Use a fresh key for the new request. - No prior entry → proceeds as a new request and stores the response.
- Same key + same body → returns the original
Lifetime
After 24 hours, the entry is purged. Reusing the same key after that point will create a new report — so don’t rely on idempotency keys for permanent deduplication.
When to use
- Retries after network errors — connection timeouts, partial responses, 5xx
- Background jobs — Inngest step retries, Celery, BullMQ, anything queue-driven
- User-facing forms — generate the key on form render, attach it to the submit, prevent double-submit
- Webhook handlers — if your webhook handler kicks off a
/v1/analyzerequest, use a deterministic key derived from the webhook event ID
When not to use
- Distinct logical operations — analyzing two different properties needs two different keys
- After the 24-hour window — generate a fresh key for retries beyond that
- Across different API keys — idempotency is scoped per customer, not per
Authorizationheader
Conflict response
If you reuse a key with a different body — common bug: changing the address slightly and forgetting to regenerate the key — you’ll get:Safe retry pattern (Node)
Body canonicalization
Idempotency comparisons are body-aware, but field order doesn’t matter. Both of these match:address.) Whitespace, case, and field values matter. Field order does not.