Skip to content

Full income statement for a date range

GET
/provider/{provider_id}/business_entity/{business_entity_id}/financial_reports/income_statement
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?start_date=2026-07-01&end_date=2026-07-31' \
--header 'Authorization: Bearer <token>'

The whole statement for one range, with per-account detail beneath each category — the identical structure our own application consumes, so nothing is held back.

Use this when you want to see which accounts make up an entity’s revenue or expenses. If you only store the category totals, use the summary variant: it costs the same on our side and returns roughly two orders of magnitude less JSON.

The start_date / end_date in the response are the effective range we reported on after clamping, not necessarily the range you asked for.

provider_id
required
string format: uuid

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-6a8b5c4d3e2f
business_entity_id
required
string format: uuid

The business entity, from GET /business_entities. Must belong to the provider_id in the same path.

Example
3f5d8b16-7c94-42a1-b0e6-58d9c2a71b43
start_date
required
string format: date
/^\d{4}-\d{2}-\d{2}$/

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-01
end_date
required
string format: date
/^\d{4}-\d{2}-\d{2}$/

Last 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-31

The full statement for the effective range.

Media typeapplication/json

The range envelope carrying the full statement.

object
provider_id
required
string format: uuid
business_entity_id
required
string format: uuid
start_date
required

First day of the effective range, inclusive — what we reported on after clamping, not necessarily what was requested.

string format: date
end_date
required

Last day of the effective range, inclusive. Compare both dates against what you asked for: a difference means the range was clamped to the entity’s books or to today.

string format: date
accounting_basis
required

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.

string | null
Allowed values: CASH ACCRUAL
currency
required

Currency of every amount in the payload. Always USD — the key exists so it never has to be assumed.

string
Allowed values: USD
is_closed
required

Whether the books are finalized through end_date (that is, end_date is on or before the entity’s books_closed_through).

false means the figures are provisional and may still be revised as transactions are reconciled. This is the flag to trust, rather than inferring from the calendar — see guides/data-semantics.

boolean
generated_at
required

When this payload was produced, ISO 8601 UTC. Reports are computed on request, so this is also the as-of time of the figures.

string format: date-time
income_statement
required

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
operating_revenues
required

One of the nine statement categories.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
key
additional properties
any
total_net_sales
required

One of the nine statement categories.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
key
additional properties
any
cost_of_goods_sold
required

A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
percentage
required

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.

number
percentage_comment
required

Explanatory copy for percentage that our own interface renders. Ignore it, as with title_tooltip.

string
gross_profit
required

A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
percentage
required

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.

number
percentage_comment
required

Explanatory copy for percentage that our own interface renders. Ignore it, as with title_tooltip.

string
operating_expenses
required

One of the nine statement categories.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
key
additional properties
any
total_operating_profit
required

One of the nine statement categories.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
key
additional properties
any
other_expenses
required

One of the nine statement categories.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
key
additional properties
any
other_income
required

One of the nine statement categories.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
key
additional properties
any
net_profit
required

A category that also carries a margin percentage — cost of goods sold, gross profit and net profit.

object
record
required

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
ledger_id

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.

string
name
required

Display name of the category or account.

string
type

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.

string
sub_type

Finer classification within a type, naming the category the account rolls up into. Present on account nodes.

string
amount_cents
required

Amount posted directly at this node, in cents. Often 0 on a root.

integer
total_amount_cents
required

This node’s total in cents, including every descendant. This is the figure to read.

integer
sort_code

The account’s code in the chart of accounts, as a string. Ordering and reconciliation aid; not unique across entities.

string
debit_credit

The natural balance of the account. Accounting metadata.

string
Allowed values: debit credit
percentage_of_operating_revenue

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).

number
children
required
Array<object> recursive
key
additional properties
any
title_tooltip
required

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.

string
percentage
required

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.

number
percentage_comment
required

Explanatory copy for percentage that our own interface renders. Ignore it, as with title_tooltip.

string
key
additional properties
any
Examples
ExamplejulyStatement

July 2026 full statement, with per-account detail

GET .../financial_reports/income_statement?start_date=2026-07-01&end_date=2026-07-31

The same figures as the summary example, with the accounts that make them up. Note that ledger_id, type, sub_type and sort_code appear on account nodes and not on category roots — an absent key means “not applicable to this node”.

{
"provider_id": "9c1e7a42-0b3d-4e58-9f21-6a8b5c4d3e2f",
"business_entity_id": "3f5d8b16-7c94-42a1-b0e6-58d9c2a71b43",
"start_date": "2026-07-01",
"end_date": "2026-07-31",
"accounting_basis": "CASH",
"currency": "USD",
"is_closed": false,
"generated_at": "2026-08-20T14:02:11Z",
"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": [
{
"ledger_id": "rhvm6QyfxbygB5warCZv8X",
"name": "Insurance Revenue",
"type": "revenue",
"sub_type": "operating_revenues",
"amount_cents": 3642500,
"total_amount_cents": 3642500,
"sort_code": "4108",
"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": [
{
"ledger_id": "SEPLyMTbGaCV5TKpq72rPe",
"name": "Clinical Labor",
"type": "expense",
"sub_type": "cost_of_goods_sold",
"amount_cents": 1600000,
"total_amount_cents": 1600000,
"sort_code": "5010",
"debit_credit": "debit",
"percentage_of_operating_revenue": 43.925875085792725,
"children": []
},
{
"ledger_id": "8Fq3rYtBnLpZ2vXcW6dKmA",
"name": "Medical Supplies",
"type": "expense",
"sub_type": "cost_of_goods_sold",
"amount_cents": 220000,
"total_amount_cents": 220000,
"sort_code": "5040",
"debit_credit": "debit",
"percentage_of_operating_revenue": 6.039807824296499,
"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": [
{
"ledger_id": "Qw9ZmT4hRc1LbYs7XkPvNe",
"name": "Rent",
"type": "expense",
"sub_type": "operating_expenses",
"amount_cents": 500000,
"total_amount_cents": 500000,
"sort_code": "6110",
"debit_credit": "debit",
"percentage_of_operating_revenue": 13.726835964310228,
"children": []
},
{
"ledger_id": "Ld2Kx8VbNq5TyWmC3rHpZa",
"name": "Administrative Salaries",
"type": "expense",
"sub_type": "operating_expenses",
"amount_cents": 410000,
"total_amount_cents": 410000,
"sort_code": "6020",
"debit_credit": "debit",
"percentage_of_operating_revenue": 11.256005490734386,
"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": [
{
"ledger_id": "Tz6BpXn9WgQ2mKdV4sYcRf",
"name": "Interest Expense",
"type": "expense",
"sub_type": "other_expenses",
"amount_cents": 15000,
"total_amount_cents": 15000,
"sort_code": "7210",
"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.

Media typeapplication/json

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
error
required
object
code
required

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 the provider_id in 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.
string
Allowed values: INVALID_REQUEST INVALID_API_KEY PARTNER_API_NOT_ENABLED PROVIDER_NOT_IN_PARTNER_SCOPE BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE PROVIDER_NOT_FOUND BUSINESS_ENTITY_NOT_FOUND BOOKS_NOT_AVAILABLE INTERNAL_ERROR AUTH_SERVICE_UNAVAILABLE
message
required

Human-readable detail. Do not match on it.

string
key
additional properties
any
key
additional properties
any
Examples

Unparseable date

{
"error": {
"code": "INVALID_REQUEST",
"message": "start_date must be a valid date in YYYY-MM-DD format."
}
}

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.

Media typeapplication/json

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
error
required
object
code
required

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 the provider_id in 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.
string
Allowed values: INVALID_REQUEST INVALID_API_KEY PARTNER_API_NOT_ENABLED PROVIDER_NOT_IN_PARTNER_SCOPE BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE PROVIDER_NOT_FOUND BUSINESS_ENTITY_NOT_FOUND BOOKS_NOT_AVAILABLE INTERNAL_ERROR AUTH_SERVICE_UNAVAILABLE
message
required

Human-readable detail. Do not match on it.

string
key
additional properties
any
key
additional properties
any
Examples
ExampleinvalidKey
{
"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.

Media typeapplication/json

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
error
required
object
code
required

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 the provider_id in 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.
string
Allowed values: INVALID_REQUEST INVALID_API_KEY PARTNER_API_NOT_ENABLED PROVIDER_NOT_IN_PARTNER_SCOPE BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE PROVIDER_NOT_FOUND BUSINESS_ENTITY_NOT_FOUND BOOKS_NOT_AVAILABLE INTERNAL_ERROR AUTH_SERVICE_UNAVAILABLE
message
required

Human-readable detail. Do not match on it.

string
key
additional properties
any
key
additional properties
any
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."
}
}

No provider or business entity exists with that id.

Media typeapplication/json

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
error
required
object
code
required

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 the provider_id in 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.
string
Allowed values: INVALID_REQUEST INVALID_API_KEY PARTNER_API_NOT_ENABLED PROVIDER_NOT_IN_PARTNER_SCOPE BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE PROVIDER_NOT_FOUND BUSINESS_ENTITY_NOT_FOUND BOOKS_NOT_AVAILABLE INTERNAL_ERROR AUTH_SERVICE_UNAVAILABLE
message
required

Human-readable detail. Do not match on it.

string
key
additional properties
any
key
additional properties
any
Examples
{
"error": {
"code": "PROVIDER_NOT_FOUND",
"message": "No provider 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.

Media typeapplication/json

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
error
required
object
code
required

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 the provider_id in 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.
string
Allowed values: INVALID_REQUEST INVALID_API_KEY PARTNER_API_NOT_ENABLED PROVIDER_NOT_IN_PARTNER_SCOPE BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE PROVIDER_NOT_FOUND BUSINESS_ENTITY_NOT_FOUND BOOKS_NOT_AVAILABLE INTERNAL_ERROR AUTH_SERVICE_UNAVAILABLE
message
required

Human-readable detail. Do not match on it.

string
key
additional properties
any
key
additional properties
any
Examples
ExamplenoBooks
{
"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.

Media typeapplication/json

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
error
required
object
code
required

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 the provider_id in 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.
string
Allowed values: INVALID_REQUEST INVALID_API_KEY PARTNER_API_NOT_ENABLED PROVIDER_NOT_IN_PARTNER_SCOPE BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE PROVIDER_NOT_FOUND BUSINESS_ENTITY_NOT_FOUND BOOKS_NOT_AVAILABLE INTERNAL_ERROR AUTH_SERVICE_UNAVAILABLE
message
required

Human-readable detail. Do not match on it.

string
key
additional properties
any
key
additional properties
any
Examples
ExampleinternalError
{
"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.

Media typeapplication/json

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
error
required
object
code
required

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 the provider_id in 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.
string
Allowed values: INVALID_REQUEST INVALID_API_KEY PARTNER_API_NOT_ENABLED PROVIDER_NOT_IN_PARTNER_SCOPE BUSINESS_ENTITY_NOT_IN_PARTNER_SCOPE PROVIDER_NOT_FOUND BUSINESS_ENTITY_NOT_FOUND BOOKS_NOT_AVAILABLE INTERNAL_ERROR AUTH_SERVICE_UNAVAILABLE
message
required

Human-readable detail. Do not match on it.

string
key
additional properties
any
key
additional properties
any
Examples
ExampleauthUnavailable
{
"error": {
"code": "AUTH_SERVICE_UNAVAILABLE",
"message": "Unable to verify the API key right now. Retry with backoff."
}
}