
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Official JavaScript/TypeScript SDK for LeapOCR - Transform documents into structured data using AI-powered OCR.
LeapOCR provides enterprise-grade document processing with AI-powered data extraction. This SDK offers a JavaScript/TypeScript-native interface for seamless integration into your Node.js and browser applications.
npm install leapocr
# or
yarn add leapocr
# or
pnpm add leapocr
import { LeapOCR } from "leapocr";
// Initialize the SDK with your API key
const client = new LeapOCR({
apiKey: process.env.LEAPOCR_API_KEY,
});
// Submit a document for processing
const job = await client.ocr.processURL("https://example.com/document.pdf", {
format: "structured",
model: "standard-v2",
});
// Wait for processing to complete
const result = await client.ocr.waitUntilDone(job.jobId);
console.log("Extracted data:", result.data);
X-R2-Signature headers with the raw request body| Model | Use Case | Credits/Page | Priority |
|---|---|---|---|
standard-v2 | General purpose (default) | 1 | 2 |
pro-v2 | Highest quality, all languages | 3 | 6 |
Specify a model in the processing options. Defaults to standard-v2.
const client = new LeapOCR({
apiKey: process.env.LEAPOCR_API_KEY,
});
const job = await client.ocr.processURL("https://example.com/invoice.pdf", {
format: "structured",
model: "standard-v2",
instructions: "Extract invoice number, date, and total amount",
});
const result = await client.ocr.waitUntilDone(job.jobId);
console.log(`Processing completed in ${result.processing_time_seconds}s`);
console.log(`Credits used: ${result.credits_used}`);
console.log("Data:", result.data);
import { readFileSync } from "fs";
const client = new LeapOCR({
apiKey: process.env.LEAPOCR_API_KEY,
});
const job = await client.ocr.processFile("./invoice.pdf", {
format: "structured",
model: "pro-v2",
schema: {
invoice_number: "string",
total_amount: "number",
invoice_date: "string",
vendor_name: "string",
},
});
const result = await client.ocr.waitUntilDone(job.jobId);
console.log("Extracted data:", result.data);
const schema = {
type: "object",
properties: {
patient_name: { type: "string" },
date_of_birth: { type: "string" },
medications: {
type: "array",
items: {
type: "object",
properties: {
name: { type: "string" },
dosage: { type: "string" },
},
},
},
},
};
const job = await client.ocr.processFile("./medical-record.pdf", {
format: "structured",
schema,
});
| Format | Description | Use Case |
|---|---|---|
structured | Single JSON object | Extract specific fields across entire document |
markdown | Text per page | Convert document to readable text |
// Poll for status updates
const pollInterval = 2000; // 2 seconds
const maxAttempts = 150; // 5 minutes max
let attempts = 0;
while (attempts < maxAttempts) {
const status = await client.ocr.getJobStatus(job.jobId);
console.log(
`Status: ${status.status} (${status.progress?.toFixed(1)}% complete)`,
);
if (status.status === "completed") {
const result = await client.ocr.getJobResult(job.jobId);
console.log("Processing complete!");
break;
}
await new Promise((resolve) => setTimeout(resolve, pollInterval));
attempts++;
}
// Process a document using a predefined template
const job = await client.ocr.processFile("./invoice.pdf", {
templateSlug: "my-invoice-template",
});
await client.ocr.waitUntilDone(job.jobId);
const result = await client.ocr.getJobResult(job.jobId);
console.log("Extracted data:", result.pages);
// Delete a completed job to free up resources
await client.ocr.deleteJob(job.jobId);
console.log("Job deleted successfully");
For more examples, see the examples/ directory.
import { LeapOCR } from "leapocr";
const client = new LeapOCR({
apiKey: "your-api-key",
baseURL: "https://api.leapocr.com", // optional
timeout: 30000, // 30 seconds (optional)
});
export LEAPOCR_API_KEY="your-api-key"
export LEAPOCR_BASE_URL="https://api.leapocr.com" # optional
The SDK provides typed errors for robust error handling:
import {
AuthenticationError,
ValidationError,
JobFailedError,
TimeoutError,
NetworkError,
} from "leapocr";
try {
const result = await client.ocr.waitUntilDone(job.jobId);
} catch (error) {
if (error instanceof AuthenticationError) {
console.error("Authentication failed - check your API key");
} else if (error instanceof ValidationError) {
console.error("Validation error:", error.message);
} else if (error instanceof NetworkError) {
// Retry the operation
console.error("Network error, retrying...");
} else if (error instanceof JobFailedError) {
console.error("Processing failed:", error.message);
} else if (error instanceof TimeoutError) {
console.error("Operation timed out");
}
}
AuthenticationError - Invalid API key or authentication failuresAuthorizationError - Permission denied for requested resourceRateLimitError - API rate limit exceededValidationError - Input validation errorsFileError - File-related errors (size, format, etc.)JobError - Job processing errorsJobFailedError - Job completed with failure statusTimeoutError - Operation timeoutsNetworkError - Network/connectivity issues (retryable)APIError - General API errorsUse verifyWebhookSignature() with the raw request body exactly as received. LeapOCR sends customer webhooks with X-Webhook-Signature and X-Webhook-Timestamp, and signs timestamp + "." + rawBody with your webhook secret.
import { verifyWebhookSignature } from "leapocr";
export async function POST(request: Request): Promise<Response> {
const rawBody = await request.text();
const signature = request.headers.get("x-webhook-signature") ?? "";
const timestamp = request.headers.get("x-webhook-timestamp") ?? "";
const isValid = await verifyWebhookSignature(
rawBody,
signature,
timestamp,
process.env.LEAPOCR_WEBHOOK_SECRET!,
);
if (!isValid) {
return new Response("Invalid signature", { status: 401 });
}
const payload = JSON.parse(rawBody);
return Response.json({ ok: true, objectKey: payload.object_key });
}
Do not verify against JSON.stringify(parsedBody). Use the original request text or bytes and the timestamp header.
Full API documentation is available in the TypeScript definitions.
// Initialize SDK
new LeapOCR(config: ClientConfig)
// Process documents
client.ocr.processURL(url: string, options?: UploadOptions): Promise<UploadResult>
client.ocr.processFile(filePath: string, options?: UploadOptions): Promise<UploadResult>
client.ocr.processFileBuffer(buffer: Buffer, filename: string, options?: UploadOptions): Promise<UploadResult>
// Job management
client.ocr.getJobStatus(jobId: string): Promise<JobStatus>
client.ocr.getJobResult(jobId: string): Promise<OCRJobResult>
client.ocr.waitUntilDone(jobId: string, options?: PollOptions): Promise<JobStatus>
client.ocr.deleteJob(jobId: string): Promise<void>
interface UploadOptions {
format?: "structured" | "markdown";
model?: OCRModel;
schema?: Record<string, any>;
instructions?: string;
templateSlug?: string;
}
# Install dependencies
pnpm install
# Build the SDK
pnpm build
pnpm build # Build the SDK
pnpm test # Run unit tests
pnpm typecheck # Type check
pnpm format # Format code
pnpm dev # Development mode with watch
pnpm generate # Generate types from OpenAPI spec
We welcome contributions! Please follow these guidelines:
git checkout -b feature/amazing-feature)git commit -m 'feat: add amazing feature')git push origin feature/amazing-feature)See CONTRIBUTING.md for detailed guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
Version: 0.0.5
FAQs
Official JavaScript/TypeScript SDK for LeapOCR API
We found that leapocr demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.