> Source: https://txtfetch.com/docs/idempotency > Plain-text twin — every page on txtfetch.com has one. https://txtfetch.com/text --- # Retries that can't double-run. A client-side timeout or a dropped response shouldn't mean paying for the same extraction twice. Idempotency-Key makes a retried request safe. how-it-works Pass an `Idempotency-Key` header on any `POST /v1/extract`. txtfetch looks the key up (scoped to your API key, so two callers can't collide on the same value): - **First time seen:** the request runs normally. If it finishes as a `2xx` or a `202` job-accepted, the response is stored against the key. - **Repeated with the identical request** (same method, `url`/`async`/body/content-type): the stored response is replayed immediately. There's no re-extraction and no second charge against your quota. - **Repeated with a different request** under the same key: rejected with `bad_request`. Reusing a key for a different request is almost always a bug. It fails loudly instead of silently returning the wrong cached result. Only successful dispatches are cached. An error response is never stored, so retrying after a transient failure re-attempts the extraction (and caches it once it succeeds). Records expire after 1 day, the same lifecycle window async job results are kept for. curl ```curl curl -X POST https://api.txtfetch.com/v1/extract \ -H "Authorization: Bearer $TXTFETCH_KEY" \ -H "Idempotency-Key: 3f29b6e4-9c1a-4b8e-9c2a-1e6f0a2d5b3c" \ -F file=@contract.pdf ``` JavaScript ```javascript // The SDK auto-generates and reuses an Idempotency-Key across its own // retry chain. Pass your own to control it explicitly: await txtfetch.extract({ file: "./contract.pdf", idempotencyKey: "3f29b6e4-..." }); ``` Python ```python # The SDK auto-generates and reuses an Idempotency-Key across its own # retry chain. Pass your own to control it explicitly: client.extract(file="contract.pdf", idempotency_key="3f29b6e4-...") ``` sdk-behavior Both official SDKs generate an `Idempotency-Key` automatically on every `POST`. They reuse the same one across a retry chain: a client-side timeout, a network error, or a bare `5xx`. An SDK-driven retry is never double-run, without you doing anything. Typed `4xx`/`5xx` error bodies are never retried. Pass your own key explicitly when you need to correlate a retry across process restarts or separate client instances. see-also Submitting a job that also carries `webhook_url`? See [async jobs & webhooks](https://txtfetch.com/docs/async) for the job lifecycle and delivery signature. A mismatched retry returns `bad_request`. The full list of codes is in the [error reference](https://txtfetch.com/docs/errors). ## Watch it run, then take a key. The playground replays a real recorded response for every sample document. [Open the playground →](https://txtfetch.com/playground) [Get an API key →](https://app.txtfetch.com/signup)