Stop Guessing. Build Your AP Automation on Verifiable Coordinate Proof.
This guide provides production-ready code to extract invoice data you can actually trust. We show you how to get not just the answer, but the visual proof of where it came from, building an auditable AP workflow from day one.
Introduction
This guide shows you how to implement production-ready invoice processing with coordinate-backed verification. Unlike traditional OCR APIs that return "best guesses," Ninjadoc provides verifiable proof of where each data point came from, enabling trustworthy AP automation.
Who is this for?
- AP teams building invoice automation
- Developers integrating document processing
- Finance leaders evaluating extraction solutions
What you'll build
- Secure server-side invoice processing
- Coordinate-verified data extraction
- Production-ready polling with error handling
- SDK-powered verification UI
Create Your Invoice Processor
Before processing invoices, you need to create a processor that understands what data to extract. This is done through our visual builder where you ask questions in natural language.
- Go to your dashboard and click "Create Processor"
- Upload a sample invoice PDF
- Ask questions like "What is the invoice number?", "What is the total amount?", "What is the vendor name?"
- Test the processor and get your processor_id
Each question becomes a stable field name in your API responses. One processor can handle hundreds of vendor layouts without templates.
The Problem: 'Black Box' APIs Create AP Bottlenecks
Traditional OCR and generic AI APIs give you a JSON output, but force a crisis of trust. You have no way to verify if `total_amount: "510.00"` is correct or a hallucination that reads the subtotal.
This forces you to build costly and slow manual review processes, defeating the purpose of automation. The core issue isn't just getting data, it's getting data you can prove is correct.
Quick Start: Secure Server-Side Pattern
For production applications, always process invoices server-side to keep API keys secure. Here's the complete pattern: frontend uploads to your server, your server calls Ninjadoc, and returns structured data.
Secure Implementation Pattern
// Frontend: Upload invoice to your server (secure pattern)
const formData = new FormData();
formData.append('invoice', invoiceFile); // The PDF invoice from a vendor
formData.append('processor_id', 'your-invoice-processor-uuid');
const response = await fetch('/api/invoices/process', {
method: 'POST',
body: formData
});
const { jobId } = await response.json();
console.log('Job started:', jobId);
// Poll your server for status (your server proxies to Ninjadoc)
const pollResponse = await fetch(`/api/jobs/${jobId}/status`);
const result = await pollResponse.json();
console.log('Extraction complete:', result);
Production Workflow: Submit → Poll → Verify
This server-side function handles the complete extraction process with robust error handling, exponential backoff polling, and rate limit management. It returns structured data with coordinates for every extracted field.
Production Processing Function
// Server-side: Production-ready invoice processing with robust polling
async function processInvoice(invoiceFile, processorId) {
try {
// 1. Submit the vendor invoice and get a job ID
const formData = new FormData();
formData.append('document', invoiceFile);
formData.append('processor_id', processorId);
const submitResponse = await fetch('https://ninjadoc.ai/api/extract', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.NINJADOC_API_KEY}` },
body: formData
});
if (!submitResponse.ok) throw new Error(`Submit failed: ${submitResponse.status}`);
const job = await submitResponse.json();
// 2. Poll for completion with exponential backoff and timeout
let result;
const maxAttempts = 30; // 5 minutes with backoff
const initialDelay = 1000; // 1 second
let attempt = 0;
let delay = initialDelay;
while (attempt < maxAttempts) {
attempt++;
const statusResponse = await fetch(`https://ninjadoc.ai/api/jobs/${job.id}/status`, {
headers: { 'Authorization': `Bearer ${process.env.NINJADOC_API_KEY}` }
});
if (statusResponse.status === 429) {
// Rate limited: honor Retry-After header or exponential backoff
const retryAfter = statusResponse.headers.get('Retry-After');
delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.min(delay * 2, 30000);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
if (!statusResponse.ok) throw new Error(`Status check failed: ${statusResponse.status}`);
result = await statusResponse.json();
if (!['queued', 'processing'].includes(result.status)) break;
// Exponential backoff with jitter
delay = Math.min(delay * 1.5, 10000) + Math.random() * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
if (result.status !== 'completed') {
throw new Error(`Invoice processing failed: ${result.status}`);
}
// 3. Extract and structure the data for your AP system
const extractedData = result.data.reduce((acc, f) => {
acc[f.field_name] = { value: f.value, coordinates: f.geometry };
return acc;
}, {});
// Validate critical fields
if (!extractedData.invoice_number?.value || !extractedData.total_amount?.value) {
throw new Error('Missing critical data for payment processing');
}
return { success: true, data: extractedData };
} catch (error) {
console.error('Invoice processing failed:', error);
return { success: false, error: error.message };
}
}
Sample API Response with Coordinates
Here's what a completed job response looks like. Each field includes the extracted value, confidence score, and precise coordinates for verification.
API Response Examples
{
"id": "job_abc123",
"status": "completed",
"data": [
{
"field_name": "invoice_number",
"value": "INV-2024-001",
"confidence": 0.98,
"geometry": [
{
"text": "INV-2024-001",
"boundingBox": [100, 150, 200, 170],
"pageNumber": 1
}
],
"page_number": 1
},
{
"field_name": "total_amount",
"value": "1250.00",
"confidence": 0.95,
"geometry": [
{
"text": "$1,250.00",
"boundingBox": [400, 500, 480, 520],
"pageNumber": 1
}
],
"page_number": 1
}
],
"page_metadata": {
"1": {
"dimensions": {
"width": 612,
"height": 792
}
}
}
}
The boundingBox
format is [x1, y1, x2, y2] in points (72 DPI). Use these coordinates to overlay verification highlights on your PDF viewer.
Extracting Line Items with Coordinates
For complex invoices with multiple line items, ask questions like "Extract all line items with description, quantity, unit_price, and line_total". The API returns a structured array with coordinates for each cell.
Line Items Extraction
{
"field_name": "line_items",
"value": [
{
"description": "Office Supplies",
"quantity": "5",
"unit_price": "25.00",
"line_total": "125.00",
"coordinates": {
"description": [100, 200, 200, 220],
"quantity": [300, 200, 320, 220],
"unit_price": [350, 200, 400, 220],
"line_total": [450, 200, 500, 220]
}
}
],
"confidence": 0.92,
"geometry": [...], // Overall table region
"page_number": 1
}
Each line item includes per-cell coordinates, enabling precise verification and audit trails for your AP system.
Evaluation Checklist for AP Automation
- Does the API return confidence scores for every field?
- Are coordinates provided for visual verification?
- Can you set confidence thresholds for automated vs manual review?
- Does it handle layout variations without templates?
- Is the pricing predictable with no per-document minimums?
- Can you integrate it server-side for security?
Pricing Estimation
Simple, transparent pricing: 25 credits per page + 5 credits per field. Credits never expire.
Plans
- Starter — 4,500 credits — $10
- Growth — 10,000 credits — $25
- Pro — 22,000 credits — $50
- Scale — 50,000 credits — $100
Typical Usage
- 1-page invoice (~10 fields) = 75 credits
- 10-page invoice (~10 fields) = 300 credits
- Start with 1,250 free credits
Verification with SDK
Use our SDK to easily overlay extraction results on PDFs for verification. Install with: npm install @ninjadoc-ai/sdk@^1.0.7
Compatibility: SDK v1.0.7+ supports React 16.8+, TypeScript 4.5+, and modern browsers with ES2020 support. For older environments, consider using the direct API approach.
SDK Implementation with BFF Routes
// app/routes/api.ninjadoc.$.tsx
import { createRemixApiRoute } from '@ninjadoc-ai/sdk/frameworks/remix';
const { loader, action } = createRemixApiRoute({
// API key automatically read from NINJADOC_API_KEY env var
});
export { loader, action };
// Add to app/routes.ts:
// route("/api/ninjadoc/*", "routes/api.ninjadoc.$.tsx")
The BFF routes create secure proxy endpoints that the SDK calls from your browser, keeping your API key safe on the server. The SDK handles coordinate scaling, confidence coloring, and click interactions automatically.
The SDK handles coordinate scaling, confidence coloring, and click interactions automatically.
Frequently Asked Questions
Why are coordinates the most important part of an invoice API?
They build trust. Without coordinates, you're just getting a "best guess" from a black box. With coordinates, you get undeniable proof. This allows you to build verification tools that show your AP team *exactly* where the data came from, which is critical for financial applications and dramatically speeds up manual reviews.
We get invoices from hundreds of vendors. Do I really not need a template for each one?
Correct. Our AI understands the context and common patterns of invoices. It finds data based on your questions (e.g., "what is the total?"), not on fixed coordinates. This means one 'Invoice Processor' can handle countless layout variations from all your vendors, saving you from endless maintenance.
How does your API handle complex invoice line items?
Our AI is trained to recognize tabular structures. You can specify to "extract all line items" and specify the columns you need (`description`, `quantity`, `unit_price`, `line_total`). The API will return a structured array of each item, each with its own value and coordinate proof.
What's the pricing model? Is it expensive?
It's simple pay-as-you-go. Plans start at just $10 for 4,500 credits. Credits never expire and there are no monthly subscriptions. 25 Credits per page + 5 Credits per field. Start with 1,250 free welcome credits!
Further reading
- →Document Overlay Guide: Build interactive PDF viewers with coordinate proof
- →Bill of Lading API Guide: Extract logistics data with coordinate proof
- →Ninjadoc vs AWS Textract: developer-first Q&A vs foundation-model extraction
- →Ninjadoc vs Docsumo: developer-first Q&A vs enterprise workflows
- →Complete API Documentation: SDK reference and examples
Ready to Build with Verifiable Data?
Integrate coordinate-backed invoice extraction into your application and bring a new level of trust and speed to your AP workflow.
- 1,250 Free Credits on Sign-up
- No Credit Card Required
- Visual coordinate overlay for auditability
Start with 1,250 free credits and copy-paste production code to get started immediately.