Perception

Extract

Fill a JSON schema from a document, with a status and citations for every field.

POST /v1/documents/extract fills a JSON Schema from a document. Send the schema inline as schema, or name a saved schema with schema_id, but not both.

curl "https://console.nace.ai/v1/documents/extract?wait_seconds=60" \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "type": "parse_result", "job_id": "'"$PARSE_JOB_ID"'" },
    "schema": {
      "type": "object",
      "properties": {
        "invoice_number": { "type": "string" },
        "total": { "type": "number" }
      },
      "required": ["invoice_number", "total"]
    }
  }'

Pointing Extract at a finished Parse job, as above, means the document isn't parsed and paid for twice. A url source requires type, url, and file_name, for example {"type":"url","url":"https://example.com/invoice.pdf","file_name":"invoice.pdf"}. A workspace_file source also works. See Sources.

Configuration

POST /v1/documents/extract has several groups of options. Each example is a whole request with that option set, for the file you uploaded above. For the SDKs and the CLI, see the Python, TypeScript and CLI pages.

Schema

The fields to extract, using the supported subset of JSON Schema, sent inline or named by the id of a saved schema. Send one, not both.

Supported schema keywords

Extract supports a limited subset of JSON Schema. The root must have type: "object" and a non-empty properties object.

  • Supported keywords: type, properties, items, required, description, enum, title, additionalProperties, maxItems and uniqueItems.
  • additionalProperties is supported only as false. maxItems and uniqueItems apply only to array properties directly under the root object.
  • Other keywords, including format, $ref and anyOf, are rejected with 422 invalid_schema before a job starts.

For a date, use a string and describe the representation you want:

{
  "type": "object",
  "properties": {
    "transactionDate": {
      "type": "string",
      "description": "Transaction date in YYYY-MM-DD format."
    }
  }
}

The word "format" is allowed inside a description. Descriptions guide extraction but do not enforce date validation. Validate the returned date in your application if you need a strict date constraint.

curl https://console.nace.ai/v1/documents/extract \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "workspace_file",
      "workspace_id": "'"$WORKSPACE_ID"'",
      "file_id": "'"$FILE_ID"'"
    },
    "schema": {
      "type": "object",
      "properties": { "total": { "type": "number" } }
    }
  }'
OptionDefaultWhat it does
schemaRequired, or schema_idThe fields to extract, using the supported schema keywords.
schema_idRequired, or schemaA saved schema's id (sch_...).
schema_versionLatestThe version of a saved schema to use. Only with schema_id: with an inline schema it's refused with 422.

Instructions

Extra guidance for filling the fields.

curl https://console.nace.ai/v1/documents/extract \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "workspace_file",
      "workspace_id": "'"$WORKSPACE_ID"'",
      "file_id": "'"$FILE_ID"'"
    },
    "schema": {
      "type": "object",
      "properties": { "total": { "type": "number" } }
    },
    "instructions": "Amounts are in euros"
  }'
OptionDefaultWhat it does
instructionsNoneExtra guidance for filling the declared fields. It can't add fields the schema doesn't list.

Citations

Each field says where in the document it was read. Turn that off, or keep it without the quoted text.

curl https://console.nace.ai/v1/documents/extract \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "workspace_file",
      "workspace_id": "'"$WORKSPACE_ID"'",
      "file_id": "'"$FILE_ID"'"
    },
    "schema": {
      "type": "object",
      "properties": { "total": { "type": "number" } }
    },
    "citations": { "include_source_text": false }
  }'
OptionDefaultWhat it does
citations.enabledtrueWhen true, each field says where in the document it was read.
citations.include_source_texttrueWhen true, each citation includes a short quote.

Pages

Parse only some pages of the file. Leave it out to read every page. Not with a parse_result source.

curl https://console.nace.ai/v1/documents/extract \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "workspace_file",
      "workspace_id": "'"$WORKSPACE_ID"'",
      "file_id": "'"$FILE_ID"'"
    },
    "schema": {
      "type": "object",
      "properties": { "total": { "type": "number" } }
    },
    "page_ranges": [{ "start": 1, "end": 3 }]
  }'
OptionDefaultWhat it does
page_rangesAll pagesOne-based, inclusive ranges, up to 200 ranges and 500 pages in all. Not with a parse_result source (422).

Parse mode

See measured latency by mode for the parsing stage. This operation adds its own work, so a Parse measurement is not its total latency.

How hard to work when Extract reads the file itself. Parse has the full description of each mode.

curl https://console.nace.ai/v1/documents/extract \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "workspace_file",
      "workspace_id": "'"$WORKSPACE_ID"'",
      "file_id": "'"$FILE_ID"'"
    },
    "schema": {
      "type": "object",
      "properties": { "total": { "type": "number" } }
    },
    "parse_mode": "high"
  }'
OptionDefaultWhat it does
parse_modelowHow hard to work when Extract parses the file itself: low, medium or high, as on Parse. Only low with a parse_result source.

Result

A finished extract has result.result_type: "extract":

{
  "result_type": "extract",
  "data": { "invoice_number": "INV-1042", "total": null },
  "fields": [
    {
      "path": "/invoice_number",
      "value": "INV-1042",
      "status": "found",
      "confidence": null,
      "citations": [
        { "location": { "kind": "page_region", "page": 1, "polygons": [] }, "source_text": "Invoice INV-1042" }
      ]
    },
    { "path": "/total", "value": null, "status": "not_found", "citations": [] }
  ],
  "schema_id": null,
  "schema_version": null,
  "units": 1,
  "warnings": []
}
FieldWhat it holds
result_typeAlways "extract".
dataThe extracted values, shaped by your schema. A value that wasn't found is null, never left out.
fieldsOne entry per schema field, plus one per item of a top-level array (/line_items/0, /line_items/1, …). Join it to data on path.
fields[].pathA JSON Pointer to the field, such as /invoice_number.
fields[].valueThe extracted value, or null.
fields[].statusfound, not_found or ambiguous (a value is there but couldn't be chosen uniquely). not_found is an answer about the document: the job still succeeded.
fields[].confidenceScores the evidence for a found top-level field, and for each item of a top-level array, when the runtime produced one. null for fields inside nested objects and for fields that weren't found.
fields[].citationsWhere the value was read. Each citation has a location (see Parse blocks) and an optional source_text quote.
schema_idThe saved schema's id, when you extracted with schema_id. Otherwise null.
schema_versionThe saved schema's version that was used. Otherwise null.
unitsThe job's standard-rate usage. See Usage fields.
warningsNon-fatal notes, such as instructions that no declared field can use.

Saved schemas

Save a schema once, then name it by id instead of sending it with every extract:

curl https://console.nace.ai/v1/extraction-schemas \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "invoice",
    "description": "Invoice header fields",
    "schema": {
      "type": "object",
      "properties": {
        "invoice_number": { "type": "string" },
        "total": { "type": "number" }
      }
    }
  }'
# 201 {"schema_id":"sch_...","name":"invoice","version":1,"owner":"account","schema":{...},...}

Send "schema_id": "sch_..." in place of schema. The extract uses the latest version, or the one you pin with "schema_version": 1, and is billed like any other.

curl https://console.nace.ai/v1/documents/extract \
  -H "Authorization: Bearer $NACE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": {
      "type": "workspace_file",
      "workspace_id": "'"$WORKSPACE_ID"'",
      "file_id": "'"$FILE_ID"'"
    },
    "schema_id": "sch_...",
    "schema_version": 1
  }'

The examples use the uploaded file from the examples above.

RouteWhat it does
POST /v1/extraction-schemas/{id}/versionsAdds the next version. name and description carry over unless you send them.
GET /v1/extraction-schemasLists the latest version of each schema, sorted by schema_id (case-insensitively, with - and _ ignored at first; not byte order), without the JSON Schema itself.
GET /v1/extraction-schemas/{id}Reads a schema's latest version.
GET /v1/extraction-schemas/{id}/versionsLists a schema's versions, oldest first.
GET /v1/extraction-schemas/{id}/versions/{version}Reads one version.
DELETE /v1/extraction-schemas/{id}Deletes the schema with every version. Answers 204, also when it's already deleted.
  • Versions never change. A schema can't be edited; add a version instead, so an extract that pins schema_version always gets the same schema.
  • Retention: a saved schema, with every version, is kept until you delete it or close your account.
  • Deleting removes every version at once. An extract already accepted keeps the copy of the schema it took and finishes, and its result still names the schema_id and schema_version it used. Afterwards, reading the schema or naming its schema_id on an extract answers 404 schema_not_found. Nace's schemas can't be deleted.
  • Lists take limit (1 to 200, default 50) and cursor, the previous page's next_cursor. Keep going until it's null.
  • Nace's schemas: the list can also hold schemas Nace provides, with owner: "platform". You can extract with them, but not add versions to them. Yours have owner: "account".
  • Only your account can see or use your schemas. Another account's schema_id answers 404 schema_not_found, and the extract isn't billed.
  • A schema Extract can't use is refused with 422 invalid_schema.
  • Retries: creating a schema or a version takes no Idempotency-Key, so a retried create saves a second one. The SDKs send these creates once, without automatic retries, unless you pass a retry policy.
  • Cost: schema routes are free and work at any balance. They count toward the per-minute limit like the other document routes.

From the SDKs and the CLI

Each route has an SDK method and a CLI command:

RoutePythonTypeScriptCLI
Createextraction_schemas.createextractionSchemas.createnace schema-create
Add a versionextraction_schemas.create_versionextractionSchemas.createVersionnace schema-version-add
Listextraction_schemas.list, extraction_schemas.iterextractionSchemas.list, extractionSchemas.iternace schemas
Readextraction_schemas.getextractionSchemas.getnace schema
List versionsextraction_schemas.list_versions, extraction_schemas.iter_versionsextractionSchemas.listVersions, extractionSchemas.iterVersionsnace schema-versions
Read a versionextraction_schemas.get_versionextractionSchemas.getVersionnace schema-version

A list comes back one page at a time. To read everything:

  • Python and TypeScript: list returns a single page. iter loops over every schema and fetches the next page whenever it needs one. For a schema's versions, use iter_versions (iterVersions in TypeScript).
  • CLI: nace schemas and nace schema-versions print one page. Add --all to print everything, or pass --cursor with the previous page's next_cursor to get the next page.

On this page