Guide

Migrate a document extraction integration to Velrim

All guides

Start a migration at the boundary your application already owns: its input document reference and output object. Place the new extraction call behind that boundary, then compare behavior before changing consumers. This guide uses a TypeScript invoice integration returning a plain object. It does not assume another provider’s SDK or HTTP response is compatible with Velrim.

If your existing pipeline meets your requirements on homogeneous, low-stakes documents, keeping it can be the right choice. A migration is useful when you have a concrete requirement to evaluate: field evidence, runtime validation, review behavior or operating cost. Write that requirement down before the comparison.

Inventory the contract before replacing the call

Capture fixtures for a normal invoice, a missing required amount, an explicit null, an unfamiliar currency, repeated line items and an invalid PDF. Record what the current integration returns or throws. Include timeouts and duplicate requests. These fixtures define the behavior your consumers depend on, including behavior you may decide to change deliberately.

Inventory the contract before replacing the call
BoundaryVelrim mappingMigration check
DocumentSDK { bytes } or { uploadKey }; REST bytes_base64 or upload_key.Do not pass a local path or provider file ID to the REST endpoint.
SchemaZod, Pydantic or supported JSON Schema.Check optional fields, enums, unions and application transformations.
ObjectTypeScript result.data; Python result.parsed on the model path.Validate with your actual application contract.
Evidencefields keyed by JSON Pointer, separate from data.Retain state, reason, confidence, conflict and anchors.
Async completionPOST /v1/jobs and terminal job result or error.Update polling and webhook verification; do not reuse provider status enums.
RetriesSDK retries transient failures with one logical request key.Use a stable caller key when retries span worker executions.

Keep an explicit adapter

Install @velrim/sdk and zod, then save the module below as migrate.ts. Import extractForExistingApp from your existing job handler and pass a VelrimClient plus document bytes. Replace the illustrative Invoice schema with your real one. The typed extraction guide provides a command-line caller you can use for a local trial. Download migrate.ts.

The returned invoice property is the application-facing object. The evidence stays alongside it for review, rather than being discarded during migration. Update the caller to read invoice; this module is an explicit contract change, not a drop-in replacement for an unnamed provider.

migrate.ts
import { z } from 'zod';
import { VelrimClient, type DocumentInput } from '@velrim/sdk';
// Replace this illustrative legacy contract with your application's exact model.
const Invoice = z.object({
invoice_number: z.string(),
total: z.number(),
currency: z.enum(['USD', 'EUR']),
po_number: z.string().nullable().optional(),
});
export async function extractForExistingApp(client: VelrimClient, document: DocumentInput) {
const result = await client.extract(Invoice, document);
return {
// Existing consumers can read invoice; review code retains the evidence.
invoice: result.data,
evidence: { fields: result.fields, meta: result.meta },
};
}

Map states and failures deliberately

A request can succeed while a field is missing. Do not convert that state into a zero total to satisfy the old interface. A strict Zod model can cause SchemaMismatchError after the API response arrives. Decide whether your task retries, requests corrected input or opens a review item. Blindly retrying the same ambiguous document is not a review policy.

Rebuild confidence thresholds from your labeled documents. A score of 0.9 from two different systems is not automatically the same operating point. Likewise, an attached bounding box and a value confirmed inside that box are different facts. Preserve Velrim’s grounding enum and the published evidence limits.

Handle 401 and 402 as credential or balance issues; inspect 400 and 422 against your input and schema. Follow the error and retry rules for transient errors. A 409 idempotency conflict needs investigation; the SDK does not retry it. The 24-hour success replay window does not make downstream database writes idempotent.

Compare in shadow mode, then cut over a bounded workload

Run both integrations on an authorized, labeled sample without allowing the new output to trigger production actions. Compare field correctness, omissions, fabricated values on absent fields, validation failures, latency, billed pages and review load. Provider agreement is not ground truth: adjudicate disagreements against the original document.

Use the same schemas and document mix where the providers support them, and record any unequal configuration. Repeated runs can differ; keep versions and run metadata with the results. Extra provider calls can incur charges, so scope the trial before running it. The comparison pages help identify configuration differences but cannot decide performance on your workload.

Choose cutover criteria in advance. Route a bounded set of jobs through the new adapter, keep your old path available, and track failures and review decisions. Use an application job ID to deduplicate downstream effects. Roll back the routing decision if the criteria fail; retain comparison evidence so the next attempt starts from what you learned.

Make review part of the migration

Before expanding traffic, verify that a reviewer can open the source document from a failed field, that missing metadata reaches review, and that rejected output cannot silently enter the old consumer. The n8n guide illustrates those branches; the threshold guide explains how to evaluate score cutoffs without assuming they transfer.

Written by Velrim.