Full income statement per calendar month
const url = 'https://api.flychain.us/external/v1/provider/9c1e7a42-0b3d-4e58-9f21-6a8b5c4d3e2f/business_entity/3f5d8b16-7c94-42a1-b0e6-58d9c2a71b43/financial_reports/income_statement/monthly?start_date=2026-07-01&end_date=2026-07-31';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.flychain.us/external/v1/provider/9c1e7a42-0b3d-4e58-9f21-6a8b5c4d3e2f/business_entity/3f5d8b16-7c94-42a1-b0e6-58d9c2a71b43/financial_reports/income_statement/monthly?start_date=2026-07-01&end_date=2026-07-31' \ --header 'Authorization: Bearer <token>'One full statement per calendar month across the range, plus the whole period, in
the same envelope as monthly/summary.
This is the heaviest endpoint on this API, and the only one whose payload grows
with the range as well as its cost on our side. Measured at roughly 38 KB for two
months, so expect a few hundred KB at twelve and close to a megabyte at
thirty-six, and a wide range can approach our 30-second request timeout. There is
no range limit, deliberately — but point a recurring reconciliation at
monthly/summary instead, which returns ten integers per period rather than every
account of every month, and reach for this variant when you actually need the
detail.
Months at the edge of the range are clipped, not extended: a range starting
mid-month yields a first period that starts on your start_date. See
guides/data-semantics.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The provider, from GET /providers or the provider_id on a business-entity
record. Must be a provider in your partner relationship.
Example
9c1e7a42-0b3d-4e58-9f21-6a8b5c4d3e2fThe business entity, from GET /business_entities. Must belong to the
provider_id in the same path.
Example
3f5d8b16-7c94-42a1-b0e6-58d9c2a71b43Query Parameters
Section titled “Query Parameters”First day of the requested range, inclusive.
Must be a real calendar date, zero-padded, in YYYY-MM-DD form — 2026-7-1 and
2026-02-31 are both 400 INVALID_REQUEST. Ranges are evaluated in UTC.
Raised to the entity’s books_start_date when it falls earlier. If the whole
requested range sits before the books begin, the result is
400 INVALID_REQUEST rather than a zero statement, so a range with no books
behind it can never read as a period with no revenue.
Example
2026-07-01Last day of the requested range, inclusive. Same format rules as start_date, and
must not be earlier than it.
Capped at today when it falls in the future, which is the ordinary case for a job that asks for the current month every day. The response echoes the effective range it used.
Example
2026-07-31Responses
Section titled “Responses”One full statement per period, plus the whole period.
A full statement per period, plus the whole range.
object
The basis an entity’s financials are prepared on.
A property of the entity, not a request parameter. A report is produced on the
basis the underlying books are kept on; there is no per-request switch. It is
returned on every entity record and every report so a figure is never ambiguous,
and it will not change without notice. See guides/data-semantics.
null only where the entity has no books yet — every entity with
reporting_available: true carries a basis.
When this payload was produced, ISO 8601 UTC.
Chronological, one entry per month in the effective range.
A period carrying the full statement.
object
Month and year of this period, e.g. July 2026. Derived from start_date, so
a clipped period still reads as its calendar month — use the dates, not the
label, to know what the period covers.
First day of the period, inclusive.
Last day of the period, inclusive.
Whether a Flychain bookkeeper has finalized the books through end_date.
This is the flag that says a figure is final.
Whether this period’s end_date is in the past. false for the in-progress
current month.
Note this is about the period, not the calendar month: a period clipped by
the requested range reads true once its end date has passed, even though the
calendar month it is labelled with is not fully covered.
The full statement: nine categories in statement order, each holding a record
with that category’s total and the accounts beneath it.
This is the identical structure our own application consumes. It therefore carries
presentation hints (title_tooltip, percentage_comment) and accounting metadata
(type, sub_type, sort_code, debit_credit) alongside the figures. Nothing is
held back and nothing is added for external callers — a pared-down copy would be a
second definition of the statement, and a second definition drifts.
object
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
The category as a percentage of total net sales — or of total revenue
(total net sales plus other income) for net profit. Unrounded, and 0
where the denominator is zero.
Explanatory copy for percentage that our own interface renders. Ignore
it, as with title_tooltip.
A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
The category as a percentage of total net sales — or of total revenue
(total net sales plus other income) for net profit. Unrounded, and 0
where the denominator is zero.
Explanatory copy for percentage that our own interface renders. Ignore
it, as with title_tooltip.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
The category as a percentage of total net sales — or of total revenue
(total net sales plus other income) for net profit. Unrounded, and 0
where the denominator is zero.
Explanatory copy for percentage that our own interface renders. Ignore
it, as with title_tooltip.
The whole range carrying the full statement.
object
First day of the effective range, inclusive.
Last day of the effective range, inclusive.
Whether the books are finalized through end_date.
The full statement: nine categories in statement order, each holding a record
with that category’s total and the accounts beneath it.
This is the identical structure our own application consumes. It therefore carries
presentation hints (title_tooltip, percentage_comment) and accounting metadata
(type, sub_type, sort_code, debit_credit) alongside the figures. Nothing is
held back and nothing is added for external callers — a pared-down copy would be a
second definition of the statement, and a second definition drifts.
object
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
The category as a percentage of total net sales — or of total revenue
(total net sales plus other income) for net profit. Unrounded, and 0
where the denominator is zero.
Explanatory copy for percentage that our own interface renders. Ignore
it, as with title_tooltip.
A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
The category as a percentage of total net sales — or of total revenue
(total net sales plus other income) for net profit. Unrounded, and 0
where the denominator is zero.
Explanatory copy for percentage that our own interface renders. Ignore
it, as with title_tooltip.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
One of the nine statement categories.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.
object
A node in the full statement: a category root, an account group, or a leaf
account. Recursive through children.
Read total_amount_cents for a total, not amount_cents.
total_amount_cents is the rolled-up figure including every descendant;
amount_cents is only what is posted directly at that node, which for a category
root is usually — but not guaranteed to be — zero.
Null fields are omitted rather than sent as null, so treat an absent key as
“not applicable to this node” rather than as a missing value. ledger_id, for
instance, appears on account nodes and not on category roots.
object
Stable identifier for an account, so the same account can be tracked across periods. Present on account nodes, absent on category roots.
Opaque — not a UUID, unlike the provider and business-entity ids. Treat it as a string and do not parse it.
Display name of the category or account.
Ledger type, revenue or expense, as classified in the chart of accounts.
Reported for completeness; the node’s position in the statement is the
authoritative structure. Absent on the derived categories, which are neither.
Finer classification within a type, naming the category the account rolls up into. Present on account nodes.
Amount posted directly at this node, in cents. Often 0 on a root.
This node’s total in cents, including every descendant. This is the figure to read.
The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.
The natural balance of the account. Accounting metadata.
This node’s total as a percentage of operating revenue, unrounded.
Computed for the five categories that hold accounts — operating revenues, cost of goods sold, operating expenses, other expenses, other income — and every node beneath them. Absent on the four derived categories (total net sales, gross profit, total operating profit, net profit).
Explanatory copy our own interface renders next to the category heading. Included because these endpoints return the identical structure our application consumes rather than a divergent copy — ignore it.
The category as a percentage of total net sales — or of total revenue
(total net sales plus other income) for net profit. Unrounded, and 0
where the denominator is zero.
Explanatory copy for percentage that our own interface renders. Ignore
it, as with title_tooltip.
Examples
One month's full statement, plus the whole range
GET .../financial_reports/income_statement/monthly?start_date=2026-07-01&end_date=2026-07-31
The periods / whole_period envelope of monthly/summary with an
income_statement per period in place of totals. Accounts are elided here for
brevity — see the range-full example for a statement with its accounts populated.
This variant returns the complete tree for every period, which is why its
payload grows with the range.
{ "provider_id": "9c1e7a42-0b3d-4e58-9f21-6a8b5c4d3e2f", "business_entity_id": "3f5d8b16-7c94-42a1-b0e6-58d9c2a71b43", "accounting_basis": "CASH", "currency": "USD", "generated_at": "2026-08-20T14:02:11Z", "periods": [ { "label": "July 2026", "start_date": "2026-07-01", "end_date": "2026-07-31", "is_closed": false, "is_complete": true, "income_statement": { "operating_revenues": { "record": { "name": "Operating Revenues", "type": "revenue", "amount_cents": 0, "total_amount_cents": 3642500, "debit_credit": "credit", "percentage_of_operating_revenue": 100, "children": [] }, "title_tooltip": "Income earned from your core healthcare services, like patient visits and treatments." }, "total_net_sales": { "record": { "name": "Total Net Sales", "amount_cents": 0, "total_amount_cents": 3642500, "debit_credit": "credit", "children": [] }, "title_tooltip": "Your total revenue after accounting for refunds, discounts, or write-offs." }, "cost_of_goods_sold": { "record": { "name": "Cost Of Goods Sold", "type": "expense", "amount_cents": 0, "total_amount_cents": 1820000, "debit_credit": "debit", "percentage_of_operating_revenue": 49.96568291008923, "children": [] }, "percentage": 49.96568291008923, "percentage_comment": "This is the cost of goods sold as a percentage of the total net sales", "title_tooltip": "Direct costs tied to delivering care, such as clinical labor and medical supplies." }, "gross_profit": { "record": { "name": "Gross Profit", "amount_cents": 0, "total_amount_cents": 1822500, "debit_credit": "credit", "children": [] }, "percentage": 50.03431708991077, "percentage_comment": "This is the gross profit as a percentage of the total net sales", "title_tooltip": "What’s left after covering care delivery costs—shows how efficiently you run clinical services." }, "operating_expenses": { "record": { "name": "Operating Expenses", "type": "expense", "amount_cents": 0, "total_amount_cents": 910000, "debit_credit": "debit", "percentage_of_operating_revenue": 24.982841455044614, "children": [] }, "title_tooltip": "Overhead costs to keep the business running, like admin salaries, rent, and software." }, "total_operating_profit": { "record": { "name": "Total Operating Profit", "amount_cents": 0, "total_amount_cents": 912500, "debit_credit": "credit", "children": [] }, "title_tooltip": "Profit from day-to-day operations before interest or unusual items." }, "other_expenses": { "record": { "name": "Other Expenses", "type": "expense", "amount_cents": 0, "total_amount_cents": 15000, "debit_credit": "debit", "percentage_of_operating_revenue": 0.41180507892930684, "children": [] }, "title_tooltip": "Non-operating costs like loan interest or legal fees not tied to clinical activity." }, "other_income": { "record": { "name": "Other Income", "type": "revenue", "amount_cents": 0, "total_amount_cents": 0, "debit_credit": "credit", "percentage_of_operating_revenue": 0, "children": [] }, "title_tooltip": "Earnings from non-core activities, like grants, investments, or rental income." }, "net_profit": { "record": { "name": "Net Profit", "amount_cents": 0, "total_amount_cents": 897500, "debit_credit": "credit", "children": [] }, "percentage": 24.639670555936856, "percentage_comment": "This is the net profit as a percentage of the total revenue", "title_tooltip": "Your true bottom line after all costs, showing how much the business actually made." } } } ], "whole_period": { "start_date": "2026-07-01", "end_date": "2026-07-31", "is_closed": false, "income_statement": { "operating_revenues": { "record": { "name": "Operating Revenues", "type": "revenue", "amount_cents": 0, "total_amount_cents": 3642500, "debit_credit": "credit", "percentage_of_operating_revenue": 100, "children": [] }, "title_tooltip": "Income earned from your core healthcare services, like patient visits and treatments." }, "total_net_sales": { "record": { "name": "Total Net Sales", "amount_cents": 0, "total_amount_cents": 3642500, "debit_credit": "credit", "children": [] }, "title_tooltip": "Your total revenue after accounting for refunds, discounts, or write-offs." }, "cost_of_goods_sold": { "record": { "name": "Cost Of Goods Sold", "type": "expense", "amount_cents": 0, "total_amount_cents": 1820000, "debit_credit": "debit", "percentage_of_operating_revenue": 49.96568291008923, "children": [] }, "percentage": 49.96568291008923, "percentage_comment": "This is the cost of goods sold as a percentage of the total net sales", "title_tooltip": "Direct costs tied to delivering care, such as clinical labor and medical supplies." }, "gross_profit": { "record": { "name": "Gross Profit", "amount_cents": 0, "total_amount_cents": 1822500, "debit_credit": "credit", "children": [] }, "percentage": 50.03431708991077, "percentage_comment": "This is the gross profit as a percentage of the total net sales", "title_tooltip": "What’s left after covering care delivery costs—shows how efficiently you run clinical services." }, "operating_expenses": { "record": { "name": "Operating Expenses", "type": "expense", "amount_cents": 0, "total_amount_cents": 910000, "debit_credit": "debit", "percentage_of_operating_revenue": 24.982841455044614, "children": [] }, "title_tooltip": "Overhead costs to keep the business running, like admin salaries, rent, and software." }, "total_operating_profit": { "record": { "name": "Total Operating Profit", "amount_cents": 0, "total_amount_cents": 912500, "debit_credit": "credit", "children": [] }, "title_tooltip": "Profit from day-to-day operations before interest or unusual items." }, "other_expenses": { "record": { "name": "Other Expenses", "type": "expense", "amount_cents": 0, "total_amount_cents": 15000, "debit_credit": "debit", "percentage_of_operating_revenue": 0.41180507892930684, "children": [] }, "title_tooltip": "Non-operating costs like loan interest or legal fees not tied to clinical activity." }, "other_income": { "record": { "name": "Other Income", "type": "revenue", "amount_cents": 0, "total_amount_cents": 0, "debit_credit": "credit", "percentage_of_operating_revenue": 0, "children": [] }, "title_tooltip": "Earnings from non-core activities, like grants, investments, or rental income." }, "net_profit": { "record": { "name": "Net Profit", "amount_cents": 0, "total_amount_cents": 897500, "debit_credit": "credit", "children": [] }, "percentage": 24.639670555936856, "percentage_comment": "This is the net profit as a percentage of the total revenue", "title_tooltip": "Your true bottom line after all costs, showing how much the business actually made." } } }}Malformed request — a missing or unparseable date, a path id that is not a UUID,
start_date after end_date, or a range that does not overlap the period this
entity has books for.
The failure shape for every error raised inside a documented operation — validation, authorization, ours — so a client needs a single error path.
Match on code, not on message: the code set below is the contract and is
stable, while wording may be clarified. New codes may be added within v1 (see
guides/versioning), so treat an unrecognised code as “the HTTP status is
authoritative”.
One exception, and it is the one you are most likely to meet while
integrating. A request that does not reach a documented operation at all — an
unrouted path (404) or a method this API does not serve (405) — is rejected
before this layer, and its body may be a different shape or not JSON at all.
Treat the HTTP status as authoritative there, and check the URL: the operations
below are the whole surface.
object
object
Machine-readable cause.
INVALID_REQUEST(400) — malformed dates, a non-UUID path id, an inverted range, or a range with no reportable books behind it.INVALID_API_KEY(401) — missing, invalid, expired or revoked key.PARTNER_API_NOT_ENABLED(403) — your key is valid, but your organization is not enrolled in the API programme. Contact us; do not rotate the key.PROVIDER_NOT_IN_PARTNER_SCOPE(403) — the provider exists but is not in your relationship, including one that has left it.BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE(403) — the entity exists but does not belong to theprovider_idin the path.PROVIDER_NOT_FOUND(404) — no provider with that id.BUSINESS_ENTITY_NOT_FOUND(404) — no business entity with that id.BOOKS_NOT_AVAILABLE(409) — the entity has no reportable books.INTERNAL_ERROR(500) — ours; retry with backoff.AUTH_SERVICE_UNAVAILABLE(503) — we could not verify your key; retry with backoff, and do not treat it as an authentication failure.
Human-readable detail. Do not match on it.
Examples
Unparseable date
{ "error": { "code": "INVALID_REQUEST", "message": "start_date must be a valid date in YYYY-MM-DD format." }}Path id is not a UUID
{ "error": { "code": "INVALID_REQUEST", "message": "business_entity_id is not a valid UUID." }}Range sits entirely outside the reportable period
{ "error": { "code": "INVALID_REQUEST", "message": "The requested range does not overlap the period this entity has reportable books for. It must fall on or after books_start_date (see GET /business_entities) and must not be entirely in the future." }}Missing, invalid, expired or revoked API key. One message covers every case on purpose — a caller cannot tell a revoked key from an unknown one.
The failure shape for every error raised inside a documented operation — validation, authorization, ours — so a client needs a single error path.
Match on code, not on message: the code set below is the contract and is
stable, while wording may be clarified. New codes may be added within v1 (see
guides/versioning), so treat an unrecognised code as “the HTTP status is
authoritative”.
One exception, and it is the one you are most likely to meet while
integrating. A request that does not reach a documented operation at all — an
unrouted path (404) or a method this API does not serve (405) — is rejected
before this layer, and its body may be a different shape or not JSON at all.
Treat the HTTP status as authoritative there, and check the URL: the operations
below are the whole surface.
object
object
Machine-readable cause.
INVALID_REQUEST(400) — malformed dates, a non-UUID path id, an inverted range, or a range with no reportable books behind it.INVALID_API_KEY(401) — missing, invalid, expired or revoked key.PARTNER_API_NOT_ENABLED(403) — your key is valid, but your organization is not enrolled in the API programme. Contact us; do not rotate the key.PROVIDER_NOT_IN_PARTNER_SCOPE(403) — the provider exists but is not in your relationship, including one that has left it.BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE(403) — the entity exists but does not belong to theprovider_idin the path.PROVIDER_NOT_FOUND(404) — no provider with that id.BUSINESS_ENTITY_NOT_FOUND(404) — no business entity with that id.BOOKS_NOT_AVAILABLE(409) — the entity has no reportable books.INTERNAL_ERROR(500) — ours; retry with backoff.AUTH_SERVICE_UNAVAILABLE(503) — we could not verify your key; retry with backoff, and do not treat it as an authentication failure.
Human-readable detail. Do not match on it.
Examples
{ "error": { "code": "INVALID_API_KEY", "message": "Missing, invalid, expired or revoked API key." }}Either your organization is not enrolled in the API programme, or the provider or
business entity exists but is not in your partner relationship — including one
that has left it. The scope cases are distinct from 404 on purpose, so “gone”
and “never existed” are tellable apart.
The failure shape for every error raised inside a documented operation — validation, authorization, ours — so a client needs a single error path.
Match on code, not on message: the code set below is the contract and is
stable, while wording may be clarified. New codes may be added within v1 (see
guides/versioning), so treat an unrecognised code as “the HTTP status is
authoritative”.
One exception, and it is the one you are most likely to meet while
integrating. A request that does not reach a documented operation at all — an
unrouted path (404) or a method this API does not serve (405) — is rejected
before this layer, and its body may be a different shape or not JSON at all.
Treat the HTTP status as authoritative there, and check the URL: the operations
below are the whole surface.
object
object
Machine-readable cause.
INVALID_REQUEST(400) — malformed dates, a non-UUID path id, an inverted range, or a range with no reportable books behind it.INVALID_API_KEY(401) — missing, invalid, expired or revoked key.PARTNER_API_NOT_ENABLED(403) — your key is valid, but your organization is not enrolled in the API programme. Contact us; do not rotate the key.PROVIDER_NOT_IN_PARTNER_SCOPE(403) — the provider exists but is not in your relationship, including one that has left it.BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE(403) — the entity exists but does not belong to theprovider_idin the path.PROVIDER_NOT_FOUND(404) — no provider with that id.BUSINESS_ENTITY_NOT_FOUND(404) — no business entity with that id.BOOKS_NOT_AVAILABLE(409) — the entity has no reportable books.INTERNAL_ERROR(500) — ours; retry with backoff.AUTH_SERVICE_UNAVAILABLE(503) — we could not verify your key; retry with backoff, and do not treat it as an authentication failure.
Human-readable detail. Do not match on it.
Examples
Your organization is not enrolled in the API programme
{ "error": { "code": "PARTNER_API_NOT_ENABLED", "message": "This partner is not enrolled in the Flychain external API programme. Contact Flychain to request access." }}Provider not in your relationship
{ "error": { "code": "PROVIDER_NOT_IN_PARTNER_SCOPE", "message": "The provider is not associated with this partner." }}Entity does not belong to the provider in the path
{ "error": { "code": "BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE", "message": "The business entity does not belong to the requested provider." }}No provider or business entity exists with that id.
The failure shape for every error raised inside a documented operation — validation, authorization, ours — so a client needs a single error path.
Match on code, not on message: the code set below is the contract and is
stable, while wording may be clarified. New codes may be added within v1 (see
guides/versioning), so treat an unrecognised code as “the HTTP status is
authoritative”.
One exception, and it is the one you are most likely to meet while
integrating. A request that does not reach a documented operation at all — an
unrouted path (404) or a method this API does not serve (405) — is rejected
before this layer, and its body may be a different shape or not JSON at all.
Treat the HTTP status as authoritative there, and check the URL: the operations
below are the whole surface.
object
object
Machine-readable cause.
INVALID_REQUEST(400) — malformed dates, a non-UUID path id, an inverted range, or a range with no reportable books behind it.INVALID_API_KEY(401) — missing, invalid, expired or revoked key.PARTNER_API_NOT_ENABLED(403) — your key is valid, but your organization is not enrolled in the API programme. Contact us; do not rotate the key.PROVIDER_NOT_IN_PARTNER_SCOPE(403) — the provider exists but is not in your relationship, including one that has left it.BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE(403) — the entity exists but does not belong to theprovider_idin the path.PROVIDER_NOT_FOUND(404) — no provider with that id.BUSINESS_ENTITY_NOT_FOUND(404) — no business entity with that id.BOOKS_NOT_AVAILABLE(409) — the entity has no reportable books.INTERNAL_ERROR(500) — ours; retry with backoff.AUTH_SERVICE_UNAVAILABLE(503) — we could not verify your key; retry with backoff, and do not treat it as an authentication failure.
Human-readable detail. Do not match on it.
Examples
{ "error": { "code": "PROVIDER_NOT_FOUND", "message": "No provider exists with that id." }}{ "error": { "code": "BUSINESS_ENTITY_NOT_FOUND", "message": "No business entity exists with that id." }}The entity exists and is in your relationship, but has no books a report can be
produced from — it is still onboarding, or it has been deactivated. It appears in
GET /business_entities with reporting_available: false; skip it rather than
recording a zero.
The failure shape for every error raised inside a documented operation — validation, authorization, ours — so a client needs a single error path.
Match on code, not on message: the code set below is the contract and is
stable, while wording may be clarified. New codes may be added within v1 (see
guides/versioning), so treat an unrecognised code as “the HTTP status is
authoritative”.
One exception, and it is the one you are most likely to meet while
integrating. A request that does not reach a documented operation at all — an
unrouted path (404) or a method this API does not serve (405) — is rejected
before this layer, and its body may be a different shape or not JSON at all.
Treat the HTTP status as authoritative there, and check the URL: the operations
below are the whole surface.
object
object
Machine-readable cause.
INVALID_REQUEST(400) — malformed dates, a non-UUID path id, an inverted range, or a range with no reportable books behind it.INVALID_API_KEY(401) — missing, invalid, expired or revoked key.PARTNER_API_NOT_ENABLED(403) — your key is valid, but your organization is not enrolled in the API programme. Contact us; do not rotate the key.PROVIDER_NOT_IN_PARTNER_SCOPE(403) — the provider exists but is not in your relationship, including one that has left it.BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE(403) — the entity exists but does not belong to theprovider_idin the path.PROVIDER_NOT_FOUND(404) — no provider with that id.BUSINESS_ENTITY_NOT_FOUND(404) — no business entity with that id.BOOKS_NOT_AVAILABLE(409) — the entity has no reportable books.INTERNAL_ERROR(500) — ours; retry with backoff.AUTH_SERVICE_UNAVAILABLE(503) — we could not verify your key; retry with backoff, and do not treat it as an authentication failure.
Human-readable detail. Do not match on it.
Examples
{ "error": { "code": "BOOKS_NOT_AVAILABLE", "message": "This business entity does not currently have reportable books. GET /business_entities lists it with reporting_available: false." }}Our side. Safe to retry with backoff.
The failure shape for every error raised inside a documented operation — validation, authorization, ours — so a client needs a single error path.
Match on code, not on message: the code set below is the contract and is
stable, while wording may be clarified. New codes may be added within v1 (see
guides/versioning), so treat an unrecognised code as “the HTTP status is
authoritative”.
One exception, and it is the one you are most likely to meet while
integrating. A request that does not reach a documented operation at all — an
unrouted path (404) or a method this API does not serve (405) — is rejected
before this layer, and its body may be a different shape or not JSON at all.
Treat the HTTP status as authoritative there, and check the URL: the operations
below are the whole surface.
object
object
Machine-readable cause.
INVALID_REQUEST(400) — malformed dates, a non-UUID path id, an inverted range, or a range with no reportable books behind it.INVALID_API_KEY(401) — missing, invalid, expired or revoked key.PARTNER_API_NOT_ENABLED(403) — your key is valid, but your organization is not enrolled in the API programme. Contact us; do not rotate the key.PROVIDER_NOT_IN_PARTNER_SCOPE(403) — the provider exists but is not in your relationship, including one that has left it.BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE(403) — the entity exists but does not belong to theprovider_idin the path.PROVIDER_NOT_FOUND(404) — no provider with that id.BUSINESS_ENTITY_NOT_FOUND(404) — no business entity with that id.BOOKS_NOT_AVAILABLE(409) — the entity has no reportable books.INTERNAL_ERROR(500) — ours; retry with backoff.AUTH_SERVICE_UNAVAILABLE(503) — we could not verify your key; retry with backoff, and do not treat it as an authentication failure.
Human-readable detail. Do not match on it.
Examples
{ "error": { "code": "INTERNAL_ERROR", "message": "An unexpected error occurred. Retry with backoff." }}We could not verify your API key right now — our identity provider was
unreachable or rate-limited. This is not an authentication failure: the key
may well be valid. Retry with backoff rather than treating it as a 401.
The failure shape for every error raised inside a documented operation — validation, authorization, ours — so a client needs a single error path.
Match on code, not on message: the code set below is the contract and is
stable, while wording may be clarified. New codes may be added within v1 (see
guides/versioning), so treat an unrecognised code as “the HTTP status is
authoritative”.
One exception, and it is the one you are most likely to meet while
integrating. A request that does not reach a documented operation at all — an
unrouted path (404) or a method this API does not serve (405) — is rejected
before this layer, and its body may be a different shape or not JSON at all.
Treat the HTTP status as authoritative there, and check the URL: the operations
below are the whole surface.
object
object
Machine-readable cause.
INVALID_REQUEST(400) — malformed dates, a non-UUID path id, an inverted range, or a range with no reportable books behind it.INVALID_API_KEY(401) — missing, invalid, expired or revoked key.PARTNER_API_NOT_ENABLED(403) — your key is valid, but your organization is not enrolled in the API programme. Contact us; do not rotate the key.PROVIDER_NOT_IN_PARTNER_SCOPE(403) — the provider exists but is not in your relationship, including one that has left it.BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE(403) — the entity exists but does not belong to theprovider_idin the path.PROVIDER_NOT_FOUND(404) — no provider with that id.BUSINESS_ENTITY_NOT_FOUND(404) — no business entity with that id.BOOKS_NOT_AVAILABLE(409) — the entity has no reportable books.INTERNAL_ERROR(500) — ours; retry with backoff.AUTH_SERVICE_UNAVAILABLE(503) — we could not verify your key; retry with backoff, and do not treat it as an authentication failure.
Human-readable detail. Do not match on it.
Examples
{ "error": { "code": "AUTH_SERVICE_UNAVAILABLE", "message": "Unable to verify the API key right now. Retry with backoff." }}