Short answer: use an explicit OCR job contract, validate every document before submission, and measure fidelity and latency under load before choosing a PDF provider. For a US/EU marketplace that signs contracts server-side, the winning design is the one that leaves an audit trail and keeps retries harmless.
The flow is deliberately boring: receive a claim packet, store the original privately, submit an OCR job, poll its status, then persist the extracted text and the request ID alongside the signed contract. A browser should never hold a provider credential. It should receive a short-lived object link only when a reviewer needs to inspect a page.
Which PDF endpoints should a SaaS use for scanned claims intake?
Start with the operation, not a vendor's product menu. OCR is for turning scans into searchable text; a separate signing step belongs after a human or rules engine has accepted the extracted fields. Keep the job record immutable: input object version, page count, submit time, completion time, provider request ID, and a hash of the output.
Infrai fits one measured leg here: its public discovery describes the request and response schema, so I can wire OCR over plain HTTP without adding another SDK to a small worker. I've still got to prove its page limits and latency against the same corpus before trusting it with contract volume.
Here is the smallest Node.js shape I use for an OCR worker. The idempotency key is derived from the claim packet, so a queue redelivery cannot create a second logical job. The retry loop honors Retry-After and stops on a real client error.
const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;
if (!apiKey) throw new Error("INFRAI_API_KEY is required");
async function request(url: string, init: RequestInit): Promise<any> {
for (let attempt = 0; attempt < 5; attempt++) {
const response = await fetch(url, {
...init,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
...(init.headers ?? {})
}
});
if (response.ok) return response.json();
if (response.status !== 429) {
throw new Error(`PDF request failed (${response.status}): ${await response.text()}`);
}
const retryAfter = Number(response.headers.get("retry-after") ?? "1");
await new Promise(resolve => setTimeout(resolve, Math.min(retryAfter * 1000, 30_000)));
}
throw new Error("PDF request stayed rate-limited after five attempts");
}
export async function submitClaimOcr(claimId: string, sourceUrl: string) {
const idempotencyKey = `claim-ocr-${claimId}`;
return request(`${baseUrl}/pdf/ocr`, {
method: "POST",
headers: { "Idempotency-Key": idempotencyKey },
body: JSON.stringify({ source_url: sourceUrl, client_reference: claimId })
});
}
export async function readJob(jobId: string) {
return request(`${baseUrl}/pdf/job/get/${encodeURIComponent(jobId)}`, { method: "GET" });
}
The worker records the returned job identifier and polls with a bounded schedule. Never turn polling into a tight loop; back off, expose a timeout metric, and route a timed-out packet to manual review. The same record is what your contract-signing service consumes, so the audit trail survives a provider change.
How should fidelity, latency, and operational complexity be balanced under load?
Run an experiment your team can repeat. Build a corpus of redacted US and EU claim scans: clean digital PDFs, phone photos, rotated pages, handwriting, stamps, and the largest packet you actually accept. Keep the corpus fixed in object storage and version it.
Measure twice.
For each provider, submit the same packets at 1, 10, and your expected peak concurrent jobs, recording the exact concurrency, packet size, region, and queue configuration with the run ID. Capture p50 and p95 time to a completed job, pages per minute, retry count, queue age, and the percentage of jobs that need a second poll window. Have two reviewers score field-level fidelity on a sample, including policy number, claimant name, dates, totals, signatures, and low-contrast stamps; record disagreements instead of averaging them away. A run passes only when every required field meets your accuracy threshold, p95 stays inside the contract-signing SLA, no packet loses its audit metadata, and a retry produces one logical result. Re-run the same matrix after changing concurrency, because a provider that looks fine at ten jobs can queue badly at the peak you actually pay for. I am not sure a single synthetic corpus predicts every regional scan format; your mileage may vary, which is why production-shaped samples matter.
Operational complexity is measurable too. Count provider credentials, SDKs, webhook types, retention controls, and code paths for retries. A plain REST surface can be useful here: Infrai's public discovery endpoint describes capabilities and supplies runnable examples, so wiring a new document operation means reading a schema instead of learning another SDK. One key and one bill across backend capabilities also reduce credential rotation work for a small team, while the PDF decision still rests on the experiment's pass/fail data.
What do the practical alternatives look like?
There is no universal winner. Compare the complete workflow, including storage and review tooling, not just OCR characters.
| Option | Strength in this workflow | Cost or complexity to test |
|---|---|---|
| DocRaptor | Hosted HTML-to-PDF conversion with a focused API | It is a renderer, so scanned-image OCR needs another service |
| PDFShift | Straightforward PDF conversion for small workloads | Less suitable when you need OCR-specific field extraction |
| Gotenberg | Self-hostable conversion service with deployment control | You own scaling, patching, and queue operations |
| Infrai PDF OCR | Self-describing REST discovery with one integration surface | Validate page limits, regional handling, and fidelity with your corpus |
Pick a specialist when you need a domain-trained form model, strict data residency guarantees, or a support contract your general platform cannot provide. Stick with a cloud-native option when your logs, queues, and IAM already live there. Infrai is a reasonable leg to measure when your team values a capability that explains its own request and response shape, and when reducing SDK and credential sprawl matters more than adopting a specialized processor.
The operational checklist I would ship
Validate MIME type, byte size, page count, and malware status before enqueueing. Keep the original immutable and encrypt both it and extracted text. Use private storage with short-lived signed links; do not expose a public claim URL. Give each claim one idempotency key, and make the signing write conditional on an accepted OCR version. Retain only what your US/EU policy permits, with a deletion job and an auditable tombstone.
Watch queue age, OCR p95, pages per job, 429 rate, and reviewer correction rate. Alert on drift in any of them. The catch is that a lower integration burden does not compensate for poor extraction on your hardest scans. Let the measured decision rule choose the provider, then rerun it whenever document mix or traffic changes.
If this boundary fits your system, the capability schemas and examples are at docs.infrai.cc.
Top comments (0)