@recursai/veris-ocr
v0.1.0
Published
Official Node.js client for the Veris OCR API — passport MRZ, document, and resume extraction.
Maintainers
Readme
@recursai/veris-ocr
Official Node.js / TypeScript client for the Veris OCR API by RecursAI Technologies — passport MRZ, general document, and resume extraction.
It is a thin, fully-typed wrapper over the HTTP API: the heavy OCR (PaddleOCR PP-OCRv5 + PP-StructureV3, vision-LLM field extraction) runs in the Veris OCR service; this package makes calling it from a Node app a one-liner.
- ✅ Zero runtime dependencies (uses the Node 18+ global
fetch/FormData) - ✅ ESM and CommonJS, with bundled TypeScript types
- ✅ Accepts file paths,
Buffer,Uint8Array,ArrayBuffer,Blob, or streams - ✅ Typed responses for every endpoint
- ✅ Typed errors, timeouts, and automatic retries (429 / 502 / 503)
Requirements
- Node.js 18 or newer.
- A running Veris OCR service and an API key (
pk_live_.../pk_test_...). See the service README to run it locally via Docker or point at a deployment.
Install
npm install @recursai/veris-ocrQuickstart
import { VerisOCR } from "@recursai/veris-ocr";
const client = new VerisOCR({
baseUrl: "http://localhost:8000", // or https://veris.recursai.in
apiKey: "pk_live_...",
});
// Passport MRZ — pass a path, a Buffer, a stream, etc.
const passport = await client.passport.extract("./passport.jpg");
console.log(passport.mrz.passport_number, passport.mrz.expiry_date);
// General document (image or PDF), optional OCR language(s)
const doc = await client.document.extract(fs.readFileSync("./invoice.pdf"), {
lang: "eng+fra",
});
console.log(doc.page_count, doc.pages[0]?.text);
// Resume / CV → structured fields
const resume = await client.resume.extract("./cv.pdf");
console.log(resume.name, resume.total_experience_human, resume.skills);CommonJS works too:
const { VerisOCR } = require("@recursai/veris-ocr");
const client = new VerisOCR({ baseUrl: "http://localhost:8000", apiKey: "pk_live_..." });Configuration
new VerisOCR({
baseUrl, // required — or set VERIS_OCR_BASE_URL
apiKey, // or set VERIS_OCR_API_KEY
adminToken, // only for admin.* calls — or set VERIS_OCR_ADMIN_TOKEN
timeoutMs, // default 120000 (OCR can be slow)
maxRetries, // default 2 (429/502/503 + idempotent connection errors)
headers, // extra headers on every request
fetch, // custom fetch implementation
});Any option can come from the environment instead:
export VERIS_OCR_BASE_URL=http://localhost:8000
export VERIS_OCR_API_KEY=pk_live_...const client = new VerisOCR(); // picks up the env varsFile inputs
Every extract method accepts any of:
| Input | Example |
| --- | --- |
| Path string | client.passport.extract("./passport.jpg") |
| Buffer / Uint8Array | client.passport.extract(buf) |
| ArrayBuffer | client.passport.extract(arrayBuffer) |
| Blob | client.passport.extract(blob) |
| Stream / async-iterable | client.passport.extract(fs.createReadStream("p.jpg")) |
| Explicit descriptor | client.passport.extract({ data: buf, filename: "p.jpg", contentType: "image/jpeg" }) |
The content type is sniffed from the bytes (JPEG/PNG/WEBP/PDF) when not given.
API
Extraction
client.passport.extract(file, opts?)→PassportResponseclient.document.extract(file, { lang?, ...opts })→DocumentResponseclient.resume.extract(file, opts?)→ResumeResponse
History
client.history.list({ mode?, limit?, offset? }, opts?)→HistoryListclient.history.get(id, opts?)→HistoryDetailclient.history.delete(id, opts?)→{ deleted }client.history.clear(opts?)→{ deleted }
Admin (requires adminToken)
client.admin.createKey(input, opts?)→AdminCreatedKey(plaintext key returned once)client.admin.listKeys(includeRevoked?, opts?)→AdminKeyListclient.admin.revokeKey(keyId, opts?)→AdminRevokeResponse
Health
client.health.check(opts?)→HealthResponse(no auth)
Every method takes an optional final opts object: { signal?, timeoutMs?, maxRetries? }.
Errors
All failures throw a subclass of VerisOCRError:
| Class | When |
| --- | --- |
| VerisOCRBadRequestError | 400 / 413 — bad, unsupported, or oversized input |
| VerisOCRAuthenticationError | 401 / 403 — missing / invalid / revoked key or admin token |
| VerisOCRNotFoundError | 404 |
| VerisOCRValidationError | 422 — detail holds the field errors |
| VerisOCRRateLimitError | 429 — check .retryAfter |
| VerisOCRServerError | 5xx |
| VerisOCRTimeoutError | request exceeded timeoutMs |
| VerisOCRConnectionError | network / DNS / connection failure |
import { VerisOCRRateLimitError, VerisOCRBadRequestError } from "@recursai/veris-ocr";
try {
await client.passport.extract("./passport.jpg");
} catch (err) {
if (err instanceof VerisOCRRateLimitError) {
console.warn(`Rate limited; retry after ${err.retryAfter}s`);
} else if (err instanceof VerisOCRBadRequestError) {
console.error(err.code, err.message, err.requestId);
} else {
throw err;
}
}Each error carries status, code, requestId, and detail when the server
provided them.
Cancellation
Pass an AbortSignal:
const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);
await client.document.extract("./big.pdf", { signal: controller.signal });Development
npm install
npm run typecheck # tsc --noEmit
npm test # vitest (no network — fetch is mocked)
npm run build # tsup → dist/ (ESM + CJS + .d.ts)License
Proprietary — © RecursAI Technologies.
