Skip to main content
Private Beta

FastOCR API

Extract text from documents and structured data from bank statements. Upload a file, poll for completion, download the result.

Getting access

The API is in private beta. Access is allowlisted per account — you cannot generate a key until your account is approved.

  1. 1Contact us to request API access for your account.
  2. 2Once approved, create an API key in the developer console.
  3. 3Pass the key as Authorization: Bearer <key> on every request.

Document OCR

Upload a PDF, run OCR, and get extracted text or a searchable PDF back. Five requests from file to result.

quickstart-documents.sh
FASTOCR_KEY="your-api-key"
BASE="https://api.fastocr.org"

# 1. Create a document job
curl -s -X POST "$BASE/v1/documents" \
  -H "Authorization: Bearer $FASTOCR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"filename":"scan.pdf","size_bytes":'$(wc -c < scan.pdf | tr -d ' ')'}' \
  -o doc.json

# 2. Upload the PDF to the presigned URL
curl -s -X PUT "$(jq -r '.upload_url' doc.json)" \
  -H "Content-Type: application/pdf" \
  -T scan.pdf

# 3. Start processing
DOC=$(jq -r '.id' doc.json)
curl -s -X POST "$BASE/v1/documents/$DOC/start" \
  -H "Authorization: Bearer $FASTOCR_KEY"

# 4. Poll until ready
while true; do
  STATUS=$(curl -s "$BASE/v1/documents/$DOC" \
    -H "Authorization: Bearer $FASTOCR_KEY" | jq -r '.status')
  case "$STATUS" in completed|partial|failed) break ;; esac
  sleep 3
done

# 5. Download the extracted text
URL=$(curl -s "$BASE/v1/documents/$DOC/output?format=text" \
  -H "Authorization: Bearer $FASTOCR_KEY" | jq -r '.url')
curl -o result.txt "$URL"

Output formats: ?format=text for plain text, ?format=pdf for a searchable PDF.

Idempotency: The Idempotency-Key header prevents duplicate jobs if a request is retried. Use a unique value per job.

Statuses: awaiting_upload processing completed or failed. Large documents may finish as partial with is_truncated: true.

Bank statement extraction

Upload a bank statement and extract transactions as structured data. Same five-step flow as documents. Accepts PDF, PNG, JPG, and WebP.

quickstart-bank-statements.sh
FASTOCR_KEY="your-api-key"
BASE="https://api.fastocr.org"

# 1. Create a bank statement job
curl -s -X POST "$BASE/v1/bank-statements" \
  -H "Authorization: Bearer $FASTOCR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"filename":"statement.pdf","size_bytes":'$(wc -c < statement.pdf | tr -d ' ')'}' \
  -o stmt.json

# 2. Upload the file
curl -s -X PUT "$(jq -r '.upload_url' stmt.json)" \
  -H "Content-Type: application/pdf" \
  -T statement.pdf

# 3. Start extraction
STMT=$(jq -r '.id' stmt.json)
curl -s -X POST "$BASE/v1/bank-statements/$STMT/start" \
  -H "Authorization: Bearer $FASTOCR_KEY"

# 4. Poll until ready
while true; do
  STATUS=$(curl -s "$BASE/v1/bank-statements/$STMT" \
    -H "Authorization: Bearer $FASTOCR_KEY" | jq -r '.status')
  case "$STATUS" in completed|failed) break ;; esac
  sleep 3
done

# 5. Download as Excel
URL=$(curl -s "$BASE/v1/bank-statements/$STMT/output?format=xlsx" \
  -H "Authorization: Bearer $FASTOCR_KEY" | jq -r '.url')
curl -o transactions.xlsx "$URL"

Output formats: ?format=xlsx (Excel), ?format=csv, or ?format=json.

File limits: PDFs up to 100 MB. Images up to 20 MB.

Endpoints

Base URL: https://api.fastocr.org

MethodPathDescription
POST/v1/documentsCreate a document job
GET/v1/documentsList documents
GET/v1/documents/{id}Check status
POST/v1/documents/{id}/startStart processing
GET/v1/documents/{id}/outputDownload result
DELETE/v1/documents/{id}Delete a document
POST/v1/bank-statementsCreate a statement job
GET/v1/bank-statementsList statements
GET/v1/bank-statements/{id}Check status
POST/v1/bank-statements/{id}/startStart extraction
GET/v1/bank-statements/{id}/outputDownload result
DELETE/v1/bank-statements/{id}Delete a statement

List parameters: ?limit= (1–100, default 20), ?status=, ?cursor=, ?updated_since=.

List response: the array is named after the resource — { documents: [...], next_cursor } and { bank_statements: [...], next_cursor }. A next_cursor of null means there are no more pages.

Create body: filename (required), size_bytes (required), external_id (optional), sha256 (optional).

Errors

A failed job returns HTTP 200 with a terminal status and an error object. HTTP status describes the request, not the work.

error object
{
  "error": {
    "type": "processing_error",
    "code": "timeout",
    "message": "This file took too long to process. Please try again.",
    "retryable": true
  }
}
  • Match on code, never on message — messages change without notice.
  • New codes will be added. Treat any unrecognised code as processing_failed.
  • Only buy_pages reopens a failed job — buy credits, then call /start again on the same job.
CodeTypeWhenRetryable
buy_pagesinsufficient_creditsOut of page credits.No — buy a pack, then call /start again on the same job.
unreadable_statementinvalid_requestBank statement could not be read.No
unreadable_documentinvalid_requestPDF could not be read.No
too_many_pagesinvalid_requestFile exceeds the page cap.No
empty_fileinvalid_requestFile has no pages.No
timeoutprocessing_errorProcessing ran out of time.Yes
processing_failedprocessing_errorAnything else.Yes

Ready to get started?

Request access, create a key, and run the quickstart above.