Skip to main content
API Docs

Document OCR

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

Quickstart

Create a job, upload the PDF, start processing, poll for completion, and download the result.

quickstart.sh
FASTOCR_KEY="your-api-key"

# 1. Create a document job
curl -s -X POST https://api.fastocr.org/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 ' ')'}'

# 2. Upload the file to the presigned URL (from step 1 response)
curl -s -X PUT "<upload_url>" \
  -H "Content-Type: application/pdf" \
  -T scan.pdf

# 3. Start processing
curl -s -X POST https://api.fastocr.org/v1/documents/<id>/start \
  -H "Authorization: Bearer $FASTOCR_KEY"

# 4. Poll until ready (status: completed, partial, or failed)
curl -s https://api.fastocr.org/v1/documents/<id> \
  -H "Authorization: Bearer $FASTOCR_KEY"

# 5. Download the result
curl -s https://api.fastocr.org/v1/documents/<id>/output?format=text \
  -H "Authorization: Bearer $FASTOCR_KEY"

Accepted files: PDF only, up to 1 GB.

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

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

POST/v1/documents

Create a new document job and get a presigned upload URL.

Required headers

Idempotency-Key — a unique value per job. See Idempotency.

Request body

FieldTypeRequiredDescription
filenamestringYesMust end with .pdf.
size_bytesintegerYesFile size. Max 1,073,741,824 (1 GB).
sha256stringNoHex-encoded SHA-256 checksum.
external_idstringNoYour own correlation ID.

Response 201

response
{
  "id": "doc_a1b2c3d4e5f6",
  "status": "awaiting_upload",
  "upload_url": "https://s3.amazonaws.com/...",
  "expires_at": "2025-01-15T13:00:00Z"
}
GET/v1/documents

List your documents with optional filtering. See Pagination for query parameters.

Response 200

response
{
  "documents": [
    {
      "id": "doc_a1b2c3d4e5f6",
      "status": "completed",
      "external_id": null,
      "pages_billed": 5,
      "pages_total": 10,
      "pages_processed": 10,
      "is_truncated": false,
      "outputs": {
        "text": { "available": true },
        "pdf": { "available": true }
      }
    }
  ],
  "next_cursor": null
}
GET/v1/documents/{id}

Get the current status and metadata for a single document.

Response 200

response
{
  "id": "doc_a1b2c3d4e5f6",
  "status": "completed",
  "external_id": null,
  "pages_billed": 5,
  "pages_total": 10,
  "pages_processed": 10,
  "is_truncated": false,
  "outputs": {
    "text": { "available": true },
    "pdf": { "available": true }
  }
}

Response fields

FieldTypeRequiredDescription
idstringYesDocument job ID.
statusstringYesawaiting_upload, processing, completed, partial, or failed.
external_idstring?NoYour correlation ID, if set on create.
pages_billedintegerNoPages charged against your quota.
pages_totalintegerNoTotal pages in the document.
pages_processedintegerNoPages processed so far.
is_truncatedbooleanNoTrue if processing stopped before all pages.
outputsobjectNoAvailable output formats (text, pdf).
errorobjectNoPresent when status is failed. See Errors.
POST/v1/documents/{id}/start

Start OCR processing after the file has been uploaded. No request body required.

Response 202

response
{
  "status": "processing"
}
  • 409 document_not_startable — the job is not in a startable state.
  • 400 upload_not_found — the file has not been uploaded yet.
  • 400 size_mismatch — uploaded file size does not match size_bytes.
  • 429 concurrency_limit — too many jobs in flight. Retry after the Retry-After header (30s).
GET/v1/documents/{id}/output

Get a presigned download URL for the processed result.

Query parameters

FieldTypeRequiredDescription
formatstringYestext or pdf.

Response 200

response
{
  "format": "text",
  "url": "https://s3.amazonaws.com/...",
  "expires_at": "2025-01-15T13:00:00Z",
  "pages_billed": 5,
  "pages_total": 10
}

The presigned URL expires in 1 hour. If the job is not yet complete, a 409 document_not_ready error is returned.

DELETE/v1/documents/{id}

Delete a document and its files. Deletion is asynchronous — the job transitions to deleting and is cleaned up in the background.

Response 202

response
{
  "status": "deleting"
}

Returns 409 document_processing if the document is currently being processed.