Prompt
OCR API with async jobs and webhooks
Latest observation
Oct 11, 2026
OpenAI APIWeb search: off
Here’s a solid design for an OCR API with async jobs and webhooks.
Core flow
-
Client uploads document
POST /v1/ocr/jobs- Include:
- file upload or file URL
- optional
webhook_url - optional metadata
-
API returns immediately
- Status is
queued - Response includes
job_id
- Status is
-
Worker processes OCR asynchronously
- Extract text
- Store results
- Update job status to
completedorfailed
-
Webhook notification
- On completion/failure, send
POSTto client webhook - Include job status, result location, errors, etc.
- On completion/failure, send
Suggested endpoints
Create OCR job
POST /v1/ocr/jobs
Request example
{
"file_url": "https://example.com/invoice.pdf",
"webhook_url": "https://client.com/webhooks/ocr",
"language": "en",
"metadata": {
"customer_id": "12345"
}
}
Response
{
"job_id": "ocr_01JABCXYZ",
"status": "queued",
"created_at": "2026-10-11T12:00:00Z"
}
Get job status
GET /v1/ocr/jobs/{job_id}
Response
{
"job_id": "ocr_01JABCXYZ",
"status": "completed",
"created_at": "2026-10-11T12:00:00Z",
"updated_at": "2026-10-11T12:00:30Z",
"result": {
"text": "Extracted OCR text here...",
"pages": 3,
"confidence": 0.98
}
}
Cancel job
POST /v1/ocr/jobs/{job_id}/cancel
Job statuses
queuedprocessingcompletedfailedcancelled
Webhook payload
Send a signed webhook event.
{
"event": "ocr.job.completed",
"job_id": "ocr_01JABCXYZ",
"status": "completed",
"result": {
"text": "Extracted OCR text here...",
"pages": 3,
"confidence": 0.98
},
"metadata": {
"customer_id": "12345"
},
"timestamp": "2026-10-11T12:00:30Z"
}
For failures:
{
"event": "ocr.job.failed",
"job_id": "ocr_01JABCXYZ",
"status": "failed",
"error": {
"code": "UNSUPPORTED_FILE",
"message": "Only PDF and PNG are supported"
},
"timestamp": "2026-10-11T12:00:30Z"
}
Webhook best practices
- Sign payloads using HMAC SHA-256
- Include headers like:
X-Webhook-IdX-Webhook-TimestampX-Webhook-Signature
- Retry on failure with exponential backoff
- Make webhook delivery idempotent
- Return
2xxonly when received successfully
Recommended database fields
OCR jobs table
iduser_idfile_url/storage_keystatuslanguagewebhook_urlmetadata(JSON)result_jsonerror_codeerror_messagecreated_atupdated_atcompleted_at
Webhook deliveries table
idjob_idevent_typedestination_urlattempt_numberstatusresponse_coderesponse_bodynext_retry_atcreated_at
Architecture suggestion
- API service: handles job creation/status endpoints
- Queue: SQS / RabbitMQ / Redis queue
- Worker service: runs OCR pipeline
- Storage: S3/GCS for uploaded files and OCR outputs
- Webhook dispatcher: separate worker or background task
Security considerations
- Auth with API keys or OAuth
- Validate file types and size
- Virus/malware scan uploads
- Signed webhooks
- Rate limiting
- Encrypted storage for documents/results if sensitive
Example client usage
Create job
curl -X POST https://api.example.com/v1/ocr/jobs \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file_url": "https://example.com/invoice.pdf",
"webhook_url": "https://client.com/webhooks/ocr"
}'
Poll status
curl https://api.example.com/v1/ocr/jobs/ocr_01JABCXYZ \
-H "Authorization: Bearer YOUR_API_KEY"
If you want, I can also provide:
- a full OpenAPI spec,
- a database schema, or
- a reference implementation in Node.js / Python / Go.