Xero Invoices Management
Overview
Invoices are the core transaction entity in Xero for billing and accounts payable. For MSPs, invoices represent two primary flows: sales invoices (ACCREC) for billing managed services clients, and supplier bills (ACCPAY) for vendor costs like software licenses, hardware purchases, and ISP charges.
Core Concepts
Invoice Types
| Type | Code | Description | MSP Use Case | |------|------|-------------|-------------| | Sales Invoice | ACCREC | Accounts Receivable - you bill a customer | Monthly managed services, project work | | Supplier Bill | ACCPAY | Accounts Payable - a vendor bills you | Software licenses, hardware, ISP bills |
Invoice Status Lifecycle
DRAFT --> SUBMITTED --> AUTHORISED --> PAID
\--> VOIDED
\--> DELETED (draft only)
| Status | Description | Editable | Can Pay | |--------|-------------|----------|---------| | DRAFT | Created but not submitted | Yes | No | | SUBMITTED | Submitted for approval | Limited | No | | AUTHORISED | Approved and sent to client | No | Yes | | PAID | Fully paid | No | N/A | | VOIDED | Cancelled/voided | No | No | | DELETED | Removed (draft only) | N/A | N/A |
Invoice Numbering
Xero auto-generates sequential invoice numbers (e.g., INV-0001, INV-0002) or you can set custom numbers using the InvoiceNumber field. MSPs often use prefixes like MS- for managed services or PJ- for project invoices.
Field Reference
Core Fields
| Field | Type | Required | Description | |-------|------|----------|-------------| | InvoiceID | string (UUID) | System | Auto-generated unique identifier | | InvoiceNumber | string | No | Invoice number (auto-generated if blank) | | Type | string | Yes | ACCREC (sales) or ACCPAY (bill) | | Contact | object | Yes | Contact object with ContactID | | Date | string | No | Invoice date (YYYY-MM-DDT00:00:00) | | DueDate | string | No | Payment due date | | Status | string | No | DRAFT, SUBMITTED, AUTHORISED, PAID, VOIDED | | LineAmountTypes | string | No | Exclusive, Inclusive, or NoTax | | Reference | string | No | Reference text (e.g., PO number) | | Url | string | No | URL link for the invoice | | CurrencyCode | string | No | Currency code (e.g., USD, AUD) | | BrandingThemeID | string | No | Invoice template/theme ID |
Line Item Fields
| Field | Type | Required | Description | |-------|------|----------|-------------| | Description | string | Yes | Line item description | | Quantity | decimal | No | Quantity (default 1) | | UnitAmount | decimal | Yes* | Price per unit | | AccountCode | string | Yes* | GL account code | | TaxType | string | No | Tax type code | | ItemCode | string | No | Inventory item code | | LineAmount | decimal | No | Total line amount (calculated) | | DiscountRate | decimal | No | Discount percentage | | Tracking | array | No | Tracking category assignments |
*Required for AUTHORISED status.
Financial Summary Fields (Read-Only)
| Field | Type | Description | |-------|------|-------------| | SubTotal | decimal | Sum of line items before tax | | TotalTax | decimal | Total tax amount | | Total | decimal | Total including tax | | AmountDue | decimal | Remaining unpaid amount | | AmountPaid | decimal | Amount already paid | | AmountCredited | decimal | Amount from credit notes | | HasAttachments | boolean | Whether attachments exist | | Payments | array | Associated payment records |
API Patterns
List Invoices
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
With Filters:
# Sales invoices only
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Type==%22ACCREC%22" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Outstanding invoices
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Type==%22ACCREC%22&&AmountDue>0" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Invoices for a specific contact
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Contact.ContactID==guid(%22${CONTACT_ID}%22)" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Invoices by date range
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Date>=DateTime(2026,3,1)&&Date<=DateTime(2026,3,31)" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
# Overdue invoices
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices?where=Type==%22ACCREC%22&&Status==%22AUTHORISED%22&&DueDate<DateTime(2026,2,23)" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
Get Single Invoice
curl -s -X GET "https://api.xero.com/api.xro/2.0/Invoices/${INVOICE_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Accept: application/json"
Create Sales Invoice (ACCREC)
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"Type": "ACCREC",
"Contact": {
"ContactID": "'${CONTACT_ID}'"
},
"Date": "2026-03-01T00:00:00",
"DueDate": "2026-03-31T00:00:00",
"LineAmountTypes": "Exclusive",
"Reference": "March 2026 Managed Services",
"LineItems": [
{
"Description": "Monthly Managed Services - Acme Corp (25 endpoints)",
"Quantity": 1,
"UnitAmount": 2500.00,
"AccountCode": "200",
"TaxType": "OUTPUT"
},
{
"Description": "Microsoft 365 Business Premium Licenses (25 users)",
"Quantity": 25,
"UnitAmount": 22.00,
"AccountCode": "200",
"TaxType": "OUTPUT"
},
{
"Description": "Backup & Disaster Recovery - 500GB",
"Quantity": 1,
"UnitAmount": 350.00,
"AccountCode": "200",
"TaxType": "OUTPUT"
}
],
"Status": "DRAFT"
}'
Create Supplier Bill (ACCPAY)
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"Type": "ACCPAY",
"Contact": {
"ContactID": "'${VENDOR_CONTACT_ID}'"
},
"Date": "2026-03-01T00:00:00",
"DueDate": "2026-03-31T00:00:00",
"InvoiceNumber": "VENDOR-INV-2026-03",
"Reference": "Monthly software licenses",
"LineAmountTypes": "Exclusive",
"LineItems": [
{
"Description": "RMM Platform - 150 endpoints",
"Quantity": 150,
"UnitAmount": 3.50,
"AccountCode": "400",
"TaxType": "INPUT"
}
],
"Status": "DRAFT"
}'
Update Invoice
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices/${INVOICE_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"InvoiceID": "'${INVOICE_ID}'",
"Reference": "Updated reference",
"Status": "AUTHORISED"
}'
Void Invoice
curl -s -X POST "https://api.xero.com/api.xro/2.0/Invoices/${INVOICE_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "xero-tenant-id: ${XERO_TENANT_ID}" \
-H "Content-Type: application/json" \
-d '{
"InvoiceID": "'${INVOICE_ID}'",
"Status": "VOIDED"
}'
Batch Create Invoices
curl -s -X POST "https://api.xero.com/api.xro/