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-journal-entries-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 Journal Entries API
version: 0.1.0
description: Production-grade Node.js + Express API starter template
license:
name: Proprietary
servers:
- url: /api/v1
security: []
tags:
- name: Journal Entries
paths:
/companies/{companyId}/journal-entries:
parameters:
- $ref: '#/components/parameters/companyId'
get:
operationId: listJournalEntries
summary: List journal entries with filters
tags:
- Journal Entries
security:
- bearerAuth: []
parameters:
- name: entityId
in: query
description: Concrete legal entity. Legacy unscoped rows resolve only to the primary entity.
schema:
type: string
format: uuid
- name: periodId
in: query
schema:
type: string
format: uuid
- name: sourceType
in: query
schema:
type: string
enum:
- transaction
- document
- adjustment
- system
- name: sourceId
in: query
schema:
type: string
- name: status
in: query
description: Omit for posted entries only; `void` returns voided entries. Any other value returns 422.
schema:
type: string
enum:
- posted
- void
- name: dateFrom
in: query
schema:
type: string
format: date
- name: dateTo
in: query
schema:
type: string
format: date
- $ref: '#/components/parameters/limit'
- $ref: '#/components/parameters/cursor'
responses:
'200':
description: Paginated list of journal entries
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntriesListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/ValidationError'
post:
operationId: createJournalEntry
summary: Create a journal entry with lines (must balance)
description: Requires company role cfo, admin, or owner.
tags:
- Journal Entries
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateJournalEntryInput'
responses:
'201':
description: Journal entry created
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntryResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
description: Validation or business rule error
/companies/{companyId}/journal-entries/{id}:
parameters:
- $ref: '#/components/parameters/companyId'
- $ref: '#/components/parameters/resourceId'
get:
operationId: getJournalEntry
summary: Get a journal entry by ID (includes lines)
tags:
- Journal Entries
security:
- bearerAuth: []
responses:
'200':
description: Journal entry found
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntryResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Journal entry not found
/companies/{companyId}/journal-entries/{id}/source:
parameters:
- $ref: '#/components/parameters/companyId'
- $ref: '#/components/parameters/resourceId'
get:
operationId: getJournalEntrySource
summary: Get a journal entry with source drill-down metadata
tags:
- Journal Entries
security:
- bearerAuth: []
responses:
'200':
description: Journal entry found with source metadata
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntryResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
description: Journal entry not found
/companies/{companyId}/journal-entries/{id}/void:
parameters:
- $ref: '#/components/parameters/companyId'
- $ref: '#/components/parameters/resourceId'
post:
operationId: voidJournalEntry
summary: Void an active posted journal entry
description: Requires company role cfo, admin, or owner.
tags:
- Journal Entries
security:
- bearerAuth: []
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/VoidJournalEntryRequest'
responses:
'200':
description: Journal entry voided
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntryResponse'
'401':
$ref: '#/components/responses/UnauthorizedJson'
'403':
$ref: '#/components/responses/ForbiddenJson'
'404':
$ref: '#/components/responses/NotFoundJson'
'409':
description: Journal entry is already void, non-posted, or soft-deleted
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'422':
description: Journal entry is reconciled or in a filing-locked period (closed periods are voidable)
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
/accountant/companies/{customerId}/transactions/{transactionId}/journal-entries:
parameters:
- $ref: '#/components/parameters/customerId'
- $ref: '#/components/parameters/transactionId'
get:
operationId: accountantListTransactionJournalEntries
summary: List journal entries linked to a customer transaction
tags:
- Journal Entries
security:
- bearerAuth: []
- serviceApiKey: []
responses:
'200':
description: Journal entries linked by source or line transaction id
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntriesListResponse'
'401':
$ref: '#/components/responses/UnauthorizedJson'
'403':
$ref: '#/components/responses/ForbiddenJson'
/accountant/companies/{customerId}/journal-entries/{id}:
parameters:
- $ref: '#/components/parameters/customerId'
- $ref: '#/components/parameters/resourceId'
get:
operationId: accountantGetJournalEntry
summary: Get one customer journal entry by ID (includes lines)
description: Read-back of a single journal entry, e.g. to verify the effect of a void or posting without scanning whole-account activity reports.
tags:
- Journal Entries
security:
- bearerAuth: []
- serviceApiKey: []
parameters:
- name: include
in: query
required: false
schema:
type: string
enum:
- source
description: Set to `source` to include source drill-down metadata.
responses:
'200':
description: Journal entry found
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntryResponse'
'401':
$ref: '#/components/responses/UnauthorizedJson'
'403':
$ref: '#/components/responses/ForbiddenJson'
'404':
$ref: '#/components/responses/NotFoundJson'
/accountant/companies/{customerId}/journal-entries/{id}/void:
parameters:
- $ref: '#/components/parameters/customerId'
- $ref: '#/components/parameters/resourceId'
post:
operationId: accountantVoidJournalEntry
summary: Accountant void of one active posted journal entry
tags:
- Journal Entries
security:
- bearerAuth: []
- serviceApiKey: []
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/VoidJournalEntryRequest'
responses:
'200':
description: Journal entry voided
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntryResponse'
'401':
$ref: '#/components/responses/UnauthorizedJson'
'403':
$ref: '#/components/responses/ForbiddenJson'
'404':
$ref: '#/components/responses/NotFoundJson'
'409':
description: Journal entry is already void, non-posted, or soft-deleted
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'422':
description: Journal entry is reconciled or in a filing-locked period (closed periods are voidable)
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
/accountant/companies/{customerId}/journal-entries/{id}/correct-date:
parameters:
- $ref: '#/components/parameters/customerId'
- $ref: '#/components/parameters/resourceId'
post:
operationId: accountantCorrectJournalEntryDate
summary: Correct the posted date of one active journal entry
description: 'Accountant-only date correction for a posted journal entry. The target date must be inside the posted-ledger date domain. Evidence naming the source of the new date is required. Neither the entry''s current period nor the target period may be filing-locked. Requires audit logging and GL recompute. Does not re-date SafeGuard `qbo-sg-9852`.
A legacy entry (no currency-authoritative line) is moved in place: when a GL period exists for the target date it is bound onto `period_id`, otherwise period_id stays null (do not invent missing months), and a matching source-transaction `occurred_on` is moved in the same write.
A currency-authoritative entry cannot change its date in place. When it is the posting of a single bank-feed row (`sourceType` `transaction`, `postingKey` `transaction:` or a replacement of it, no line for another row, the row not imported from QuickBooks or mirrored from Stripe), it is voided and replaced in one transaction by an entry with the same lines on the target date, in the target period, with the row''s source and posting key, so the row is never posted a second time on its old date. The response is the replacement (a new `id`, `relatedJeId` pointing at the original); the original keeps `adjustmentReason` `date_correction:->`, which a later rebuild of the row''s posting honors. A correction back to the row''s provider date is recorded as `date_restore:->` instead and releases that pin. The bank row''s `occurred_on` is left as the provider reported it. The target date must fall in an existing GL period, and the row must not be in a completed reconciliation. Any other currency-authoritative entry is refused with 422 `JOURNAL_ENTRY_CURRENCY_AUTHORITY_IMMUTABLE`.'
tags:
- Journal Entries
security:
- bearerAuth: []
- serviceApiKey: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CorrectJournalEntryDateRequest'
responses:
'200':
description: Journal entry date corrected
content:
application/json:
schema:
$ref: '#/components/schemas/JournalEntryResponse'
'401':
$ref: '#/components/responses/UnauthorizedJson'
'403':
$ref: '#/components/responses/ForbiddenJson'
'404':
$ref: '#/components/responses/NotFoundJson'
'409':
description: 'Journal entry is already void, non-posted, or soft-deleted, or a replacement lost a race (the entry was replaced, its lines or ownership changed, or its bank-feed row went inactive meanwhile)
'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'422':
description: 'Date is out of policy, the entry or its bank-feed row is reconciled, a period involved is filing-locked, no period covers the target date of a replacement, or the entry''s date is currency-authoritative and it is not a single bank-feed posting, or that posting''s bank-feed row no longer exists
'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
components:
schemas:
CorrectJournalEntryDateRequest:
type: object
required:
- entryDate
- evidence
additionalProperties: false
properties:
entryDate:
type: string
format: date
description: Target posted date (YYYY-MM-DD) inside the ledger date domain.
evidence:
type: string
minLength: 8
maxLength: 500
description: Source of the corrected date (for example a QuickBooks TxnDate).
CreateJournalEntryInput:
type: object
required:
- entryDate
- description
- sourceType
- lines
properties:
entityId:
type: string
format: uuid
description: Concrete legal posting entity; defaults to the company's primary entity.
entryDate:
type: string
format: date
example: '2024-01-15'
description:
type: string
minLength: 1
maxLength: 500
sourceType:
type: string
enum:
- transaction
- document
- adjustment
- system
sourceId:
type: string
format: uuid
periodId:
type: string
format: uuid
postingKey:
type: string
description: 'Optional identity a hand-written replacement can inherit from a voided transaction-sourced entry (`transaction:<uuid>`). Required to keep the engine from re-posting the same transaction (#1975).
'
pattern: ^transaction:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$
lines:
type: array
minItems: 2
items:
type: object
required:
- glAccountId
properties:
glAccountId:
type: string
format: uuid
debitCents:
type: integer
minimum: 0
default: 0
creditCents:
type: integer
minimum: 0
default: 0
memo:
type: string
maxLength: 500
transactionId:
type: string
format: uuid
documentId:
type: string
format: uuid
PaginationMeta:
type: object
properties:
nextCursor:
type:
- string
- 'null'
hasMore:
type: boolean
ApiErrorResponse:
type: object
required:
- success
- error
properties:
success:
type: boolean
enum:
- false
error:
$ref: '#/components/schemas/ProblemDetail'
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
JournalEntriesListResponse:
type: object
properties:
success:
type: boolean
data:
type: array
items:
$ref: '#/components/schemas/JournalEntry'
meta:
$ref: '#/components/schemas/PaginationMeta'
VoidJournalEntryRequest:
type: object
properties:
reason:
type: string
maxLength: 500
JournalLine:
type: object
required:
- id
- journalEntryId
- glAccountId
- debitCents
- creditCents
- currency
- minorUnitExponent
- ledgerDebitCents
- ledgerCreditCents
- ledgerCurrency
- ledgerMinorUnitExponent
properties:
id:
type: string
format: uuid
journalEntryId:
type: string
format: uuid
glAccountId:
type: string
format: uuid
classId:
type:
- string
- 'null'
format: uuid
description: 'Line-level class dimension for downstream reporting. Accountant-portal responses always carry this field. Customer-facing responses do not carry it on journal lines.
'
className:
type:
- string
- 'null'
description: 'Name of the class in `classId`, resolved from the company''s class list. Accountant-portal responses only, present when the class is known.
'
classStatus:
type: string
enum:
- draft
- active
- inactive
description: 'Status of the class in `classId`. Accountant-portal responses only; never returned to the customer app.
'
debitCents:
type: integer
creditCents:
type: integer
currency:
type: string
memo:
type:
- string
- 'null'
transactionId:
type:
- string
- 'null'
format: uuid
documentId:
type:
- string
- 'null'
format: uuid
JournalEntry:
type: object
properties:
id:
type: string
format: uuid
companyId:
type: string
format: uuid
entityId:
type:
- string
- 'null'
format: uuid
description: Concrete legal posting entity. Null is legacy data and resolves to the primary entity.
entryDate:
type: string
format: date
description:
type: string
sourceType:
type: string
enum:
- transaction
- document
- adjustment
- system
sourceId:
type:
- string
- 'null'
format: uuid
periodId:
type:
- string
- 'null'
format: uuid
status:
type: string
enum:
- posted
- void
createdByUserId:
type:
- string
- 'null'
format: uuid
createdAt:
type: string
format: date-time
deletedAt:
type:
- string
- 'null'
format: date-time
deletedByUserId:
type:
- string
- 'null'
format: uuid
relatedJeId:
type:
- string
- 'null'
format: uuid
adjustmentReason:
type:
- string
- 'null'
isClosingEntry:
type: boolean
description: A period-end closing entry (a system entry keyed on one of the company's periods). Reports leave these out of the P&L.
sourceLabel:
type: string
sourceLink:
oneOf:
- type: object
properties:
kind:
type: string
id:
type: string
- type: 'null'
lines:
type: array
items:
$ref: '#/components/schemas/JournalLine'
JournalEntryResponse:
type: object
properties:
success:
type: boolean
data:
$ref: '#/components/schemas/JournalEntry'
responses:
ForbiddenJson:
description: Insufficient permissions or not a company member
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
UnauthorizedJson:
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
Forbidden:
description: Insufficient permissions or not a company member
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
Unauthorized:
description: Authentication required
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
NotFoundJson:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
ValidationError:
description: Request failed validation
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetail'
parameters:
customerId:
name: customerId
in: path
required: true
schema:
type: string
format: uuid
resourceId:
name: id
in: path
required: true
schema:
type: string
format: uuid
limit:
name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 50
companyId:
name: companyId
in: path
required: true
schema:
type: string
format: uuid
transactionId:
name: transactionId
in: path
required: true
schema:
type: string
format: uuid
cursor:
name: cursor
in: query
schema:
type: string
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