Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/medianfi-com:medianfi-com-books-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Median Books API
version: 0.1.0
description: Production-grade Node.js + Express API starter template
license:
name: Proprietary
servers:
- url: /api/v1
security: []
tags:
- name: Books
paths:
/companies/{companyId}/books/overview:
parameters:
- $ref: '#/components/parameters/companyId'
- $ref: '#/components/parameters/demoParityCustomerAppSurface'
get:
operationId: getBooksOverview
summary: Books hub overview (today's balances, last completed month)
description: 'Demo-parity customer route for an explicitly allowlisted active or test company. `/qa` callers additionally require the QA application marker and persisted test lifecycle.
Returns a single-screen summary of the company''s financial position. Balances are as of **today** (read at the current UTC month end, so they tie to the Assets and Liabilities sub-ledgers); revenue and expenses cover the **last completed calendar month** (UTC). Revenue is operating revenue (other income and 4999 Uncategorized Income excluded). Includes headline asset / liability / revenue / expense figures plus composition segments and P&L spark series for the trailing months.
All monetary amounts are in **cents** (integer).
Every amount comes from the selected entity''s posted books. A liability balance is never mirrored into a synthetic asset segment. A company that has never closed a GL period still gets its real balances (#2411).'
tags:
- Books
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/reportEntityId'
responses:
'200':
description: Books overview payload
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
$ref: '#/components/schemas/BooksOverview'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
/companies/{companyId}/books/schedules/recognition:
parameters:
- $ref: '#/components/parameters/companyId'
- $ref: '#/components/parameters/demoParityCustomerAppSurface'
get:
operationId: getRecognitionSchedule
summary: Recognition / amortization schedule for a document
description: 'Demo-parity customer route for an explicitly allowlisted active or test company. `/qa` callers additionally require the QA application marker and persisted test lifecycle.
Returns the recognition or amortization schedule for a contract / invoice document line: the schedule type and a list of period entries with running cumulative amounts and posted/pending status. `{ immediate: true }` is returned only when the company posts through the subledger core and no schedule exists for the document in the selected entity. Every other schedule-less case returns `{ status, reason }` and makes no recognition claim: `unavailable`/`document_not_found` for a document outside the selected entity (unknown and sibling-entity documents are indistinguishable), `not_scheduled`/`no_business_event` for a document with no business event, and `unavailable`/`schedule_authority_not_entity_scoped` when the only schedule authority is not keyed to the selected entity.'
tags:
- Books
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/reportEntityId'
- name: documentId
in: query
required: true
description: 'The invoice/bill document id. Resolved to its recognition schedule only after the document is authorized for the selected legal entity. It is then matched against `business_events.metadata.sourceDocumentId`, and the schedule keys on that event id (`event_schedules.source_event_id`).
'
schema:
type: string
- name: lineIndex
in: query
required: false
description: 'Zero-based line index for multi-line documents (reserved for future use; currently only the first schedule per document is returned).
'
schema:
type: integer
minimum: 0
responses:
'200':
description: Recognition schedule payload
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
$ref: '#/components/schemas/RecognitionSchedule'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
description: Missing or invalid query parameters (e.g. documentId not provided)
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
components:
responses:
Forbidden:
description: Insufficient permissions or not a company member
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
NotFound:
description: Resource not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
Unauthorized:
description: Authentication required
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
schemas:
ProblemDetail:
type: object
properties:
type:
type: string
title:
type: string
description: 'For application errors, a stable UPPER_SNAKE machine code (for example `NOT_FOUND`, `FORECAST_NOT_FOUND`, `VALIDATION_ERROR`). Clients branch on this, never on `detail` wording. A few transport level responses use a short human title instead.
'
status:
type: integer
detail:
type: string
description: 'Human-readable explanation; correlate a failure with `traceId`. A NOT_FOUND-family 404 names the resource type (for example "Company not found"), not its id. Some legacy messages still include an id (tracked in #2666).
'
instance:
type: string
traceId:
type: string
retryAfter:
type: integer
minimum: 0
description: Whole seconds until retry is allowed for a 429 response
errors:
type: array
items:
type: object
properties:
field:
type: string
message:
type: string
extensions:
type: object
additionalProperties: true
BooksOverview:
type: object
description: 'Headline financial overview for the Books hub: balances as of today, revenue and expenses for the last completed calendar month. All monetary amounts are integers in **cents**.
Asset segments are total assets by class (cash, what clients owe you, prepaid costs, inventory, equipment after depreciation, other), from posted entity-scoped report values; the service never derives an asset from a payable balance.
'
required:
- companyId
- entityId
- asOf
- lastFullMonthLabel
- netLastMonthCents
- assets
- liabilities
- revenue
- expenses
properties:
companyId:
type: string
format: uuid
description: Authenticated company whose Books data was read.
entityId:
type: string
format: uuid
description: Authorized concrete legal entity whose Books data was read.
asOf:
type: string
format: date
description: Today (UTC). Balances include every posting through the current month.
lastFullMonthLabel:
type: string
description: Human-readable label for the last completed calendar month (e.g. "May 2026").
netLastMonthCents:
type: integer
description: Net income for the last completed month in cents (full P&L revenue − expenses).
assets:
type: object
required:
- netBookValueCents
- segments
properties:
totalAssetsCents:
type: integer
description: Total balance-sheet assets as of today, in cents (the hub's Assets value).
netBookValueCents:
type: integer
description: 'Fixed-asset net book value (cost − accumulated depreciation) as of today, in cents. Ties out to the Assets page headline and the balance-sheet fixed-asset section, NOT to total balance-sheet assets.
'
segments:
type: array
items:
$ref: '#/components/schemas/BooksOverviewSegment'
liabilities:
type: object
required:
- totalCents
- segments
properties:
totalCents:
type: integer
description: Total liabilities as of today, in cents.
equityCents:
type: integer
description: Balance-sheet equity as of today, including earnings not yet closed (#1994). The liabilities segments end with an "Equity" segment when it is positive.
segments:
type: array
items:
$ref: '#/components/schemas/BooksOverviewSegment'
revenue:
type: object
required:
- recognizedLastMonthCents
- deferredCarryingCents
- sparkSeries
properties:
recognizedLastMonthCents:
type: integer
description: Operating revenue recognized in the last completed month, in cents (other income and 4999 Uncategorized Income excluded).
deferredCarryingCents:
type: integer
description: 'Outstanding deferred-revenue liability carrying balance as of today, in cents (unearned revenue still to be recognized).
'
sparkSeries:
type: array
items:
$ref: '#/components/schemas/BooksOverviewSparkPoint'
expenses:
type: object
required:
- recognizedLastMonthCents
- topCategoryCents
- sparkSeries
properties:
recognizedLastMonthCents:
type: integer
description: Total expenses in the last closed month, in cents.
topCategoryCents:
type: integer
description: 'Largest single expense category recognized in the last completed month, in cents.
'
largestAccount:
type:
- object
- 'null'
description: The single expense account with the largest amount in the last completed month.
required:
- name
- amountCents
properties:
name:
type: string
amountCents:
type: integer
sparkSeries:
type: array
items:
$ref: '#/components/schemas/BooksOverviewSparkPoint'
BooksOverviewSegment:
type: object
description: 'A single line-item segment inside an assets or liabilities breakdown. `amountCents` is always a non-negative integer.
'
required:
- label
- amountCents
properties:
label:
type: string
amountCents:
type: integer
minimum: 0
RecognitionSchedule:
description: 'Recognition or amortization schedule for a document/contract line.
When `immediate` is `true`, entity-keyed schedule authority proves the document recognises in full in the period it was received. When `scheduleType` and `schedule` are populated, a persisted schedule exists. When `status` is present, nothing proves either, and no recognition timing is claimed.
'
oneOf:
- type: object
description: Immediate full recognition — no schedule.
required:
- companyId
- entityId
- immediate
properties:
companyId:
type: string
format: uuid
entityId:
type: string
format: uuid
immediate:
type: boolean
enum:
- true
- type: object
description: Multi-period recognition or amortization schedule.
required:
- companyId
- entityId
- scheduleType
- schedule
properties:
companyId:
type: string
format: uuid
entityId:
type: string
format: uuid
scheduleType:
type: string
enum:
- prepaid_amortization
- deferred_revenue_recognition
- depreciation
- operating_lease_payment
- finance_lease_payment
schedule:
type: array
items:
$ref: '#/components/schemas/RecognitionScheduleEntry'
- type: object
description: No persisted schedule and no authority proving immediate recognition.
required:
- companyId
- entityId
- status
- reason
properties:
companyId:
type: string
format: uuid
entityId:
type: string
format: uuid
status:
type: string
enum:
- not_scheduled
- unavailable
reason:
type: string
enum:
- document_not_found
- no_business_event
- schedule_authority_not_entity_scoped
BooksOverviewSparkPoint:
type: object
description: One month's P&L data for the spark-line chart.
required:
- month
- revenueCents
- expensesCents
- netCents
properties:
month:
type: string
description: YYYY-MM-DD (first of month)
revenueCents:
type: integer
expensesCents:
type: integer
netCents:
type: integer
RecognitionScheduleEntry:
type: object
description: A single period entry in a recognition or amortization schedule.
required:
- periodIndex
- label
- amountCents
- cumulativeCents
- posted
- date
properties:
periodIndex:
type: integer
minimum: 1
description: 1-based sequence number.
label:
type: string
description: Human-readable label for this period (e.g. "Period 1").
amountCents:
type: integer
description: Amount recognised/amortized in this period, in cents.
cumulativeCents:
type: integer
description: Running cumulative total through this period, in cents.
posted:
type: boolean
description: Whether the corresponding journal entry has been posted.
date:
type: string
format: date
description: Scheduled date for this period (ISO YYYY-MM-DD).
parameters:
reportEntityId:
name: entityId
in: query
description: 'Concrete legal entity to read. Mutually exclusive with `reportingScopeId`/`scopeAsOf`. Omission is accepted only when the actor is authorized to exactly one concrete entity.
'
schema:
type: string
format: uuid
companyId:
name: companyId
in: path
required: true
schema:
type: string
format: uuid
demoParityCustomerAppSurface:
name: X-Median-App-Surface
in: header
required: false
description: 'Optional customer-app bundle marker for production-promoted demo-parity routes. Production customer calls omit this header. When present, qa selects the QA bundle and the server additionally requires an allowlisted test company with persisted client_status=test.
'
schema:
type: string
const: qa
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
serviceApiKey:
type: apiKey
in: header
name: X-API-Key
description: 'Persistent credential for the configured cloud-bookkeeping service principal. The key must carry accountant:* and is accepted only on accountant operations that explicitly list this scheme. Ordinary API keys, and service keys presented to bearer-only operations, are denied.
'
refreshSessionCookie:
type: apiKey
in: cookie
name: __Secure-median_refresh
description: 'Exact production HttpOnly refresh-session cookie. Local non-secure development uses median_refresh.
'
passkeyEnrollmentGrantCookie:
type: apiKey
in: cookie
name: __Secure-median_passkey_enrollment
description: 'Exact production HttpOnly passkey-enrollment grant cookie. Local non-secure development uses median_passkey_enrollment.
'
webAuthnCeremonyCookie:
type: apiKey
in: cookie
name: __Secure-median_webauthn
description: 'Exact production HttpOnly WebAuthn ceremony cookie. Local non-secure development uses median_webauthn.
'
x-median-quarantined-authorities:
decision: ADR-0001-model-a
runtimeStatus: unmounted
description: 'Migrations 267-272 modeled legal entities as separate company tenants. These paths are not runtime API authority while their preserved accounting math is re-keyed to legal entities inside one company workspace.
'
paths:
- /companies/{companyId}/consolidation-groups
- /companies/{companyId}/consolidation-groups/{groupId}/versions/{groupVersionId}/report-rollups
- /companies/{companyId}/consolidation-groups/{groupId}/versions/{groupVersionId}/report-rollups/{rollupId}
- /companies/{companyId}/consolidation-groups/{groupId}/versions/{groupVersionId}/translation-adjustments
- /companies/{companyId}/consolidation-groups/{groupId}/versions/{groupVersionId}/translation-adjustments/{adjustmentId}
x-median-demo-parity-customer-surface:
runtimeStatus: mounted-lifecycle-only
description: 'v2 customer-app capabilities available to JWT-authenticated members of any active or test company — the v2 app is the product, not a rollout cohort, so no allowlist applies to the markerless path. Production customer calls omit X-Median-App-Surface. Test-company calls may carry X-Median-App-Surface: qa to select the QA bundle; that marker branch alone still requires membership in CUSTOMER_APP_DEMO_PARITY_COMPANY_IDS. An API key, unknown marker, malformed company id, inactive company, missing gate dependency, or failed company lookup receives the standard hidden-resource 404 contract. The held surfaces riding these prefixes (AR/AP, Forecast, Insights) carry their own additional allowlist gate — see x-median-forecast-hold and x-median-ar-ap-hold.
'
headerContract: '#/components/parameters/demoParityCustomerAppSurface'
routePrefixes:
- /companies/{companyId}/ar
- /companies/{companyId}/ap
- /companies/{companyId}/customers
- /companies/{companyId}/vendors
- /companies/{companyId}/contracts
- /companies/{companyId}/receivables
- /companies/{companyId}/entities
- /companies/{companyId}/currencies
- /companies/{companyId}/reporting-scopes
- /companies/{companyId}/reporting-scopes/{reportingScopeId}/versions/{versionId}/rollups
- /companies/{companyId}/reporting-scopes/{reportingScopeId}/versions/{versionId}/translation-adjustments
- /companies/{companyId}/presentation-report-snapshots
- /companies/{companyId}/reporting-trial-balances
- /companies/{companyId}/reporting-scopes/{reportingScopeId}/versions/{versionId}/trial-balances
- /companies/{companyId}/reporting-scopes/{reportingScopeId}/versions/{versionId}/intercompany
- /companies/{companyId}/weekly-email
- /companies/{companyId}/forecast
- /companies/{companyId}/books
- /companies/{companyId}/sub-ledgers
x-median-forecast-hold:
runtimeStatus: mounted-only-with-server-gate
description: 'Forecast is held. Beyond the lifecycle-only customer surface above, every operation under the prefix below also requires the company to appear in the held-surface allowlist CUSTOMER_APP_DEMO_PARITY_COMPANY_IDS — the one operator-set list that opens AR/AP, Forecast and Insights (the legacy CUSTOMER_APP_FORECAST_COMPANY_IDS variable is no longer consulted). It is empty by default, so the v2 rollout alone never exposes Forecast. A company off the list receives the same hidden-resource 404 contract as one for which the surface does not exist. The auth-context featureFlags key `forecast` mirrors this verdict for the customer app shell.
'
featureFlag: forecast
routePrefixes:
- /companies/{companyId}/forecast
x-median-ar-ap-hold:
runtimeStatus: mounted-only-with-server-gate
description: 'Receivables/Payables are held behind TWO required authorities. Beyond the lifecycle-only customer surface above, every operation under the prefixes below requires the company to appear in the held-surface allowlist CUSTOMER_APP_DEMO_PARITY_COMPANY_IDS (requireDemoParityAllowlistedCompany) AND to satisfy the company_subledger_flags conversion chain (requireArApItemsEnabled — the same authority the public /pay page, aging and the accountant portal consult); failing either answers the opaque 404. The auth-context featureFlags key `arApItems` mirrors exactly that conjunction, resolved server-side, so the customer shell hides the Receivables/Payables nav and pages instead of offering menu entries these routes 404. Default is FALSE for every company while the list is empty or the conversion has not run.
'
featureFlag: arApItems
routePrefixes:
- /companies/{companyId}/ar
- /companies/{companyId}/ap
- /companies/{companyId}/customers
- /companies/{companyId}/vendors
- /companies/{companyId}/contracts
- /companies/{companyId}/receivables
x-median-demo-parity-qa-only:
runtimeStatus: mounted-only-with-server-gate
description: 'Strict test-company-only routes. Every interactive call requires X-Median-App-Surface: qa in addition to JWT authentication, the server allowlist, and persisted client_status=test. A copied header, API key, active company, missing gate dependency, or failed company lookup receives the standard hidden-resource 404 contract.
'
headerContract: '#/components/parameters/qaAppSurface'
routePrefixes:
- /companies/{companyId}/gl-accounts/{id}/monetary-classification
- /companies/{companyId}/fx-account-roles
- /companies/{companyId}/gl-periods/{periodId}/fx-revaluation
- /accountant/companies/{customerId}/gl-accounts/{id}/monetary-classification
- /accountant/companies/{customerId}/fx-account-roles
- /accountant/companies/{customerId}/gl-periods/{periodId}/fx-revaluation
- /accountant/companies/{customerId}/ar/{id}
- /accountant/companies/{customerId}/ap/{id}
x-median-onboarding-v3-surface:
runtimeStatus: promoted
promotionFlag: ONBOARDING_V3_QA_ONLY=false
description: 'Promoted. The deployment this contract describes runs ONBOARDING_V3_QA_ONLY=false, so none of the onboarding-v3 auth, pricing, or setup paths below requires X-Median-App-Surface: qa. An unmarked request is served and reaches ordinary authentication, so an unauthenticated call now answers 401 rather than the hidden-resource 404. Mounting is still conditional: with ONBOARDING_V3_ENABLED false every path below returns the hidden-resource 404 before body parsing or authentication. The header stays defined and is still honoured, because a deployment left at ONBOARDING_V3_QA_ONLY=true keeps requiring it on every path below and 404s unmarked traffic; setting that flag back to true is the rollback. On either setting the header is a pre-company bundle marker, never tenant authorization.
'
headerContract: '#/components/parameters/onboardingV3QaSurface'
routePaths:
- /auth/otp/start
- /auth/otp/verify
- /auth/passkeys/register/options
- /auth/passkeys/register/verify
- /auth/passkeys/assert/options
- /auth/passkeys/assert/verify
- /onboarding/v3/quote
- /onboarding/v3/offer/resolve
- /onboarding/v3/flow
- /onboarding/v3/setup-intent
- /onboarding/v3/subscribe
- /onboarding/v3/test-account-activation
- /onboarding/v3/checkout-session
- /onboarding/v3/checkout-session/complete
- /onboarding/v3/setup-state
- /onboarding/v3/delegate-invites
- /onboarding/v3/delegate-invites/{inviteId}
- /onboarding/v3/delegate/resolve
- /onboarding/v3/delegate
- /onboarding/v3/task-context
- /onboarding/v3/delegate/task-context
- /onboarding/v3/banks/plaid/link-token
- /onboarding/v3/banks/plaid/exchange
- /onboarding/v3/banks/commit
- /onboarding/v3/documents/google-workspace/auth-url
- /onboarding/v3/documents/google-workspace/callback
- /onboarding/v3/books/quickbooks/auth-url
- /onboarding/v3/books/quickbooks/callback
- /onboarding/v3/books/xero/auth-url
- /onboarding/v3/books/xero/callback
- /onboarding/v3/welcome-call
- /onboarding/v3/welcome-call/embed
- /onboarding/v3/books-progress
- /onboarding/v3/books/open
- /companies/{companyId}/onboarding/v3/questions
- /companies/{companyId}/onboarding/v3/questions/{questionId}/answer
- /companies/{companyId}/onboarding/v3/review-items