# Invoice OCR to Xero: The Real API Field Mapping (2026)

> The real Xero Invoices API field mapping for invoice OCR: ACCPAY vs ACCREC, the DRAFT to AUTHORISED status workflow, and where automation actually breaks.

**Canonical URL:** https://docsapi.co/resources/blogs/invoice-ocr-xero
**Author:** Nupura Ughade — Content Marketing Lead, DocsAPI
**Author LinkedIn:** https://www.linkedin.com/in/nupura-ughade/
**Published:** 2026-08-08T00:00:00.000Z
**Updated:** August 8, 2026
**Primary topic:** invoice ocr xero
**Site:** https://docsapi.co (DocsAPI — Document AI & OCR API for SMB Lending)

---

A bookkeeper managing eleven client organizations on Xero told me she had "automated" invoice entry for all of them, then spent an hour every Friday manually fixing bills that synced as AUTHORISED before anyone had actually approved them. The OCR tool she used had defaulted every posted bill straight to the AUTHORISED status because that was the simplest integration path to build, not because that was the right workflow for a firm managing client money on someone else's behalf. Nobody had told her the status field was even a choice, and by the time she noticed the pattern, three months of client bills had gone through with zero human review before hitting each client's actual books.

This is the real Xero Invoices API field mapping for [invoice automation](/solutions/finance-automation), the ACCPAY versus ACCREC distinction, the status workflow that decides whether a bill is a safe draft or a posted liability, and where the sync actually breaks for bookkeepers and accounting firms running multiple client organizations.

## ACCPAY vs. ACCREC: Xero's invoice type field decides everything

Xero uses a single Invoices endpoint for both money owed and money owing, distinguished by the Type field. ACCPAY is a bill, an invoice you owe a supplier, the type relevant to invoice OCR and accounts payable. ACCREC is a sales invoice you have issued to a customer. Getting this field wrong does not throw an obvious error in every case, it can post a supplier bill as a customer invoice, which corrupts both your payables and receivables reporting simultaneously. Any OCR pipeline extracting vendor invoices must hard-code Type to ACCPAY and never infer it from document content alone, since a badly formatted invoice gives no clean signal for which direction the money flows.

## The real Invoices API field mapping

This is what an OCR-extracted bill needs to become to post correctly through Xero's Accounting API, based on the Invoices endpoint's actual field structure.

| OCR-extracted field | Maps to Xero Invoices field | Notes |
| --- | --- | --- |
| Invoice direction | Type = "ACCPAY" | Must be hard-coded for supplier bills, never inferred, since the consequence of getting it wrong corrupts both AP and AR |
| Vendor/supplier name | Contact.ContactID (preferred) or Contact.Name | Matching by ContactID avoids creating duplicate contact records; matching by raw name string does not |
| Invoice date | Date | The transaction date on the document |
| Due date | DueDate | Independent field, not auto-derived unless payment terms are configured on the contact |
| Invoice/reference number | InvoiceNumber, Reference | Xero does not block duplicate invoice numbers across different contacts by default; your duplicate check needs ContactID plus InvoiceNumber together |
| Line item description, qty, price | LineItems[].Description, Quantity, UnitAmount | Table structure across page breaks is where extraction most commonly drops or duplicates a row |
| GL account per line | LineItems[].AccountCode | Required per line. OCR has no inherent knowledge of your chart of accounts; this needs a separate coding layer. |
| Tax treatment | LineItems[].TaxType | Overrides the account's default tax code when set explicitly, and jurisdiction-specific tax types (GST, VAT, sales tax) vary by Xero organization region |
| Posting state | Status ("DRAFT", "SUBMITTED", "AUTHORISED") | This is the field the bookkeeper above did not realize she could control. Only AUTHORISED posts to the ledger as a real liability. |

## Why the Status field matters more in Xero than in most ERPs

Most invoice OCR guidance treats "posting the bill" as a single step. Xero splits it explicitly: a bill can exist as DRAFT (visible, editable, not affecting any ledger balance), SUBMITTED (pending approval in a workflow, still not posted), or AUTHORISED (a real liability on the books). An integration that always sets Status to AUTHORISED is choosing zero-review automation whether or not that is what the business actually wants. An integration that always sets Status to DRAFT is choosing full manual review of every single bill regardless of confidence level. Neither is correct for every use case, and most vendor integrations pick one default and do not expose the choice.

The right pattern for most AP teams: set Status based on extraction confidence. High-confidence extractions (clean invoice, high-confidence field match, known vendor) can go to AUTHORISED directly if your risk tolerance allows it. Low-confidence extractions should land as DRAFT with the uncertain fields flagged, so a human reviews before the liability hits the books rather than after. This is a genuinely different design decision from QuickBooks or NetSuite, where the API either accepts or rejects a post outright rather than offering a middle state; Xero's three-state workflow gives you a review gate the other platforms do not have natively, and most integrations waste it by picking one status and hard-coding it.

## Tracking categories: the field most OCR pipelines skip entirely

Beyond AccountCode, Xero supports up to two Tracking Categories per organization (common examples: Region, Department, Project, Cost Centre), and each line item can carry a tracking option value alongside its account code. This is a genuinely useful reporting dimension for businesses that need to slice AP spend by project or location, but it is also the field almost every invoice OCR integration ignores, because OCR extraction has no natural way to infer "this expense belongs to Project Falcon" from an invoice that never mentions the project by name. In practice, tracking category assignment for AP either comes from a vendor-to-project mapping rule (a specific recurring vendor always bills the same cost center) or requires a human decision at review time. Pipelines that silently drop tracking data leave a gap in every downstream project-cost report that nobody notices until someone asks why a project's actual spend does not match its invoiced total.

If tracking categories matter to your reporting, build the mapping logic explicitly rather than assuming OCR will infer it, and flag any line item where no mapping rule matches for human assignment instead of posting it uncategorized. This is a small design decision that compounds significantly at scale, since a steady trickle of silently dropped tracking values can quietly erode confidence in an entire project-cost reporting system over the course of a year, long after anyone remembers why the numbers stopped matching.

## Attachments and the audit trail

Xero supports attaching the source document to an invoice record through a separate Attachments endpoint, distinct from the Invoice creation call itself, the same two-step pattern QuickBooks and NetSuite both use. For a bookkeeping firm, this attachment is often the single most important artifact in the entire pipeline, because when a client questions a bill six months later, or an accountant needs to verify a number during year-end review, the original PDF attached to the transaction record is what actually resolves the question. An integration that posts the invoice data successfully but silently fails the attachment upload leaves clean numbers with no way to verify them against the source, which matters more in a client-services context than almost anywhere else this field mapping gets used.

## Multi-organization sync: the bookkeeper's actual failure mode

Xero's API is organization-scoped, every API call operates against one specific Xero organization identified by a tenant ID, which matters enormously for bookkeepers and accounting firms managing multiple client books. A pipeline built assuming a single organization connection will either require re-authentication chaos across dozens of clients or, if built carelessly, risk posting a bill extracted from Client A's invoice into Client B's organization because the tenant ID was not explicitly re-validated per request. This is not a hypothetical, it is the single most damaging failure mode for firms running invoice OCR across a client portfolio, because unlike a wrong GL code, a bill posted to the wrong client's books is a trust-breaking error that surfaces at the worst possible time, during that client's own reconciliation.

Any OCR integration built for accounting-firm use needs an explicit, tested check that the tenant ID on the API call matches the client the invoice was actually extracted for, on every single request, not just at initial setup. Rate limiting compounds this at scale: Xero enforces API call limits per organization connection, and a firm processing invoices across dozens of client organizations in parallel needs to queue and throttle requests per tenant rather than treating the whole batch as one undifferentiated stream, or legitimate traffic to one client's organization can get throttled by volume spikes on an unrelated client's batch.

## Where extraction accuracy actually shows up in Xero specifically

LineItems is where accuracy matters most, because Xero validates that line amounts reconcile with the invoice total before AUTHORISED status can apply, similar in spirit to QuickBooks and NetSuite's total validation. Our own [accuracy benchmark](/resources/blogs/ocr-accuracy-benchmark-2026) measured layout-aware line-item extraction at 93% versus 81 to 87% for engines with weaker multi-page table handling, and on Xero specifically, a dropped or duplicated line item does not just create a reconciliation nuisance, it blocks the AUTHORISED transition entirely until someone manually corrects the line items. We built [DocsAPI](/products) to handle multi-page table stitching for exactly this reason: a bookkeeping firm managing dozens of client organizations cannot afford a line-item error rate that creates a manual-fix queue at every single client.

## What I would check before scaling Xero invoice automation

First, confirm what Status your current integration defaults to and whether that matches your actual risk tolerance, not just what was easiest to build. Second, if you manage more than one Xero organization, test explicitly that a batch run cannot cross-post between tenants under load, not just in a single-client demo. Third, pull 15 real invoices and check whether vendor matching resolves to ContactID correctly rather than creating near-duplicate contacts, the same failure pattern that shows up across every accounting platform we have covered in this [accounts payable OCR series](/resources/blogs/accounts-payable-ocr).

For a bookkeeping or accounting firm specifically, add a fourth check: confirm that whatever review queue your team uses actually separates by client organization, rather than presenting one undifferentiated list of pending bills across every client. A shared queue with no client-level filtering is how the tenant-mismatch failure mode above compounds into a real incident, someone approves a bill quickly without checking which client's name is attached, because the interface never made that distinction obvious in the first place.

### Frequently asked questions

**What is the difference between ACCPAY and ACCREC in the Xero API?**
 ACCPAY is a bill, an invoice you owe a supplier, relevant to accounts payable and invoice OCR. ACCREC is a sales invoice issued to a customer. The Type field must be set explicitly and should never be inferred from document content, since getting it wrong corrupts both payables and receivables.

**What does the Status field control on a Xero invoice created via API?**
 Status determines whether the bill is DRAFT (visible but not posted to the ledger), SUBMITTED (pending approval), or AUTHORISED (a posted liability). Most OCR integrations hard-code one status by default; a confidence-based approach that routes low-confidence extractions to DRAFT for review is safer for most AP workflows.

**Why did my invoice OCR post a bill to the wrong Xero organization?**
 This typically happens when a multi-client integration does not explicitly re-validate the tenant ID on every API call. Xero's API is organization-scoped, and without a per-request check, a batch process managing multiple client books risks cross-posting invoices between organizations.

**Can Xero invoice OCR assign GL account codes automatically?**
 Not from optical extraction alone. AccountCode is required per line item, and OCR has no inherent knowledge of a specific organization's chart of accounts. This requires a separate rules engine or historical vendor-to-account mapping layered on top of the extracted data.

**Does Xero block duplicate invoices automatically?**
 Not by default across all contacts. Duplicate detection needs to check ContactID combined with InvoiceNumber, since Xero does not prevent the same invoice number from being used across different suppliers.

**Can invoice OCR assign Xero tracking categories automatically?**
 Only through an explicit vendor-to-category mapping rule, not from extraction alone. Tracking categories like project or cost center have no natural signal on most invoices, so line items without a matching rule should route to human assignment rather than post uncategorized.

Sources: field structure verified against the Xero Accounting API Invoices endpoint documentation and independent technical references. Extraction accuracy figures from our own [OCR accuracy benchmark](/resources/blogs/ocr-accuracy-benchmark-2026). Written by [Nupura Ughade](/author/nupura-ughade).

## Frequently Asked Questions

### What is the difference between ACCPAY and ACCREC in the Xero API?

ACCPAY is a bill, an invoice you owe a supplier, relevant to accounts payable and invoice OCR. ACCREC is a sales invoice issued to a customer. The Type field must be set explicitly and never inferred from document content.

### What does the Status field control on a Xero invoice created via API?

Status determines whether the bill is DRAFT (not posted to the ledger), SUBMITTED (pending approval), or AUTHORISED (a posted liability). A confidence-based approach that routes low-confidence extractions to DRAFT for review is safer than defaulting every bill to AUTHORISED.

### Why did my invoice OCR post a bill to the wrong Xero organization?

This typically happens when a multi-client integration does not explicitly re-validate the tenant ID on every API call. Xero's API is organization-scoped, and without a per-request check, a batch process risks cross-posting invoices between client organizations.

### Can Xero invoice OCR assign GL account codes automatically?

Not from optical extraction alone. AccountCode is required per line item, and OCR has no inherent knowledge of a specific organization's chart of accounts, requiring a separate rules engine or mapping layer.

### Does Xero block duplicate invoices automatically?

Not by default across all contacts. Duplicate detection needs to check ContactID combined with InvoiceNumber, since Xero does not prevent the same invoice number from being used across different suppliers.

### Can invoice OCR assign Xero tracking categories automatically?

Only through an explicit vendor-to-category mapping rule, not from extraction alone. Tracking categories like project or cost center have no natural signal on most invoices, so unmatched line items should route to human assignment.


---

**Source URL (cite this):** https://docsapi.co/resources/blogs/invoice-ocr-xero
**Author profile:** https://docsapi.co/author/nupura-ughade
**Published by:** DocsAPI (https://docsapi.co)
