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. Maximum per_page is 250.

Date Ranges

  • date_from and date_to apply to the column set by filter_on.
  • Date-only inputs are normalized to full day boundaries.
  • Use due_date_from and due_date_to for 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_key or invalid_api_key with HTTP 401.
  • db_not_initialized or 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_since to implement incremental syncs.
  • Keep per_page reasonable 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.