Limai Docs
API ReferenceDocument Processing

Process File (Sync)

Extract structured data from an uploaded document synchronously.

POST/api/v1/document/{extractionSchemaId}/process-file/{fileId}SYNC

Extract 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

NameTypeInRequiredDescription
extractionSchemaIdstringpathYesThe model or deployment's extraction schema ID, returned when listing a project's deployments.
fileIdstringpathYesThe 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.

Response200
{
  "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

FieldTypeDescription
idstringUnique table identifier
namestringHuman-readable table name
columnsarrayArray of column definitions (id, name, type, description)
rowsarrayArray of extracted data rows

Row

FieldTypeDescription
idstringUnique row identifier
indexstringRow position
statusstringRow status: PENDING, ACCEPTED, or REJECTED
cellsobjectCell data keyed by column name
childTablesobjectNested child tables (if schema has relationships)

Cell

FieldTypeDescription
valuestringExtracted cell value
columnIdstringReference to the column definition
metadataobjectColumn metadata: id, type, description, and slug
validationsarrayPer-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 / FAILED result 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 as FAILED for 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:

FieldTypeDescription
checkKeystring | nullIdentifier of the rule or script that produced the entry
sourcestringRULE, SCRIPT, or AGENT
passedbooleanWhether the check passed for this cell
messagestring | nullHuman-readable detail
expected / actualstring | nullCompared values, when the check reports them
amendedbooleantrue 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:

FieldTypeDescription
failCountnumber | nullNumber of failing checks; null when no checks ran
checksarrayPer-check results: key, name, source, behavior (SURFACE or RESEND), status, and timing
rulesobject | nullDeclarative 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

SynchronousAsynchronous
Best forSmall files (< 10MB), real-time UIsLarge files, batch processing
BehaviorBlocks until completeReturns job ID immediately
Timeout riskMay timeout on large filesNo 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.

On this page