Process File (Sync)
Extract structured data from an uploaded document synchronously.
/api/v1/document/{extractionSchemaId}/process-file/{fileId}SYNCExtract structured data from an uploaded file using AI-powered document processing. This endpoint processes the document synchronously and returns the extracted data immediately upon completion.
Validations run as part of the call: schema rules and the first pass of custom checks complete inline, so their pass/fail is already in the response. A failing check that is configured to RESEND (re-derive the value) does not block the response — that step continues asynchronously (see Validations). You get the first-round signal immediately and read the corrected outcome later.
For large files or batch processing, consider using the async endpoint instead.
Parameters
| Name | Type | In | Required | Description |
|---|---|---|---|---|
extractionSchemaId | string | path | Yes | The model or deployment's extraction schema ID, returned when listing a project's deployments. |
fileId | string | path | Yes | The file ID returned from the get-url endpoint after uploading. |
The request body should be an empty JSON object {}.
Request
const response = await fetch(
`https://app.limai.io/api/v1/document/${SCHEMA_ID}/process-file/${fileId}`,
{
method: "POST",
headers: {
"Authorization": `Bearer ${API_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({})
}
)
const result = await response.json()Response
The response carries the extracted data plus a file-level validations object, and every cell includes a validations array (empty when no check applies). The values reflect the first pass. In the example below the amount failed a RESEND reconciliation check: the check reports FAILED with behavior: "RESEND", and the re-derivation continues asynchronously — poll Get File Data (or listen for the DOCUMENT_VALIDATED webhook) to see it settle to RESEND_PASSED and the corrected, amended value.
{
"message": "File processed successfully.",
"fileId": "file_abc123def456",
"jobId": "job_789xyz012",
"data": {
"tables": {
"table_id_1": {
"id": "table_id_1",
"name": "Invoices",
"slug": "invoices",
"columns": [
{
"id": "col_1",
"name": "Invoice Number",
"type": "TEXT",
"description": "Unique invoice identifier",
"sharedColumnId": null,
"slug": "invoice_number"
},
{
"id": "col_2",
"name": "Amount",
"type": "NUMBER",
"description": "Invoice total amount",
"sharedColumnId": null,
"slug": "amount"
}
],
"rows": [
{
"id": "row_1",
"index": "0",
"status": "PENDING",
"cells": {
"Invoice Number": {
"value": "INV-001",
"columnId": "col_1",
"metadata": {
"id": "col_1",
"type": "TEXT",
"description": "Unique invoice identifier",
"slug": "invoice_number"
},
"validations": []
},
"Amount": {
"value": "1000.00",
"columnId": "col_2",
"metadata": {
"id": "col_2",
"type": "NUMBER",
"description": "Invoice total amount",
"slug": "amount"
},
"validations": [
{
"checkKey": "amount-reconciliation",
"source": "SCRIPT",
"passed": false,
"message": "Amount does not reconcile with line items",
"expected": null,
"actual": null,
"amended": false
}
]
}
}
}
]
}
}
},
"validations": {
"failCount": 1,
"checks": [
{
"key": "amount-reconciliation",
"name": "Amount reconciliation",
"source": "STATIC",
"status": "FAILED",
"behavior": "RESEND",
"findings": [],
"errorMessage": null,
"startedAt": "2026-07-21T10:00:00.000Z",
"completedAt": "2026-07-21T10:00:04.000Z"
}
],
"rules": {
"crossField": [],
"row": [],
"document": []
}
}
}Data Structure
Table
| Field | Type | Description |
|---|---|---|
id | string | Unique table identifier |
name | string | Human-readable table name |
columns | array | Array of column definitions (id, name, type, description) |
rows | array | Array of extracted data rows |
Row
| Field | Type | Description |
|---|---|---|
id | string | Unique row identifier |
index | string | Row position |
status | string | Row status: PENDING, ACCEPTED, or REJECTED |
cells | object | Cell data keyed by column name |
childTables | object | Nested child tables (if schema has relationships) |
Cell
| Field | Type | Description |
|---|---|---|
value | string | Extracted cell value |
columnId | string | Reference to the column definition |
metadata | object | Column metadata: id, type, description, and slug |
validations | array | Per-cell validation entries (see Validations). Empty when no check touched the cell |
Validations
Validation runs before the response returns, but only the parts that are fast run inline:
- Rules — declarative checks configured on the schema. They evaluate on the first pass and never re-extract.
- Scripts and agents, first pass — custom checks run once against the extracted values. Their
PASSED/FAILEDresult is in the response. - RESEND (asynchronous) — when a custom check fails and is configured to
RESEND, re-deriving the value requires a fresh model call, so it is not done inline. The response reports that check asFAILEDfor now, and the re-derivation continues in the background.
To read the final outcome of a RESEND check, poll Get File Data with include=validations or listen for the DOCUMENT_VALIDATED webhook. Once it settles, the check reports RESEND_PASSED (corrected) or RESEND_FAILED (still failing), and any corrected cell is flagged amended: true.
Validation fields
Each per-cell entry in validations has:
| Field | Type | Description |
|---|---|---|
checkKey | string | null | Identifier of the rule or script that produced the entry |
source | string | RULE, SCRIPT, or AGENT |
passed | boolean | Whether the check passed for this cell |
message | string | null | Human-readable detail |
expected / actual | string | null | Compared values, when the check reports them |
amended | boolean | true once a RESEND check has corrected this cell's value. Always false on the first-pass response and for RULE entries |
The file-level validations object summarizes the run:
| Field | Type | Description |
|---|---|---|
failCount | number | null | Number of failing checks; null when no checks ran |
checks | array | Per-check results: key, name, source, behavior (SURFACE or RESEND), status, and timing |
rules | object | null | Declarative rule results grouped by crossField, row, and document |
A check's status follows the lifecycle: PASSED / FAILED on the first pass (what this endpoint returns), then RESEND_PASSED / RESEND_FAILED once a RESEND check finishes re-extracting. RESEND_PASSED is the signal that a value initially failed and was corrected.
When to Use Sync vs Async
| Synchronous | Asynchronous | |
|---|---|---|
| Best for | Small files (< 10MB), real-time UIs | Large files, batch processing |
| Behavior | Blocks until complete | Returns job ID immediately |
| Timeout risk | May timeout on large files | No timeout limitations |
The synchronous call waits for extraction and the first validation pass; RESEND re-extraction never blocks it, since that runs in the background either way. Both endpoints surface the same validation data — the async endpoint simply returns everything, including any RESEND outcome, on a later Get File Data poll.