eScanX API Reference

Everything you need to integrate our intelligent document OCR API into your applications.

Base URL
https://api.escanx.com
API Version
v1
Content Type
Responses are JSON. File uploads use multipart/form-data.
All API endpoints are prefixed with /api/v1. Example: https://api.escanx.com/api/v1/extract/receipt

Authentication

Authenticate your API requests using the X-API-Key header. Get your API key from the dashboard after signing up.

Get your API key
Sign up for a free account and generate an API key from your dashboard.

Include your API key in every request:

# Sample: list async jobs (any authenticated endpoint works the same way)
curl https://api.escanx.com/api/v1/jobs \
  -H "X-API-Key: YOUR_API_KEY"
Keep your API key secret. Do not expose it in client-side code or public repositories.

API Playground

Try the extraction endpoint live. Pick a document type, paste your API key, upload a file, and run a real request.

This runs a real extraction against your account and consumes credits. Your API key is sent directly to the API over HTTPS and is never stored by this page.
Document type
Document file

Drag & drop a file or click to browse

JPEG, PNG, WebP, HEIC, or PDF · max 5 MB

Document Extraction

Extract structured data from documents (receipts, invoices, etc.) via our intelligent OCR engine.

POST/api/v1/extract/{document_type}
Requires API key authenticationTimeout: 120 seconds
Document type

Request

Send a document image as multipart/form-data.

ParameterTypeDescription
document_type*stringDocument type (path parameter): receipt, invoice, bank_statement, purchase_order, sales_order
file*fileDocument file (JPEG, PNG, WebP, HEIC, or PDF). Max 5 MB.
curl -X POST https://api.escanx.com/api/v1/extract/receipt \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@receipt.jpg"

Response

The extraction object is nested and document-type-specific — switch the document type above to see each shape.

{
  "success": true,
  "request_id": "req_abc123def456",
  "processing_time_ms": 1250,
  "document_type": "receipt",
  "extraction": {
    "merchant": {
      "name": "Helsinki Market",
      "address": {
        "city": "Helsinki",
        "country_code": "FI"
      },
      "business_id": "1234567-8"
    },
    "buyer": {
      "name": "Aurora Digital Oy",
      "business_id": "7788990-1"
    },
    "transaction": {
      "date": "2025-01-15",
      "time": "14:30",
      "receipt_number": "A-4471"
    },
    "items": [
      {
        "line_number": 1,
        "description": "Coffee 250g",
        "quantity": 1,
        "unit_price": 4.9,
        "item_total": 4.9
      }
    ],
    "financial": {
      "subtotal": 43.1,
      "tax": [
        {
          "rate": 25.5,
          "amount": 4.75
        }
      ],
      "tax_total": 4.75,
      "total": 47.85,
      "currency": "EUR"
    },
    "payments": [
      {
        "method": "card",
        "card_type": "Visa",
        "card_last4": "4242",
        "amount": 47.85
      }
    ],
    "loyalty": {
      "card_number": "9012345678",
      "points_earned": 12,
      "points_balance": 340
    },
    "metadata": {
      "sub_type": "grocery",
      "confidence": {
        "overall": 0.97
      }
    }
  },
  "error": null
}
ParameterTypeDescription
successbooleanWhether the extraction succeeded
request_idstringUnique request identifier
processing_time_msnumberProcessing time in milliseconds
extractionobjectExtracted data — a nested object whose shape depends on document_type (e.g. receipt: merchant, transaction, items, financial, metadata; invoice: seller, invoice_details, …)
document_typestring | nullDocument type that was processed
errorstring | nullError message if extraction failed

Async Jobs

Submit documents for asynchronous extraction. Ideal for large files or batch workflows where you don't need immediate results.

Requires API key authentication

Submit a Job

POST/api/v1/jobs/{document_type}

Submit a document for background processing. Returns a job ID you can poll for results.

ParameterTypeDescription
document_type*stringDocument type (path parameter): receipt, invoice, bank_statement, purchase_order, sales_order
file*fileDocument file (JPEG, PNG, WebP, HEIC, or PDF). Sent as multipart/form-data.
webhook_urlstringHTTPS URL to receive completion notification. Sent as a query string parameter, not a form field.
curl -X POST https://api.escanx.com/api/v1/jobs/invoice \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@invoice.pdf"

Check Job Status

GET/api/v1/jobs/{job_id}

Poll the job status until it reaches a terminal state.

Status Values
pendingJob is queued for processing
processingJob is being processed
completedExtraction successful — results in extraction field
failedExtraction failed — error details in error field
cancelledJob was cancelled
curl https://api.escanx.com/api/v1/jobs/JOB_ID \
  -H "X-API-Key: YOUR_API_KEY"

Webhooks

Instead of polling, provide a webhook_url when submitting a job. Your endpoint will receive a POST request when the job completes or fails. The response includes a webhook_secret for verifying request signatures.

Requirements
URL must use HTTPS
URL must be publicly accessible (no private IPs)
Endpoint must respond with 2xx within 10 seconds
# Submit job with webhook notification (webhook_url is a query parameter)
curl -X POST "https://api.escanx.com/api/v1/jobs/invoice?webhook_url=https://your-app.com/webhooks/escanx" \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@invoice.pdf"

Store the webhook_secret returned in the job submission response. Use it to verify that incoming webhook requests are from eScanX.

List Jobs

GET/api/v1/jobs

List your extraction jobs with optional filters.

ParameterTypeDescription
statusstringFilter by job status (e.g. pending, completed, failed)
document_typestringFilter by document type (e.g. receipt, invoice)
pageintegerPage number (default: 1)
page_sizeintegerItems per page (default: 20, max: 100)

Cancel a Job

POST/api/v1/jobs/{job_id}/cancel

Cancel a job that is still in pending status.

Retry a Job

POST/api/v1/jobs/{job_id}/retry

Retry a job that has failed.

Job Statistics

GET/api/v1/jobs/stats

Get aggregate counts of your jobs and your current pending-job capacity.

ParameterTypeDescription
totalnumberTotal number of jobs
by_statusobjectJob counts keyed by status
pending_limitnumberMaximum number of pending jobs allowed
pending_remainingnumberRemaining pending-job slots
curl https://api.escanx.com/api/v1/jobs/stats \
  -H "X-API-Key: YOUR_API_KEY"

Usage Statistics

Check your API usage, quota, and remaining calls for the current billing period.

GET/api/v1/usage
Requires API key authentication
ParameterTypeDescription
daysintegerNumber of days to include in the statistics window (default: current billing period)
curl "https://api.escanx.com/api/v1/usage?days=30" \
  -H "X-API-Key: YOUR_API_KEY"

Response

ParameterTypeDescription
api_key_idnumberID of the API key the stats are for
api_key_namestring | nullLabel of the API key (null if unnamed)
period_startstringStart of the reporting period (ISO 8601)
period_endstringEnd of the reporting period (ISO 8601)
total_requestsnumberTotal API requests in the period
successful_requestsnumberNumber of successful extractions
failed_requestsnumberNumber of failed extractions
success_ratenumberSuccess rate as a percentage
avg_processing_time_msnumber | nullAverage processing time in milliseconds (null if no requests)
quota_limitnumber | nullQuota limit for the period, if applicable
quota_usednumber | nullQuota consumed in the current period
quota_remainingnumber | nullQuota remaining in the current period

Health Checks

Monitor the API status with liveness and readiness endpoints. No authentication required.

Liveness Check

GET/health
No authentication required

Returns OK if the API server is running.

curl https://api.escanx.com/health

Readiness Check

GET/health/ready
No authentication required

Returns OK if the API and all dependencies (database) are ready to serve requests.

curl https://api.escanx.com/health/ready

Error Handling

The API uses standard HTTP status codes. Error responses follow the RFC 7807 problem+json format with flat fields.

Error Response Format

{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "The uploaded file type is not supported",
"error_code": "INVALID_FILE_TYPE",
"error_id": "err_abc123",
"instance": "/api/v1/extract/receipt",
"timestamp": "2026-01-15T12:00:00Z"
}
ParameterTypeDescription
detailstringHuman-readable error description
error_codestringMachine-readable error code
error_idstringUnique identifier for this error (useful for support)

Validation Errors (422)

Validation failures return a 422 with a detail array — one entry per invalid field, each with its location, message, and type.

{
"detail": [{
"loc": ["body", "file"],
"msg": "field required",
"type": "value_error.missing"
}]
}

HTTP Status Codes

400Bad Request — Invalid parameters or missing required fields
401Unauthorized — Missing or invalid API key
403Forbidden — the email associated with the API key is not verified
404Not Found — The requested resource does not exist
413Payload Too Large — File exceeds the maximum allowed size
422Unprocessable Entity — Request body validation failed
429Too Many Requests — Rate limit exceeded. Check Retry-After header
500Internal Server Error — Something went wrong on our end
502Bad Gateway — Extraction service returned an error
503Service Unavailable — Extraction service is temporarily unavailable
504Gateway Timeout — Extraction service did not respond in time

Rate Limits

API requests are rate-limited per API key to ensure fair usage and platform stability.

How it works

Rate limits are applied per API key. When you exceed the limit, requests return HTTP 429.

The response includes a Retry-After header indicating how many seconds to wait before retrying.

Handling Rate Limits

Implement exponential backoff when you receive a 429 response.

async function extractWithRetry(file, documentType, maxRetries = 3) {
  const formData = new FormData()
  formData.append('file', file)

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(`https://api.escanx.com/api/v1/extract/${documentType}`, {
      method: 'POST',
      headers: { 'X-API-Key': 'YOUR_API_KEY' },
      body: formData
    })

    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || '5'
      await new Promise(r => setTimeout(r, parseInt(retryAfter) * 1000))
      continue
    }

    return await response.json()
  }
  throw new Error('Max retries exceeded')
}

SDKs & Libraries

Official SDKs for popular programming languages are coming soon. For now, use our REST API directly with any HTTP client.

Native SDKs for JavaScript and Python are in development and will be available soon.
Complete extraction example
# Upload an invoice and extract structured data
curl -X POST https://api.escanx.com/api/v1/extract/invoice \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@invoice.pdf"

# Check your API usage
curl https://api.escanx.com/api/v1/usage \
  -H "X-API-Key: YOUR_API_KEY"

Ready to Get Started?

Create a free account and start extracting data from documents in minutes.

Get Free API Key