Documentation
Invoices API User Guide
Overview
This guide explains how wholesale admins can fetch invoice data programmatically. Results are returned as JSON with UTF-8 encoding. All requests must include a valid API key and are scoped to your tenant.
Authentication
Use one of the following in every request:
- Header: X-API-Key: your_api_key (recommended)
- Query string: api_key=your_api_key
If the key is missing or invalid, the response is a JSON error with HTTP 401.
Endpoint
Resource: /api/invoices/
Method: GET
Quick Start Examples
GET /api/invoices/?sort=-created_at&per_page=50
GET /api/invoices/?date_from=2024-01-01&date_to=2024-12-31&status=paid,posted&sort=-created_at
GET /api/invoices/?q=Acme
GET /api/invoices/?include=items,payments
Query Parameters
All parameters are optional unless stated otherwise.
| Name | Type | Example | Description |
|---|---|---|---|
| include | list | items,payments,refunds |
Expands nested data arrays on each invoice. |
| status | list | paid,posted |
Filter by invoice status. Valid values: draft, sent, posted, paid, void. |
| terms | list | net30,prepaid |
Filter by credit terms. |
| customer_id | number | 123 |
Only invoices for this customer. |
| order_id | number | 9876 |
Only invoices linked to this order. |
| invoice_number | string | INV-10045 |
Exact match on invoice number. |
| q | string | Acme |
Searches invoice_number, customer name, and customer code. |
| is_tax_exempt | bool | true |
true or false. Filters invoices with the tax exempt flag. |
| paid | bool | true |
true returns invoices with a paid_at timestamp. false returns invoices without it. |
| min_total | number | 100.00 |
Minimum grand_total. |
| max_total | number | 5000.00 |
Maximum grand_total. |
| balance_min | number | 0.01 |
Minimum outstanding balance. Computed as grand_total - payments_total + refunds_total. |
| balance_max | number | 1000.00 |
Maximum outstanding balance. |
| filter_on | string | created_at |
Which timestamp the generic date range applies to. One of: created_at, updated_at, sent_at, paid_at, voided_at, due_date. |
| date_from | date or datetime | 2025-01-01 |
Start of range. If date only (YYYY-MM-DD), time is normalized to 00:00:00. |
| date_to | date or datetime | 2025-12-31 |
End of range. If date only, time is normalized to 23:59:59. |
| due_date_from | date | 2025-01-01 |
Start of due date range. |
| due_date_to | date | 2025-03-31 |
End of due date range. |
| updated_since | datetime | 2025-07-01 00:00:00 |
Return invoices updated at or after this timestamp. |
| sort | string | -created_at,invoice_number |
Comma separated list. Prefix with - for descending. Allowed keys: created_at, updated_at, due_date, grand_total, invoice_number, status, customer_name, paid_at, sent_at. |
| page | number | 1 |
1-based page index. Default 1. |
| per_page | number | 100 |
Results per page. Default 50. Min 1. Max 250. |
Response Structure
On success, HTTP 200 with a JSON object:
{
"meta": {
"tenant_id": 123,
"filters": { ... },
"pagination": {
"page": 1,
"per_page": 50,
"total": 325,
"total_pages": 7
},
"sort": "-created_at",
"timings_ms": { "total": 12 }
},
"data": [
{
"id": 42,
"invoice_number": "INV-10045",
"order_id": 9876,
"customer": {
"id": 55,
"name": "Acme Distributors",
"code": "ACME",
"email": "ap@acme.example"
},
"terms": "net30",
"is_tax_exempt": false,
"due_date": "2025-03-31",
"totals": {
"subtotal": 100.00,
"discount_total": 0.00,
"tax_total": 8.25,
"shipping_total": 0.00,
"grand_total": 108.25,
"payments_total": 50.00,
"refunds_total": 0.00,
"balance": 58.25
},
"tax": {
"rate_percent": 8.250,
"jurisdiction": "AZ"
},
"status": "posted",
"sent_at": "2025-03-01 09:15:00",
"paid_at": null,
"voided_at": null,
"note_owner": null,
"created_at": "2025-02-28 16:40:00",
"updated_at": "2025-03-01 09:15:00",
"items": [ ... ],
"payments": [ ... ],
"refunds": [ ... ]
}
]
}
Notes: balance is computed as grand_total - payments_total + refunds_total. When not requested in include, items, payments, and refunds are omitted.
Expansions
- items: Line items with qty, unit_price, discounts, tax, and line_total.
- payments: Payment records with amount, method, reference, received_at, received_by, note.
- refunds: Refund records with amount, method, reference, refunded_at, refunded_by, note.
Sorting and Pagination
- Sort keys are whitelisted. Unknown keys are ignored.
- Use a minus prefix for descending, for example
-created_at. - Pagination defaults:
page=1,per_page=50. Maximumper_pageis 250.
Date Ranges
date_fromanddate_toapply to the column set byfilter_on.- Date-only inputs are normalized to full day boundaries.
- Use
due_date_fromanddue_date_tofor due date specific ranges.
Error Responses
Errors return JSON and a meaningful HTTP status code.
{
"error": {
"type": "missing_api_key",
"message": "api_key is required (use X-API-Key header or api_key param)."
}
}
Common error types:
missing_api_keyorinvalid_api_keywith HTTP 401.db_not_initializedor server errors with HTTP 500.- Validation or malformed input may return HTTP 400 or 422.
Tips
- Combine filters for efficient exports. Example: paid invoices updated since a date with items included.
- Use
updated_sinceto implement incremental syncs. - Keep
per_pagereasonable to balance performance and payload size.
Changelog Highlights
- API key via header or query parameter.
- Unified balance computation available in results and filters.
- Strict sort whitelist and bounded pagination.
- Optional expansions: items, payments, refunds.