SDK · Node / TypeScript

ocrqueen — Node / TypeScript

Typed client for Node 18+. Zero runtime dependencies — uses the built-in fetch and FormData. Dual ESM / CJS build with .d.ts shipped.

Install

bash
npm install ocrqueen
# or
pnpm add ocrqueen
# or
yarn add ocrqueen

Quickstart

typescript
import { OCRQueen } from "ocrqueen";

const client = new OCRQueen({ apiKey: "pk_test_xxx" });
const result = await client.extract("invoice.pdf");

console.log(result.markdown);
for (const block of result.blocks) {
  console.log(block.type, block.text);
}

That's the whole loop. extract() uploads, asks the server to hold the connection up to 25 seconds (sync mode), and falls back to polling automatically for longer documents.

Environment variables

bash
export OCRQUEEN_API_KEY=pk_live_xxx
# optional — for staging / self-hosted
export OCRQUEEN_BASE_URL=https://api.ocrqueen.com

With those set you can drop the apiKey argument: new OCRQueen() reads from the environment.

Idempotent retries

typescript
const result = await client.extract("invoice.pdf", {
  idempotencyKey: "invoice-3034-2026-05-14",
});

See the idempotency reference for the contract.

Inputs

client.extract() accepts a filesystem path or an in-memory buffer / blob with an explicit filename:

typescript
// 1. Filesystem path (Node only)
await client.extract("./invoice.pdf");

// 2. Buffer + filename (works in serverless / edge)
await client.extract({
  filename: "invoice.pdf",
  data: buffer,                  // Uint8Array | ArrayBuffer | Blob
  mimeType: "application/pdf",   // optional — inferred from extension
});

Fire-and-forget with webhooks

typescript
const job = await client.submit("invoice.pdf", {
  callbackUrl: "https://your-server.com/hooks/ocrqueen",
});
console.log(job.job_id);

See the batch + webhooks cookbook for a complete receiver with HMAC verification.

Error handling

typescript
import {
  RateLimitError,
  InvalidRequestError,
  ExtractionFailedError,
} from "ocrqueen";

try {
  const result = await client.extract("doc.pdf");
} catch (err) {
  if (err instanceof RateLimitError) {
    await sleep((err.retryAfter ?? 5) * 1000);
    // retry
  } else if (err instanceof ExtractionFailedError) {
    console.error("can't extract:", err.code);
  } else if (err instanceof InvalidRequestError) {
    throw err; // bad input — don't retry
  }
}

Full reference

Every method, option, and exception type is documented in the package README:

github.com/ocrqueen/ocrqueen-node →