Chat Completions
OpenAI-compatible endpoint for document OCR
Chat Completions
The /v1/chat/completions endpoint is the recommended way to use DocsRouter. It's fully compatible with OpenAI and OpenRouter SDKs, making integration seamless with your existing codebase.
Endpoint
POST https://api.docsrouter.com/v1/chat/completionsAuthentication
All requests to this endpoint require authentication via the Authorization header using a Bearer token.
Authorization: Bearer YOUR_API_KEYKeep your API key secure. Never expose it in client-side code, public repositories, or browser applications. Always make API calls from your server.
You can generate API keys from the DocsRouter Dashboard. Each key can be named for easy identification and revoked individually if compromised.
Request Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer token with your API key: Bearer YOUR_API_KEY |
Content-Type | Yes | Must be application/json |
X-Request-ID | No | Optional unique identifier for request tracing |
Request Body
The request follows the OpenAI chat completions format:
{
"model": "google/gemini-2.0-flash-001",
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": "Extract all text from this document"
},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/invoice.png"
}
}
]
}
],
"docsrouter": {
"extract_tables": true,
"output_format": "json"
}
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Model ID (e.g., google/gemini-2.0-flash-001) |
messages | array | Yes | Array of message objects |
temperature | number | No | Sampling temperature (0-2) |
max_tokens | number | No | Maximum tokens to generate |
docsrouter | object | No | DocsRouter-specific options |
DocsRouter Options
| Option | Type | Default | Description |
|---|---|---|---|
extract_tables | boolean | false | Extract tables as structured data |
extract_key_values | boolean | false | Extract form key-value pairs |
output_format | string | "text" | Output format: text, markdown, or json |
language_hint | string | null | ISO 639-1 language code hint |
Message Content Types
Messages can contain text, images, and files (PDFs):
{
"role": "user",
"content": [
{ "type": "text", "text": "Your instructions here" },
{ "type": "image_url", "image_url": { "url": "https://..." } }
]
}Image URL formats supported:
- HTTP/HTTPS URLs:
https://example.com/document.png - Data URIs:
data:image/png;base64,iVBORw0KGgo...
PDF File Support
You can send PDF documents directly using the file content type:
{
"role": "user",
"content": [
{ "type": "text", "text": "Extract all text from this PDF" },
{
"type": "file",
"file": {
"filename": "document.pdf",
"file_data": "https://example.com/document.pdf"
}
}
]
}File data formats supported:
- HTTP/HTTPS URLs:
https://example.com/document.pdf - Data URIs:
data:application/pdf;base64,JVBERi0xLjQ...
PDF Processing Plugins
Configure PDF processing with the plugins parameter:
{
"model": "google/gemini-2.0-flash-001",
"messages": [...],
"plugins": [
{
"id": "file-parser",
"pdf": {
"engine": "mistral-ocr"
}
}
]
}Available PDF engines:
| Engine | Description | Pricing |
|---|---|---|
pdf-text | Best for well-structured PDFs with clear text | Free |
mistral-ocr | Best for scanned documents or PDFs with images | $0.10 per 1,000 pages |
native | Use model's native file processing (if supported) | Charged as input tokens |
If no engine is specified, DocsRouter defaults to the model's native capabilities, falling back to pdf-text.
Response
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1734567890,
"model": "google/gemini-2.0-flash-001",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "INVOICE\n\nInvoice #: INV-2024-001\nDate: December 15, 2024\n\nBill To:\nAcme Corporation\n123 Business St\n..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 1200,
"completion_tokens": 450,
"total_tokens": 1650
},
"docsrouter": {
"confidence": 94,
"detected_language": "en",
"pages_processed": 1,
"tables_detected": 2,
"tables": [
{
"page_number": 1,
"headers": ["Item", "Quantity", "Price"],
"rows": [
["Widget A", "10", "$99.00"],
["Widget B", "5", "$49.50"]
],
"confidence": 92
}
],
"provider": "openrouter",
"provider_cost_cents": 1.2,
"platform_fee_cents": 0.4,
"total_cost_cents": 1.6,
"processing_time_ms": 1850
}
}Response Fields
Standard OpenAI fields:
id- Unique completion IDobject- Alwayschat.completioncreated- Unix timestampmodel- Model usedchoices- Array of completion choicesusage- Token usage statistics
DocsRouter extensions (docsrouter object):
confidence- OCR confidence score (0-100)detected_language- Detected document languagepages_processed- Number of pages processedtables_detected- Number of tables foundtables- Extracted table data (ifextract_tableswas true)provider_cost_cents- Provider cost in centsplatform_fee_cents- DocsRouter fee in centstotal_cost_cents- Total cost in centsprocessing_time_ms- Processing time in milliseconds
Examples
Basic Image OCR
curl -X POST https://api.docsrouter.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.0-flash-001",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Extract all text from this document"},
{"type": "image_url", "image_url": {"url": "https://example.com/invoice.png"}}
]
}]
}'Processing a PDF with Mistral OCR
For best PDF processing, use the mistral-ocr engine which calls Mistral's dedicated OCR API directly:
curl -X POST https://api.docsrouter.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.0-flash-001",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Extract all text from this PDF"},
{
"type": "file",
"file": {
"filename": "document.pdf",
"file_data": "https://example.com/document.pdf"
}
}
]
}],
"plugins": [{
"id": "file-parser",
"pdf": {"engine": "mistral-ocr"}
}]
}'PDF with Base64 Data
# First, encode your PDF to base64
PDF_BASE64=$(base64 -i document.pdf)
curl -X POST https://api.docsrouter.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.0-flash-001",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Extract all text"},
{
"type": "file",
"file": {
"filename": "document.pdf",
"file_data": "data:application/pdf;base64,'"$PDF_BASE64"'"
}
}
]
}],
"plugins": [{
"id": "file-parser",
"pdf": {"engine": "mistral-ocr"}
}]
}'With Table Extraction
curl -X POST https://api.docsrouter.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.0-flash-001",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Extract all text and tables from this invoice"},
{"type": "image_url", "image_url": {"url": "https://example.com/invoice.png"}}
]
}],
"docsrouter": {
"extract_tables": true,
"output_format": "json"
}
}'Image with Base64 Data
# Encode image to base64
IMG_BASE64=$(base64 -i document.png)
curl -X POST https://api.docsrouter.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.0-flash-001",
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Extract all text"},
{"type": "image_url", "image_url": {"url": "data:image/png;base64,'"$IMG_BASE64"'"}}
]
}]
}'Streaming
DocsRouter supports streaming responses for real-time text extraction. Enable streaming by setting stream: true:
curl -X POST https://api.docsrouter.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/gemini-2.0-flash-001",
"stream": true,
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Extract all text from this document"},
{"type": "image_url", "image_url": {"url": "https://example.com/invoice.png"}}
]
}]
}'Streaming responses are sent as Server-Sent Events (SSE):
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"delta":{"content":"INVOICE"},"index":0}]}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"delta":{"content":" #001"},"index":0}]}
data: [DONE]Rate Limits
The API implements rate limiting to ensure fair usage and system stability:
| Tier | Requests/Minute | Requests/Day |
|---|---|---|
| Free | 10 | 100 |
| Starter | 60 | 1,000 |
| Pro | 300 | 10,000 |
| Enterprise | Custom | Custom |
Rate limit headers are included in every response:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1734567890If you exceed your rate limit, you'll receive a 429 Too Many Requests response. Check the Retry-After header for when you can retry.
Error Handling
Errors follow the OpenAI error format:
{
"error": {
"message": "No images found in messages",
"type": "invalid_request_error",
"param": "messages",
"code": "missing_image"
}
}HTTP Status Codes
| Status Code | Description | Common Causes |
|---|---|---|
| 400 | Bad Request | Invalid JSON, missing required fields, invalid image URL |
| 401 | Unauthorized | Missing or invalid API key |
| 402 | Payment Required | Insufficient credits in your account |
| 403 | Forbidden | API key doesn't have permission for this operation |
| 404 | Not Found | Invalid model ID or endpoint |
| 413 | Payload Too Large | Image or PDF exceeds size limits (max 20MB) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Unexpected server error |
| 502 | Bad Gateway | Upstream provider (Google, OpenAI, etc.) is unavailable |
| 503 | Service Unavailable | DocsRouter is temporarily unavailable |
Common Error Codes
| Code | Description | Solution |
|---|---|---|
missing_image | No image or file found in messages | Include at least one image_url or file content block |
invalid_image_url | Image URL is not accessible | Ensure the URL is publicly accessible or use base64 |
unsupported_format | File format not supported | Use PNG, JPG, WEBP, GIF, or PDF |
model_not_found | Specified model doesn't exist | Check /v1/models for available models |
insufficient_credits | Account balance too low | Add credits in the dashboard |
context_length_exceeded | Document too large for model | Use a model with larger context or split the document |
Best Practices
Optimizing for Speed
- Use Gemini 2.0 Flash for most documents - it's the fastest and most cost-effective
- Compress images before sending - smaller files process faster
- Use streaming for real-time feedback in user-facing applications
- Batch similar documents when possible
Optimizing for Accuracy
- Use higher-quality models (GPT-4o, Claude Sonnet) for complex documents
- Provide clear instructions in your prompt about what to extract
- Use
mistral-ocrengine for scanned PDFs with poor quality - Set
language_hintif you know the document language
Handling Large Documents
- Multi-page PDFs: Use the
filecontent type withmistral-ocrengine - Large images: Resize to max 4096x4096 pixels before sending
- Many documents: Process in parallel with proper rate limiting