> 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.

# extraction.ready

POST 

Fires once per document, the moment its extraction is queryable in the shape you should build on, and the usual cue to pull line items. For a bank statement it is held back until counterparty enrichment lands, or until the grace window elapses without it (`enrichment` says which).

Reference: https://docs.spreadspace.app/api/api-reference/webhook-events/webhook-extraction-ready

## Request

### Headers

- `SpreadSpace-Signature` (string, required) — Signature over the exact request body: `t=<seconds since the Unix epoch>,v1=<lowercase hex HMAC-SHA256 of "{t}.{body}" keyed with your endpoint's signing secret>`. Verify it before trusting the body, and reject a `t` more than five minutes from your own clock. During a secret rotation both the new and the previous secret verify for 24 hours; each delivery is signed with exactly one.
- `SpreadSpace-Event-Id` (string, required) — The event id, identical to the body's `id`. Stable across retries and replays, and shared by every endpoint one event fans out to. Delivery is at-least-once, so dedupe on it.

### Payload

- `id` (string, required) — Event id: `evt_` plus 24 lowercase hex characters. Also sent as the `SpreadSpace-Event-Id` header. Stable across retries and replays, so dedupe on it.
- `type` (enum, required) — Always this event type on this body.
  - Allowed values: `extraction.ready`
- `created` (long, required) — Seconds since the Unix epoch at which the event was created server-side. Seconds, not milliseconds. Deliveries are not ordered; reconcile on this.
- `tenant_id` (string, required) — The workspace the event belongs to. Reject a delivery whose tenant does not match the endpoint you registered.
- `livemode` (boolean, required) — `true` for live activity, `false` for test mode (an `ss_test_` key or the sandbox simulator). Branch on it to route test deliveries to a staging handler.
- `data` (ExtractionReadyPayload, required) — The `data` object on an `extraction.ready` delivery, sent once per document the moment its extraction is queryable in the shape you should build on. It is the usual cue to pull line items, and narrower than `document.processed`, which also covers the classification-only and failure paths. A bank statement can be enriched shortly after it is ingested. So that what you fetch on this event is what you keep, `extraction.ready` for such a statement is held back until the enrichment lands (`enrichment` is `complete`), or until a grace window elapses without it (`timed_out`, and an `extraction.updated` follows if it arrives later). Every other document fires at ingestion with `not_applicable`. `document.processed` is never held back.

## Types

### ExtractionReadyPayload

The `data` object on an `extraction.ready` delivery, sent once per document the moment its extraction is queryable in the shape you should build on. It is the usual cue to pull line items, and narrower than `document.processed`, which also covers the classification-only and failure paths. A bank statement can be enriched shortly after it is ingested. So that what you fetch on this event is what you keep, `extraction.ready` for such a statement is held back until the enrichment lands (`enrichment` is `complete`), or until a grace window elapses without it (`timed_out`, and an `extraction.updated` follows if it arrives later). Every other document fires at ingestion with `not_applicable`. `document.processed` is never held back.

- `extraction_id` (string, required) — The extraction record to fetch. Equal to `document_id` today, but carried as its own id so a later split into several extractions per document does not break you.
- `document_id` (string, required) — The extracted document.
- `job_id` (string, required) — The document package (job) the document was uploaded in.
- `borrower_id` (string, required) — The borrower that owns the loan.
- `loan_id` (string, required) — The loan the document belongs to.
- `document_type` (string, required) — What the document was classified as, using the same values `document.processed` reports.
- `enrichment` (enum, required) — Enrichment state of the extraction this event announces: `complete` (the enrichment is already in what you can fetch now), `not_applicable` (no enrichment applies to this document, so it is final), or `timed_out` (enrichment was expected but did not land within the grace window, so you are reading the un-enriched extraction and an `extraction.updated` follows if it lands later).
  - Allowed values: `complete`, `not_applicable`, `timed_out`
- `ready_at` (datetime, required) — Server-side wall-clock time the extraction was made queryable.
- `extraction_version` (integer, optional, nullable) — The revision of the stored extraction this event announces, 1 as ingested and incremented on every later rewrite. Compare it against the version on the document you fetched, or on a later `extraction.updated`, to spot a stale read. Null only on events emitted before versioning shipped.