> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ndi.nace.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Extract

> Fill a JSON Schema from a document

Exactly one of `json_schema` or `schema_id` is required. `not_found` on a
field is an answer about the document, not an HTTP error.

```ts theme={"dark"}
import { NdiClient } from "ndi-sdk";

const schema = {
  type: "object",
  properties: {
    invoice_number: { type: "string" },
    total: { type: "number" },
  },
  required: ["invoice_number", "total"],
};

const client = new NdiClient();
const upload = await client.documents.createUpload("invoice.pdf");
const parsed = await client.jobs.wait(
  (await client.documents.parse(upload, { wait_seconds: 30 })).job_id,
);
const job = await client.jobs.wait(
  (
    await client.documents.extract(
      { type: "parse_result", job_id: parsed.job_id },
      { json_schema: schema, wait_seconds: 30 },
    )
  ).job_id,
);
if (job.result?.result_type === "extract" && "fields" in job.result) {
  console.log(job.result.data);
  for (const field of job.result.fields) {
    console.log(field.path, field.status, field.value);
  }
}
```

## Method signature

```text theme={"dark"}
extract(
  source: DocumentSource | UploadResponse,
  opts: {
    json_schema?: JsonSchema;
    schema_id?: string;
    instructions?: string;
    page_ranges?: PageRange[];
    citations?: ExtractCitationOptions;
    wait_seconds?: number;
    idempotency_key?: string;
  },
): Promise<Job>
```

### Parameters

| Parameter           | Type                                 | Required | Description                              |
| ------------------- | ------------------------------------ | -------- | ---------------------------------------- |
| `source`            | `DocumentSource` or `UploadResponse` | Yes      | File or prior parse                      |
| `opts.json_schema`  | JSON Schema object                   | One of   | Inline schema                            |
| `opts.schema_id`    | `string`                             | One of   | Saved schema id                          |
| `opts.instructions` | `string`                             | No       | Extra extraction guidance                |
| `opts.page_ranges`  | `PageRange[]`                        | No       | Not available on a `parse_result` source |
| `opts.citations`    | `ExtractCitationOptions`             | No       | Default on                               |
| `opts.wait_seconds` | `number`                             | No       | Hold the HTTP response open (max 300)    |

### Returns

A `Job`. On success, `result.result_type === "extract"`.

## Validate a schema

```ts theme={"dark"}
import { NdiClient } from "ndi-sdk";

const schema = { type: "object", properties: { total: { type: "number" } } };
const client = new NdiClient();
const check = await client.documents.validateExtractSchema({ json_schema: schema });
console.log(check);
```

Register reusable schemas over HTTP (`POST /v1/extraction-schemas`) and pass
`schema_id`. There is no SDK registry namespace.

See [Extract guide](/guides/extract) and [Extract response](/guides/extract-response).
