Loading...
Loading...
Call the OpenOCR REST API directly with cURL, JavaScript fetch, or Python requests. You do not need an OpenOCR package to get started.
Send JSON to https://api.open-ocr.com/v1/ocr and pass your API key as a Bearer token. The examples below all use the same request shape.
The primary endpoint accepts a public URL or base64-encoded document.
curl -X POST https://api.open-ocr.com/v1/ocr \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-ocr-your-api-key" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"engine": "mistral-mistral-ocr-4-1",
"input": {
"type": "url",
"url": "https://example.com/receipt.png"
}
}'# Encode a local file and send as base64
BASE64=$(base64 -w0 document.png)
curl -X POST https://api.open-ocr.com/v1/ocr \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-ocr-your-api-key" \
-H "Idempotency-Key: $(uuidgen)" \
-d "{
\"engine\": \"mistral-mistral-ocr-4-1\",
\"input\": {
\"type\": \"base64\",
\"data_base64\": \"$BASE64\",
\"mime_type\": \"image/png\"
}
}"import base64
import uuid
import requests
API_KEY = "sk-ocr-your-api-key"
BASE_URL = "https://api.open-ocr.com"
# --- From URL ---
resp = requests.post(
f"{BASE_URL}/v1/ocr",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"engine": "mistral-mistral-ocr-4-1",
"input": {"type": "url", "url": "https://example.com/receipt.png"},
},
)
resp.raise_for_status()
result = resp.json()
if result["status"] != "succeeded":
raise RuntimeError(f"OCR ended as {result['status']}: {result.get('provider_error')}")
print(f"Text: {result['extracted_text'][:200]}")
print(f"Latency: {result['provider_latency_ms']}ms")
print(f"Cost: ${result['cost_debited']}")
# --- From local file ---
with open("document.png", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
resp = requests.post(
f"{BASE_URL}/v1/ocr",
headers={
"Authorization": f"Bearer {API_KEY}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"engine": "mistral-mistral-ocr-4-1",
"input": {
"type": "base64",
"data_base64": b64,
"mime_type": "image/png",
},
},
)
resp.raise_for_status()
body = resp.json()
assert body["status"] == "succeeded", body
print(body["extracted_text"])import { readFileSync } from 'fs';
const API_KEY = process.env.OPENOCR_API_KEY!;
const BASE_URL = 'https://api.open-ocr.com';
// --- From URL ---
const resp = await fetch(`${BASE_URL}/v1/ocr`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
engine: 'mistral-mistral-ocr-4-1',
input: { type: 'url', url: 'https://example.com/receipt.png' },
}),
});
const result = await resp.json();
if (result.status !== "succeeded") throw new Error("OCR ended as " + (result.status ?? result.error?.code)); // error envelopes have no status
if (!resp.ok) throw new Error(result.error?.message ?? `HTTP ${resp.status}`);
console.log(result.extracted_text);
console.log(`Latency: ${result.provider_latency_ms}ms, Cost: $${result.cost_debited}`);
// --- From local file ---
const b64 = readFileSync('document.png').toString('base64');
const fileResp = await fetch(`${BASE_URL}/v1/ocr`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_KEY}`,
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
engine: 'mistral-mistral-ocr-4-1',
input: { type: 'base64', data_base64: b64, mime_type: 'image/png' },
}),
});
const fileResult = await fileResp.json();
if (fileResult.status !== "succeeded") throw new Error("OCR ended as " + (fileResult.status ?? fileResult.error?.code)); // error envelopes have no status
if (!fileResp.ok) throw new Error(fileResult.error?.message ?? `HTTP ${fileResp.status}`);
console.log(fileResult.extracted_text);Returns all engines with availability, pricing, and supported languages. No auth required.
curl https://api.open-ocr.com/v1/engines | jq '.data[] | {id, name, status}'import requests
BASE_URL = "https://api.open-ocr.com"
resp = requests.get(f"{BASE_URL}/v1/engines")
engines = resp.json()["data"]
for engine in engines:
status = "✅" if engine["status"] == "available" else "🔜"
print(f"{status} {engine['id']} — {engine['name']}")
print(f" Price: ${engine['pricing']['per_page_usd']}/page")
print(f" Languages: {len(engine.get('supported_languages', []))}")
# Filter to available engines only
available = [e for e in engines if e["status"] == "available"]
print(f"\n{len(available)} engines ready to use")const BASE_URL = 'https://api.open-ocr.com';
const resp = await fetch(`${BASE_URL}/v1/engines`);
const { data: engines } = await resp.json();
const available = engines.filter((e: any) => e.status === 'available');
console.log(`${available.length} engines available:`);
available.forEach((e: any) => {
console.log(` ${e.id} — ${e.name} ($${e.pricing.per_page_usd}/page)`);
});Check your remaining credits and usage statistics. Requires authentication.
curl https://api.open-ocr.com/v1/usage \
-H "Authorization: Bearer sk-ocr-your-api-key" | jqimport os
import requests
BASE_URL = "https://api.open-ocr.com"
API_KEY = os.environ["OPENOCR_API_KEY"]
resp = requests.get(
f"{BASE_URL}/v1/usage",
headers={"Authorization": f"Bearer {API_KEY}"},
)
usage = resp.json()
print(f"Balance: ${usage['balance_usd']}")
print(f"Total requests: {usage['total_requests']}")
print(f"Pages processed: {usage['total_pages']}")const BASE_URL = 'https://api.open-ocr.com';
const API_KEY = process.env.OPENOCR_API_KEY!;
const resp = await fetch(`${BASE_URL}/v1/usage`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const usage = await resp.json();
console.log(`Balance: $${usage.balance_usd}`);
console.log(`Total requests: ${usage.total_requests}`);Public endpoints for monitoring. No authentication required.
# Health check — returns 200 if all systems operational
curl https://api.open-ocr.com/v1/health
# Status — returns version and uptime
curl https://api.open-ocr.com/v1/status | jqimport time
import requests
def check_health(base_url: str = "https://api.open-ocr.com") -> bool:
"""Returns True if API is healthy."""
try:
resp = requests.get(f"{base_url}/v1/health", timeout=5)
return resp.status_code == 200
except requests.RequestException:
return False
# Simple polling monitor
while True:
healthy = check_health()
status = "✅ UP" if healthy else "❌ DOWN"
print(f"[{time.strftime('%H:%M:%S')}] {status}")
time.sleep(60)All successful OCR responses follow this structure:
{
"request_id": "req_abc123",
"status": "succeeded",
"engine": "mistral-mistral-ocr-4-1",
"extracted_text": "Invoice #1234\nDate: 2026-02-24\n...",
"provider_latency_ms": 342,
"cost_debited": 0.005
}Error responses use a consistent envelope:
{
"error": {
"code": "unknown_engine",
"message": "'fake/engine' is not a known engine id. List valid ids with GET /v1/engines."
}
}Rate limits depend on your account tier. Authenticated responses include headers showing the current limit, remaining requests, and reset time:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1709301600
Retry-After: 8 # Only present on 429 responsesWhen rate limited, wait for the Retry-After seconds before retrying. See the error handling examples for automatic retry logic.
Official Python and JavaScript/TypeScript SDKs are not published yet. Until they are, use the HTTP examples above or any standards-compliant HTTP client. Do not install a third-party package named OpenOCR; packages with similar names are not maintained by us.