Invoice list fields: what an agent gets per row

Every row from the invoice list tool carries the business name an operator recognises, the registered legal entity, the live overdue position judged against the tenant's own calendar day, and a ready-made ageing phrase. Read `client_name` when telling a human who an invoice is for, `client_legal_name` when reconciling against books, `is_overdue` for lateness, and `due_phrase` instead of doing date arithmetic yourself.

The invoice list tool is the receivables surface an assistant works from. This page is the field reference: what arrives on each row, and which field answers which question.

The short version: do not re-derive anything on this payload. Identity, lateness and ageing are all resolved server-side, in the tenant's timezone, in one batched read.

Identity fields

FieldMeaningUse it when
client_nameThe name the operator knows the business by — the trading name by defaultTelling a human who an invoice belongs to
client_legal_nameThe registered legal entityReconciling against books, or quoting what the tax invoice says
client_display_secondaryThe other name, or null when it would only repeat the firstRendering a two-line row
client_idStable identifierAny follow-up call

client_name follows the tenant's directory.entity_display_name_preference setting, so on a tenant configured legal_first the two name fields swap which is which. Read the field, never the preference.

client_display_secondary is null in three distinct situations — no second name exists, the tenant turned the second line off, or both names normalise to the same business. Treat null as "there is nothing more to say about this name", not as missing data.

Overdue and ageing fields

FieldMeaning
statusThe stored enum, exactly as persisted
display_statusThe stored status, except a past-due sent invoice displays overdue
is_overdueTrue whenever display_status is overdue, stored or derived
days_overdueWhole days past due, or null
days_until_dueWhole days until due, or null
draft_age_daysDays since the draft was created, or null
due_phraseThe ready-made sentence: 14 days overdue, due in 3 days, due today, draft · 6 days old, or empty
as_of_dateResponse-level: today in the tenant's timezone, the date every derivation above was judged against

The three counters are mutually exclusive by construction. An unpaid invoice past due has days_overdue and null for the other two; a draft has draft_age_days only; a paid or voided invoice has all three null and an empty due_phrase.

due_phrase is the same string the operator's screen renders. Using it means a human and an assistant describing the same invoice cannot word it differently — which is the point of pre-computing it rather than leaving each surface to phrase its own.

Why is ageing pre-computed at all?

Because "today" is not a global fact.

An assistant computing days overdue from due_date uses its own clock, which is almost never the operator's calendar day. For an Australian tenant that shows yesterday as today for most of the working morning — on a counter the operator acts on. The server resolves the day in the tenant's timezone once per call, publishes it as as_of_date, and derives every counter from it. The related pattern is in whose "today" is it.

Filtering

status: "overdue" is derived-inclusive: it returns stored-overdue invoices and sent invoices already past their due date, so chasing late payers never misses an invoice the once-daily sweep has not reached. Every other status filter keeps exact stored-enum semantics.

search matches the invoice number by exact value or prefix, or the client's legal or trading name by case-insensitive substring. A term that matches nothing returns an empty list — never the newest invoices — so an empty result is a trustworthy "no such invoice" rather than a silent fallback an assistant would read as success.

Test rows are hidden by default; pass the include-test flag to surface them.

What this replaced

Until v71.7.0 the tool returned client_id and no client name at all. An assistant asked "which invoices are late and who are they for?" could answer the first half and not the second without a second round of lookups — leaving it less informed than the operator looking at the same data on screen.

Surface parity is a platform rule rather than a nicety: if a human can read it, an agent reads it at the same depth. A capability that ships to one surface only is treated as incomplete.

Related

Last updated 2026-08-27