Income statement totals for a date range
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/summary?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/summary?start_date=2026-07-01&end_date=2026-07-31' \ --header 'Authorization: Bearer <token>'The category totals for one range and nothing else — the endpoint to integrate against if you store a fixed set of figures per period.
Ten integers: the nine income-statement categories plus net_other_income_cents.
See guides/migrating-from-quickbooks for how they line up with a QuickBooks
Profit & Loss.
The start_date / end_date in the response are the effective range we
reported on after clamping, not necessarily the range you asked for.
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”The category totals for the effective range.
The range envelope carrying the category totals.
object
First day of the effective range, inclusive — what we reported on after clamping, not necessarily what was requested.
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.
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.
Currency of every amount in the payload. Always USD — the key exists so it
never has to be assumed.
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.
When this payload was produced, ISO 8601 UTC. Reports are computed on request, so this is also the as-of time of the figures.
The nine income-statement category totals, in statement order, plus
net_other_income_cents.
Every value is a signed integer in cents and is the rolled-up figure for that category, including every account beneath it. Expense categories are positive magnitudes, as they appear on the statement.
See guides/migrating-from-quickbooks for the mapping onto a QuickBooks Profit &
Loss.
object
Income earned from core services. This is gross revenue, and the figure to use as a revenue base.
Operating revenue net of refunds, discounts and write-offs. Equal to
operating_revenues_cents for most entities; where it differs it is the more
conservative revenue measure.
Direct costs of delivering the service.
Total net sales less cost of goods sold.
Overhead — administrative salaries, rent, software and the like.
Profit from operations, before non-operating items.
Non-operating costs, such as loan interest.
Non-operating income, such as grants or interest earned.
The bottom line, after everything above.
other_income_cents minus other_expenses_cents. The one derived value here,
returned directly so it does not have to be computed on your side.
Examples
July 2026 totals for one entity
GET /provider/9c1e7a42-.../business_entity/3f5d8b16-.../financial_reports/income_statement/summary?start_date=2026-07-01&end_date=2026-07-31
is_closed: false because this entity’s books are closed through 2026-06-30, so
July’s figures are still provisional.
{ "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", "totals": { "operating_revenues_cents": 3642500, "total_net_sales_cents": 3642500, "cost_of_goods_sold_cents": 1820000, "gross_profit_cents": 1822500, "operating_expenses_cents": 910000, "total_operating_profit_cents": 912500, "other_expenses_cents": 15000, "other_income_cents": 0, "net_profit_cents": 897500, "net_other_income_cents": -15000 }}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." }}