Referencia de la API

Structured extraction

PDF or image in — schema-validated JSON out. OCR runs automatically when needed.

Two endpoints, same idea: you describe the shape you want as a JSON Schema, and the response is guaranteed to validate against it. You don't extract text yourself — OCR runs automatically wherever it's needed.

POST/v1/documents/extract
POST/v1/images/extract

Use /documents/extract for a PDF (OCR only kicks in for scanned pages), and /images/extract for a loose image — a phone photo, a screenshot, a standalone scan — where every image goes through OCR.

Request

Both take multipart/form-data with the same fields:

filefileObligatorio

The PDF (/documents/extract) or the image — JPEG, PNG, or WEBP (/images/extract).

schemastringObligatorio

A JSON Schema (as a string) describing the fields to extract.

systemstringOpcional

Replaces your stack's configured system prompt for this request. Omit it to keep your stack's configured behavior.

userstringOpcional

Extra context about this specific file — added on top of the extraction instruction, not a replacement for it. Use it to say what kind of document or image this is when the same stack handles several.

max_tokensintegerOpcionalPredeterminado: 4000

Ceiling on the response. Must be greater than 0, up to 16000.

Example

curl -X POST "https://api.trystac.com/v1/documents/extract" \
  -H "Authorization: Bearer $STAC_API_KEY" \
  -F file=@invoice.pdf \
  -F 'schema={
        "type": "object",
        "properties": {
          "invoice_number": {"type": "string"},
          "vendor_tax_id":  {"type": ["string", "null"]},
          "total":          {"type": "number"}
        },
        "required": ["invoice_number", "vendor_tax_id", "total"]
      }'
curl -X POST "https://api.trystac.com/v1/images/extract" \
  -H "Authorization: Bearer $STAC_API_KEY" \
  -F file=@invoice.jpg \
  -F 'schema={"type": "object", "properties": {"total": {"type": "number"}}, "required": ["total"]}'

Response

200 OKjson
{
  "data": { "invoice_number": "12345", "vendor_tax_id": "11-2223334", "total": 1500.0 },
  "pages": 3,
  "ocr_used": false,
  "usage": { "prompt_tokens": 2104, "completion_tokens": 48 }
}
dataobjectOpcional

Your JSON, already validated against schema.

pagesintegerOpcional

Page count for a PDF. Always 1 for /images/extract — there's no "page" concept for a loose image.

ocr_usedbooleanOpcional

true if OCR ran. For /images/extract it's always true — every image goes through OCR. For /documents/extract it's true only for scanned pages; worth reviewing the result more carefully in that case.

The most important rule: mark fields nullable if they can be missing

Output is grammar-constrained to match your schema token by token — that's what guarantees valid JSON, but it has a consequence that decides the quality of your results:

Declare any field that might legitimately be absent as nullable:

json
"vendor_tax_id": { "type": ["string", "null"] }

There's a second trap in the opposite direction: a field left out of required is optional under JSON Schema, so the model can simply omit the key instead of looking for the value — you get a 200 with valid JSON and a missing field, no warning. The combination that avoids both traps is required on every field, with nullable types on the ones that can legitimately be missing:

json
{
  "type": "object",
  "properties": {
    "invoice_number": { "type": "string" },
    "vendor_tax_id":  { "type": ["string", "null"] },
    "total":          { "type": "number" }
  },
  "required": ["invoice_number", "vendor_tax_id", "total"]
}

This applies inside nested arrays and objects too — each object in a list needs its own required, or items come back with fields silently missing.

Errors

StatusMeaning
400Unreadable/corrupt file, no extractable text, invalid schema, or content too large for the plan's context window
413File, page count/resolution, or schema over the plan's limit
422max_tokens outside the accepted range
502Model output didn't validate against schema (response includes raw_output for debugging)

A truncated raw_output on a 502 usually means the response didn't fit the remaining context — the file is large and little room was left for the JSON. Split the PDF or trim the schema.

Limits

LimitEndpointGoProMaxEnterprise
File size/documents/extract8 MB15 MB25 MBCustom
Pages per request/documents/extract153050Custom
File size/images/extract5 MB10 MB15 MBCustom
Resolution/images/extract20 megapixels20 megapixels20 megapixels20 megapixels

Schema up to 64 KB on both. Server timeout: 240s — set your client's timeout above that; a multi-page scanned document can take minutes.