Skip to main content
Submit a document for OCR. We extract text, detect tables, and optionally generate a searchable PDF. Processing is async — you get a job ID immediately, then poll for results or use webhooks.
Endpoint
POST /ocr/v1/process
curl -X POST https://api.case.dev/ocr/v1/process \
  -H "Authorization: Bearer sk_case_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "document_url": "https://storage.example.com/scanned-deposition.pdf"
  }'
casedev ocr:v1 process \
  --document-url "https://storage.example.com/document.pdf"
import Casedev from 'casedev';

const client = new Casedev({ apiKey: 'sk_case_YOUR_API_KEY' });

const job = await client.ocr.v1.process({
  document_url: 'https://storage.example.com/scanned-deposition.pdf'
});

console.log(job.id); // 1f4a195e-026b-41ff-b367-c61089f5f367
import casedev

client = casedev.Casedev(api_key='sk_case_YOUR_API_KEY')

job = client.ocr.v1.process(
    document_url='https://storage.example.com/scanned-deposition.pdf'
)

print(job.id)  # 1f4a195e-026b-41ff-b367-c61089f5f367
job, _ := client.Ocr.V1.Process(ctx, casedev.OcrV1ProcessParams{
	DocumentURL: casedev.F("https://storage.example.com/document.pdf"),
})
fmt.Println(job.ID)
Response
{
  "id": "1f4a195e-026b-41ff-b367-c61089f5f367",
  "status": "pending",
  "document_url": "https://storage.example.com/scanned-deposition.pdf",
  "engine": "doctr",
  "created_at": "2025-11-04T09:30:12Z",
  "links": {
    "self": "https://api.case.dev/ocr/v1/1f4a195e-026b-41ff-b367-c61089f5f367",
    "text": "https://api.case.dev/ocr/v1/1f4a195e-026b-41ff-b367-c61089f5f367/download/text",
    "json": "https://api.case.dev/ocr/v1/1f4a195e-026b-41ff-b367-c61089f5f367/download/json"
  }
}

Parameters

Required

ParameterTypeDescription
document_urlstringURL to your document. HTTP/HTTPS or s3://

Optional

ParameterTypeDefaultDescription
document_idstringauto-generatedYour internal reference ID
enginestringdoctrOCR engine (see below)
callback_urlstringWebhook URL for completion notification
featuresobject{}Additional processing options

OCR engines

EngineBest forSpeed
doctrClean printed text, typed documentsFast
paddleocrTables, forms, complex layouts, handwritingMedium
For legal documents: Start with doctr. If you’re getting poor results on forms or tables, try paddleocr.

Features

Enable additional processing:
JSON
{
  "features": {
    "embed": {},          // Generate searchable PDF
    "tables": {           // Extract tables as CSV
      "format": "csv"
    }
  }
}

Checking status

Poll the job to check if processing is complete:
casedev ocr:v1 retrieve --id $JOB_ID
const result = await client.ocr.v1.retrieve(job.id);

if (result.status === 'completed') {
  // Download the extracted text
  const text = await client.ocr.v1.download(job.id, 'text');
  console.log(text);
}
result = client.ocr.v1.retrieve(job.id)

if result.status == 'completed':
    # Download the extracted text
    text = client.ocr.v1.download(job.id, 'text')
    print(text)
result, _ := client.Ocr.V1.Get(ctx, jobID)
fmt.Println(result.Status)

Using webhooks

For large documents, use webhooks instead of polling:
casedev ocr:v1 process \
  --document-url "https://storage.example.com/500-page-discovery.pdf" \
  --callback-url "https://your-app.com/api/ocr-complete"
const job = await client.ocr.v1.process({
  document_url: 'https://storage.example.com/500-page-discovery.pdf',
  callback_url: 'https://your-app.com/api/ocr-complete'
});
job = client.ocr.v1.process(
    document_url='https://storage.example.com/500-page-discovery.pdf',
    callback_url='https://your-app.com/api/ocr-complete'
)
job, _ := client.Ocr.V1.Process(ctx, casedev.OcrV1ProcessParams{
	DocumentURL: casedev.F("https://storage.example.com/500-page-discovery.pdf"),
	CallbackURL: casedev.F("https://your-app.com/api/ocr-complete"),
})
We POST the completed job to your callback URL when processing finishes.

S3 URLs

If your document is in S3, use an s3:// URL:
casedev ocr:v1 process \
  --document-url "s3://your-bucket/documents/deposition.pdf"
const job = await client.ocr.v1.process({
  document_url: 's3://your-bucket/documents/deposition.pdf'
});
job = client.ocr.v1.process(
    document_url='s3://your-bucket/documents/deposition.pdf'
)
job, _ := client.Ocr.V1.Process(ctx, casedev.OcrV1ProcessParams{
	DocumentURL: casedev.F("s3://your-bucket/documents/deposition.pdf"),
})
We automatically generate a presigned URL to access the file.

Examples

Scanned deposition

casedev ocr:v1 process \
  --document-url "https://storage.example.com/deposition-smith.pdf" \
  --document-id smith-depo-2024 \
  --engine doctr \
  --features.embed '{}'
const job = await client.ocr.v1.process({
  document_url: 'https://storage.example.com/deposition-smith.pdf',
  document_id: 'smith-depo-2024',
  engine: 'doctr',
  features: { embed: {} }  // Generate searchable PDF
});
job = client.ocr.v1.process(
    document_url='https://storage.example.com/deposition-smith.pdf',
    document_id='smith-depo-2024',
    engine='doctr',
    features={'embed': {}}  # Generate searchable PDF
)
job, _ := client.Ocr.V1.Process(ctx, casedev.OcrV1ProcessParams{
	DocumentURL: casedev.F("https://storage.example.com/deposition-smith.pdf"),
	DocumentID:  casedev.F("smith-depo-2024"),
	Engine:      casedev.F(casedev.OcrV1ProcessParamsEngineDoctr),
	Features: casedev.F(casedev.OcrV1ProcessParamsFeatures{
		Embed: casedev.F(casedev.OcrV1ProcessParamsFeaturesEmbed{}),
	}),
})

Medical records with tables

casedev ocr:v1 process \
  --document-url "https://storage.example.com/patient-records.pdf" \
  --engine paddleocr \
  --features.tables '{"format": "csv"}' \
  --features.embed '{}' \
  --callback-url "https://your-app.com/webhooks/ocr"
const job = await client.ocr.v1.process({
  document_url: 'https://storage.example.com/patient-records.pdf',
  engine: 'paddleocr',  // Better for tables and forms
  features: {
    tables: { format: 'csv' },
    embed: {}
  },
  callback_url: 'https://your-app.com/webhooks/ocr'
});
job = client.ocr.v1.process(
    document_url='https://storage.example.com/patient-records.pdf',
    engine='paddleocr',  # Better for tables and forms
    features={
        'tables': {'format': 'csv'},
        'embed': {}
    },
    callback_url='https://your-app.com/webhooks/ocr'
)
job, _ := client.Ocr.V1.Process(ctx, casedev.OcrV1ProcessParams{
	DocumentURL: casedev.F("https://storage.example.com/patient-records.pdf"),
	Engine:      casedev.F(casedev.OcrV1ProcessParamsEnginePaddleocr),
	Features: casedev.F(casedev.OcrV1ProcessParamsFeatures{
		Tables: casedev.F(casedev.OcrV1ProcessParamsFeaturesTables{Format: casedev.F("csv")}),
		Embed:  casedev.F(casedev.OcrV1ProcessParamsFeaturesEmbed{}),
	}),
	CallbackURL: casedev.F("https://your-app.com/webhooks/ocr"),
})

Handwritten notes

casedev ocr:v1 process \
  --document-url "https://storage.example.com/witness-notes.jpg" \
  --engine paddleocr
const job = await client.ocr.v1.process({
  document_url: 'https://storage.example.com/witness-notes.jpg',
  engine: 'paddleocr'  // Better for handwriting
});
job = client.ocr.v1.process(
    document_url='https://storage.example.com/witness-notes.jpg',
    engine='paddleocr'  # Better for handwriting
)
job, _ := client.Ocr.V1.Process(ctx, casedev.OcrV1ProcessParams{
	DocumentURL: casedev.F("https://storage.example.com/witness-notes.jpg"),
	Engine:      casedev.F(casedev.OcrV1ProcessParamsEnginePaddleocr),
})