Invoices

Sales documents with their lines, written and read back. An invoice explains the receivables figure the trial balance carries; it never moves it.

Writing invoices

The endpoints

MethodPathWhat it does
POST/api/v1/organisations/{organisation}/invoices Writes the documents and their lines
POST/api/v1/organisations/{organisation}/invoices/validate The same checks; nothing is written

Needs a bearer token, a credential issued for that company, and the credential's invoices.write scope.

The body

{
  "declarations": {
    "source_reference": "netsuite-ar",
    "period": "2026-09",
    "value_basis": "document",
    "rate_direction": "document_to_base",
    "base_currency": "SGD",
    "mode": "replace_period"
  },
  "records": [
    {
      "external_id": "INV-10241",
      "number": "INV-2026-0091",
      "party_name": "Harbour Logistics Pte Ltd",
      "party_city": "Singapore",
      "party_country": "SG",
      "date": "2026-09-14",
      "due_date": "2026-10-14",
      "payment_date": null,
      "currency_code": "USD",
      "exchange_rate": 1.3521,
      "sub_total": 1000.00,
      "total_tax": 90.00,
      "total": 1090.00,
      "amount_due": 1090.00,
      "lines": [
        {
          "line_item_id": "INV-10241-1",
          "account_code": "4000",
          "description": "Freight forwarding, September",
          "quantity": 1,
          "unit_price": 1000.00,
          "amount": 1000.00,
          "tax_amount": 90.00,
          "tax_type": "GST",
          "tax_inclusive": false
        }
      ]
    }
  ]
}

Declarations

DeclarationRequiredValue
source_referenceyesYour own id for the feed, 1–64 characters.
periodyesThe month, YYYY-MM.
value_basisyesdocument when the amounts are in each document's currency, company_base when already converted.
rate_directionyesWhich way exchange_rate converts.
base_currencyyesThe company's reporting currency.
scenarionoActual (default), Budget or Forecast.
modenoreplace_period (default) for the whole month, merge to add and update only.
webhook_urlnoCalled once when the request finishes or fails.

The fields

FieldTypeRequiredWhat it means
external_idstringyesThe identity the source states for this invoice. It is the record's identity.
numberstringnoThe number a reader sees.
party_namestringyesThe customer's name, stored as sent.
party_city, party_countrystringnoWhere the customer is.
datedateyesThe document date.
due_datedatenoThe due date. With the amounts, it decides the stored status.
payment_datedatenoWhen it was settled, if it was.
statusstringnoThe source's own word. The stored status is decided from the amounts and the due date, not from this field.
totalnumberyesThe document total.
sub_total, total_tax, total_discountnumber noNet, tax and discount totals.
amount_due, amount_paidnumbernoThe balance owed and what has been paid.
currency_codestringnoThe document currency; the base currency when absent.
exchange_ratenumbernoRequired when the document currency is not the base currency, in the direction declared. A base-currency document states 1, or nothing.
linesarrayyesAt least one line — see below.

Each line carries line_item_id, account_code, description, quantity, unit_price, amount, tax_amount, tax_type and tax_inclusive. A line without an account code is refused with line_requires_account.

Text is stored exactly as sent: no lookup, no shortening, no substitute value. A line sent without a description keeps an empty description.

What it does

What it answers

{
  "id": 91, "kind": "invoices", "source_reference": "netsuite-ar",
  "period": "2026-09", "status": "written", "records_received": 34,
  "counts": { "created": 30, "updated": 3, "unchanged": 1, "rejected": 0 },
  "recalculation": null,
  "written_at": "2026-10-23T06:31:07+00:00",
  "links": { "self": "…/requests/91", "results": "…/requests/91/results" }
}

Refusals

CodeWhen
account_not_foundA line names a code the company does not hold
line_requires_accountA line carries no account code
lines_are_requiredAn invoice carries no lines
amount_disagrees_with_totalThe total differs from the lines beyond the tolerance
rate_required_for_foreign_currencyAnother currency and no rate
rate_must_be_one_for_base_currencyA base-currency document states a rate other than 1
duplicate_record_identityTwo records state the same external_id

Bills is the same shape against the purchase side.

Reading invoices

The sales documents the company holds, with their lines: what explains the receivables figure the trial balance carries.

The endpoint

MethodPathAnswers
GET/api/v1/organisations/{organisation}/invoices The invoices and their lines

Needs a bearer token, a credential issued for that company, and the invoices.read scope.

The filters

ParameterWhat it does
periodOne month, Mon-YYYY, by the document date.
external_idOne document. Unknown, it answers 404.
account_codeOnly documents with a line on that account.
statusOne stored status, such as OPEN or OVERDUE. A non-posted status - DRAFT, VOIDED - is refused, because no document this read answers can carry it.
page, per_pagePaging, as everywhere.

What it answers

{
  "data": [
    {
      "external_id": "DEMO-IC-INV-177-2026-09-1", "number": "INV-177-2026-09-IC2",
      "party": { "name": "Demo Service Company", "city": "Seattle", "country": "USD" },
      "date": "2026-09-01", "due_date": "2026-10-01", "payment_date": null,
      "status": "OVERDUE", "currency": "SGD", "exchange_rate": 1,
      "sub_total": 19100, "total_tax": 0, "total_discount": 0, "total": 19100,
      "amount_due": 19100, "amount_paid": 0, "provider": "Import",
      "lines": [
        { "line_item_id": "DEMO-IC-INV-177-2026-09-1-1", "account_code": "SA-4110",
          "description": "Support & Maintenance", "quantity": 1, "unit_price": 19100,
          "amount": 19100, "tax_amount": 0, "tax_type": null, "tax_inclusive": false }
      ]
    }
  ],
  "page": 1, "per_page": 50, "total": 5, "has_more": false
}
FieldWhat it says
external_idThe identity the source stated for the document.
numberThe number a reader sees.
party.name, party.city, party.countryThe other party, stored as sent.
date, due_date, payment_dateWhen it was raised, when it falls due, and when it was settled.
statusThe stored status, decided from the amounts and the due date - not the word the source sent.
currency, exchange_rateThe document's own currency and the rate it was stored with.
sub_total, total_tax, total_discount, total The document's totals.
amount_due, amount_paidWhat is still owed and what has been paid.
providerWho wrote it: API, Zoho, Xero, QuickBooks, MYOB or an uploaded import.
linesOne row per line: line_item_id, account_code, description, quantity, unit_price, amount, tax_amount, tax_type, tax_inclusive.

Only posted documents are answered: a draft or a void one is not part of the figures, so it is not part of the read either.