> This page is for API.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.spreadspace.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.spreadspace.app/_mcp/server.

# Idempotency

Send an `Idempotency-Key` header on any `POST`/`PATCH`/`PUT`/`DELETE` call
made with an API key. The first request with a given key runs normally and its
response is cached for 24 hours; retries that reuse the key replay that
response instead of re-running the operation.

```bash
curl -X POST https://api.spreadspace.app/api/extractions/exports \
  -H "Authorization: Bearer ss_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3f7c31c9-3a06-4a5f-9f6b-8d34ef9f2b41" \
  -d '{"borrower_id": "4a2c8e1f6b3d5a7c9e0f1b2d", "loan_id": "7d1e3b5a9c2f4e6b8d0a3c5e", "document_ids": ["1f2e3d4c5b6a79081a2b3c4d"], "format": "csv"}'
```

The header is optional: omit it and every request is processed fresh.

## Keys

* Up to 255 characters. Generate a UUID per logical operation.
* Scoped per API key: two credentials never share a cache entry.
* Read calls (`GET`) ignore the header: they are already idempotent. Endpoints
  that don't support it don't list it on their reference page.
* Embed session tokens (`ss_embed_…`) do not participate: the header is
  ignored for them.

## Replays

A replayed response body is byte-for-byte the original, with the
`Idempotency-Replay: true` header added. `Content-Type`, `Cache-Control`,
`ETag`, `Last-Modified`, `Vary` and `X-SpreadSpace-*` headers are replayed;
other headers, including `Location`, are not, and `X-Request-ID` is minted
fresh.

Cached responses include client errors (`4xx`) and server errors (`5xx`).
Reusing the key returns the stored error. An interrupted request may return
`500 internal_error` with an unknown outcome.

A `429` or a `503` sent with a `Retry-After` header is the one answer that is
not cached: the request did not run, and a retry with the same key runs it.

Before retrying a `5xx` with a new key, check whether the operation completed
by retrieving or listing the affected resource. Create a new key only after
confirming that another operation is needed. Contact support with the
`request_id` if you cannot determine the result.

## Request fingerprint

The request method, path (including the query string) and body are
fingerprinted alongside the key. Reusing a key with a different method, path
or body returns `409 idempotency_request_mismatch`. Use one key per logical
operation.

## Concurrent retries

If a duplicate arrives while the original is still executing, it waits for the
original to finish (up to 30 seconds) and replays its response. If the
original is still running past that window, the duplicate returns
`429 idempotency_in_progress` with a `Retry-After` header: retry after the
indicated pause.

## Limits

Responses larger than 1 MiB are delivered but not stored. The original
request succeeds normally; a replay of its key returns
`409 idempotency_response_too_large` with `Idempotency-Replay: true`, and the
operation is not re-run. Read the resource the original created rather than
resending.

A request body over 16 MiB sent with an `Idempotency-Key` returns
`413 invalid_request`.

## SDKs

The [official SDKs](/sdks/overview) generate an idempotency key for each
non-`GET` call and reuse it for their automatic retries. A cached `5xx` raises
the SDK's server-error class. Check the resource state before submitting
another operation with a new key.