Relaystation logo Relaystation

Document AI

Extract structure and meaning from a document — OCR with word/line layout, form key→value pairs, tables, invoice and ID parsing, and natural-language questions about the content — from a single API call. Backed by AWS Textract. Six synchronous ops handle a single page; one asynchronous op handles a multi-page PDF and returns a job ticket you poll (see Async jobs).

curl -X POST https://api.relaystation.ai/v1/doc/ocr-layout \
  -H 'Authorization: Bearer rs_live_<key>' \
  -H 'Idempotency-Key: ocr-page1-20260707' \
  -H 'Content-Type: application/json' \
  -d '{ "file": { "inline": "<base64 image or 1-page PDF>" } }'

Or on the lodestone path — no account, a signed x402 payment instead of an API key:

curl -X POST https://api.relaystation.ai/v1/doc/ocr-layout \
  -H 'X-Payment: <base64 EIP-3009 authorization>' \
  -H 'Idempotency-Key: ocr-page1-20260707' \
  -H 'Content-Type: application/json' \
  -d '{ "file": { "inline": "<base64 image or 1-page PDF>" } }'

Inputs — the cputools file convention

Every op takes its document as a file input source, the same shape used across the compute API:

{ "inline": "<base64-encoded document>" }   // for files ≤ 4 MiB
{ "inputKey": "<scratch object key>" }        // for larger files, up to 50 MB

For a file above the inline ceiling, mint a one-time presigned upload with POST /v1/cputools/upload-url, POST the bytes, then pass {"inputKey":"..."} — the full recipe is in Passing & receiving files.

The synchronous ops (single page)

All six are POST /v1/doc/<op> and take a single-page document (an image or a 1-page PDF) up to 5 MB (operator-tunable docai.max_doc_bytes). A multi-page or oversized input returns a 422 before any charge, naming the limit — reach for analyze-async for multi-page PDFs.

OpRouteWhat it returns
OCR with layoutPOST /v1/doc/ocr-layout{ blocks: [...] } — Textract line/word blocks with geometry
Extract form fieldsPOST /v1/doc/extract-form{ fields: [...], blocks: [...] } — key→value pairs
Extract tablesPOST /v1/doc/extract-tables{ tables: [...], blocks: [...] }
Parse invoice / receiptPOST /v1/doc/parse-invoice{ documents: [...] } — normalized expense fields
Parse government IDPOST /v1/doc/parse-id{ documents: [...] } — ID field extraction
Ask the documentPOST /v1/doc/ask-document{ answers: [...] } — one answer per question

ask-document also takes a questions array (1–15 items, each ≤ 200 chars):

curl -X POST https://api.relaystation.ai/v1/doc/ask-document \
  -H 'Authorization: Bearer rs_live_<key>' \
  -H 'Idempotency-Key: ask-20260707' \
  -H 'Content-Type: application/json' \
  -d '{ "file": { "inline": "<base64 1-page PDF>" }, "questions": ["What is the total?", "What is the due date?"] }'

Each synchronous op is a flat per-document charge — Textract’s own per-page unit. The rates differ by op (a plain OCR costs less than a form or ID parse); see Pricing, or send an unauthenticated POST to read the exact price from the 402 challenge. An upstream Textract failure reverses the charge (you pay only for a delivered result).

analyze-async — multi-page PDFs

POST /v1/doc/analyze-async runs Textract’s asynchronous analysis over a multi-page PDF (PDF-only — the page count is what the ceiling is based on, and only PDFs page-count reliably). Instead of a result inline, it returns a job ticket; the compute finishes minutes later in a separate worker.

FieldTypeNotes
fileinput source, requiredthe multi-page PDF (inline ≤ 4 MiB, or inputKey up to 50 MB)
featuresstring[], requiredone or more of FORMS, TABLES, QUERIES
questionsstring[]required when features includes QUERIES (1–15 items, each ≤ 200 chars)
deliver{ batonId }optionally deliver the result to a baton instead of holding it for polling
curl -X POST https://api.relaystation.ai/v1/doc/analyze-async \
  -H 'Authorization: Bearer rs_live_<key>' \
  -H 'Idempotency-Key: async-report-20260707' \
  -H 'Content-Type: application/json' \
  -d '{ "file": { "inputKey": "<key from upload-url>" }, "features": ["FORMS", "TABLES"] }'

Response — the ticket:

{ "ticket": "...", "job_id": "...", "status": "running", "ceiling_micros": 42000 }

Poll GET /v1/jobs/{id} until the status is terminal, or subscribe to the job.completed webhook. Page count is capped by docai.async_max_pages (default 3000); a document over the cap returns 422 DOC_TOO_LARGE before any charge.

Billing is per page. The page count is counted at submit, so the ceiling is exact for Textract. On the x402 rail the charge settles at submit (pages × per-page); on the balance / API-key rail a hold is authorized at submit and the actual is captured at completion. A job that fails for an infrastructure reason is made whole. The billing mechanics are laid out in Async jobs; see Pricing for the per-page rate.

MCP tools

Callable over MCP at https://api.relaystation.ai/mcp: doc_ocr_layout, extract_form, extract_tables, parse_invoice, parse_id, ask_document, and doc_analyze_async (with job_status to poll the ticket). Same auth, same prices as the HTTP routes.

Next

Async jobs · Passing & receiving files · ID verification · Quickstart · x402 wire format · API reference