medianfi-com Checkout API

The Checkout API from medianfi-com — 6 operation(s) for checkout.

Operations 6

GET /companies/{companyId}/checkout/subscription Get the company's active Median subscription, with plan + payment method #
GET /companies/{companyId}/checkout/custom-offer Get the sales-led custom pricing offer for the authenticated user #
POST /companies/{companyId}/checkout/custom-offer-session Start Stripe Checkout at the sales-led custom flat monthly price #
GET /companies/{companyId}/checkout/quote Retired usage-derived price quote (always 410) #
POST /companies/{companyId}/pricing/statement-estimate Estimate monthly transactions from an uploaded statement #
GET /companies/{companyId}/pricing/usage-vs-quote Compare actual posted entry volume against the quoted volume #

Work with this as data

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-checkout-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 Specification

medianfi-com-checkout-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Median Checkout API
  version: 0.1.0
  description: Production-grade Node.js + Express API starter template
  license:
    name: Proprietary
servers:
- url: /api/v1
security: []
tags:
- name: Checkout
paths:
  /companies/{companyId}/checkout/subscription:
    parameters:
    - $ref: '#/components/parameters/companyId'
    get:
      operationId: getCheckoutSubscription
      summary: Get the company's active Median subscription, with plan + payment method
      description: 'Returns the joined view of a company''s Median (SaaS) subscription,

        shaped for the Billing & Plan card in the customer app. When the

        local median_subscriptions row is missing but the company already

        has a Stripe customer, the service resyncs from Stripe before

        returning (self-heals missed webhook deliveries).'
      tags:
      - Checkout
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Subscription (null when the company has none)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                    - true
                  data:
                    oneOf:
                    - $ref: '#/components/schemas/CheckoutSubscriptionResponse'
                    - type: 'null'
                required:
                - success
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /companies/{companyId}/checkout/custom-offer:
    parameters:
    - $ref: '#/components/parameters/companyId'
    get:
      operationId: getCustomPricingOffer
      summary: Get the sales-led custom pricing offer for the authenticated user
      description: 'Returns the active sales-led custom pricing offer matched by the

        authenticated user''s email, or null. When present, the onboarding price

        screen shows a single fixed-price card instead of the tier list.'
      tags:
      - Checkout
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Custom offer (null when none is active for this email)
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                    - true
                  data:
                    oneOf:
                    - type: object
                      additionalProperties: false
                      properties:
                        monthlyPriceCents:
                          type: integer
                          minimum: 1
                          maximum: 100000000
                        trialDays:
                          type: integer
                          minimum: 0
                          maximum: 365
                      required:
                      - monthlyPriceCents
                      - trialDays
                    - type: 'null'
                required:
                - success
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /companies/{companyId}/checkout/custom-offer-session:
    parameters:
    - $ref: '#/components/parameters/companyId'
    post:
      operationId: createCustomOfferCheckoutSession
      summary: Start Stripe Checkout at the sales-led custom flat monthly price
      description: 'Creates a Stripe Checkout session billing the customer''s agreed flat

        monthly price (locked indefinitely), looked up by the authenticated

        email and never trusted from the client. Adds a 30-day trial when the

        offer grants the first month free. The price attaches to the shared

        Median catalog product, like the usage-based subscription.'
      tags:
      - Checkout
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Stripe Checkout URL
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                    - true
                  data:
                    type: object
                    properties:
                      url:
                        type:
                        - string
                        - 'null'
                    required:
                    - url
                required:
                - success
                - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
  /companies/{companyId}/checkout/quote:
    parameters:
    - $ref: '#/components/parameters/companyId'
    get:
      operationId: getPricingQuote
      deprecated: true
      summary: Retired usage-derived price quote (always 410)
      description: '#3647: the $55/account + $0.60/line meter was retired on 2026-10-21.

        New signups are priced by revenue tier, so this quote no longer exists.

        It always answers 410 `METERED_PRICING_RETIRED`, as does

        `POST /checkout/custom-session`, the retired checkout for these quotes.'
      tags:
      - Checkout
      security:
      - bearerAuth: []
      responses:
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '410':
          description: Per-account pricing is retired.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
  /companies/{companyId}/pricing/statement-estimate:
    parameters:
    - $ref: '#/components/parameters/companyId'
    post:
      operationId: estimateStatement
      summary: Estimate monthly transactions from an uploaded statement
      description: 'Line-counts a recent statement for one unconnected account into a monthly

        transaction estimate, so a statement account still contributes to the

        onboarding quote. With a documentId the server reads the uploaded

        statement itself: text-layer PDFs and text/CSV exports are counted

        directly; scanned PDFs/images go through a best-effort LLM count. Falls

        back to a conservative per-account default when the statement cannot be

        counted.'
      tags:
      - Checkout
      security:
      - bearerAuth: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                documentId:
                  type: string
                  format: uuid
                  description: An uploaded statement document to count server-side (takes precedence over rawText/lineCount).
                rawText:
                  type: string
                  description: Raw statement text to line-count.
                lineCount:
                  type: integer
                  minimum: 0
                  description: A pre-counted line total (when counted client-side).
                monthsCovered:
                  type: integer
                  minimum: 1
                  description: Months the statement covers; the line count is divided by this.
      responses:
        '200':
          description: The per-account monthly transaction estimate
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                    - true
                  data:
                    type: object
                    properties:
                      monthlyTransactions:
                        type: integer
                        minimum: 0
                      source:
                        type: string
                        enum:
                        - parsed
                        - fallback
                    required:
                    - monthlyTransactions
                    - source
                required:
                - success
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationError'
  /companies/{companyId}/pricing/usage-vs-quote:
    parameters:
    - $ref: '#/components/parameters/companyId'
    get:
      operationId: getUsageVsQuote
      summary: Compare actual posted entry volume against the quoted volume
      description: 'Returns the quoted monthly entry volume vs actual posted ledger lines over

        the trailing complete months, with the re-quote threshold (150% monthly,

        200% annual) and an advisory breach flag set when every trailing month

        (>= 2) exceeds the threshold. V1 surfaces this for display only and never

        auto-rebills.'
      tags:
      - Checkout
      security:
      - bearerAuth: []
      responses:
        '200':
          description: The usage-vs-quote comparison
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                    - true
                  data:
                    type: object
                    properties:
                      hasQuotedVolume:
                        type: boolean
                      billingInterval:
                        type:
                        - string
                        - 'null'
                      quotedMonthlyEntries:
                        type:
                        - integer
                        - 'null'
                        minimum: 0
                      thresholdPct:
                        type:
                        - integer
                        - 'null'
                      thresholdEntries:
                        type:
                        - integer
                        - 'null'
                        minimum: 0
                      months:
                        type: array
                        items:
                          type: object
                          properties:
                            month:
                              type: string
                            actualEntries:
                              type: integer
                              minimum: 0
                            ratioPct:
                              type:
                              - integer
                              - 'null'
                          required:
                          - month
                          - actualEntries
                          - ratioPct
                      breached:
                        type: boolean
                    required:
                    - hasQuotedVolume
                    - billingInterval
                    - quotedMonthlyEntries
                    - thresholdPct
                    - thresholdEntries
                    - months
                    - breached
                required:
                - success
                - data
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
components:
  schemas:
    ApiErrorResponse:
      type: object
      required:
      - success
      - error
      properties:
        success:
          type: boolean
          enum:
          - false
        error:
          $ref: '#/components/schemas/ProblemDetail'
    CheckoutSubscriptionResponse:
      type: object
      required:
      - id
      - companyId
      - status
      - stripeSubscriptionStatus
      - platformItemState
      - platformItemId
      - providerObservedAt
      - platformTermsVerifiedAt
      - stripeSubscriptionId
      - stripePriceId
      - currentPeriodStart
      - currentPeriodEnd
      - cancelledAt
      - planTier
      - plan
      - billing
      - paymentMethod
      - paymentMethodStatus
      - paymentMethodSummary
      - source
      properties:
        id:
          type:
          - string
          - 'null'
          format: uuid
        companyId:
          type: string
          format: uuid
        status:
          type: string
          enum:
          - active
          - past_due
          - cancelled
          - trialing
          - incomplete
          - needs_attention
          description: Missing or ambiguous platform items project needs_attention; cancellation takes precedence.
        stripeSubscriptionStatus:
          type:
          - string
          - 'null'
          description: Exact provider status from the last observation.
        platformItemState:
          type: string
          enum:
          - unverified
          - present
          - missing
          - ambiguous
        platformItemId:
          type:
          - string
          - 'null'
        providerObservedAt:
          type:
          - string
          - 'null'
          format: date-time
        platformTermsVerifiedAt:
          type:
          - string
          - 'null'
          format: date-time
        stripeSubscriptionId:
          type:
          - string
          - 'null'
        stripePriceId:
          type:
          - string
          - 'null'
        currentPeriodStart:
          type:
          - string
          - 'null'
          format: date-time
        currentPeriodEnd:
          type:
          - string
          - 'null'
          format: date-time
        cancelledAt:
          type:
          - string
          - 'null'
          format: date-time
        planTier:
          type:
          - string
          - 'null'
        plan:
          oneOf:
          - $ref: '#/components/schemas/CheckoutSubscriptionPlan'
          - type: 'null'
        billing:
          description: 'Null when the billed amount cannot be read from Stripe (no

            subscription, or Stripe unavailable). Clients must not present the

            plan''s list price as the billed amount in that case.

            '
          oneOf:
          - $ref: '#/components/schemas/CheckoutSubscriptionBilling'
          - type: 'null'
        paymentMethod:
          oneOf:
          - $ref: '#/components/schemas/CheckoutSubscriptionPaymentMethod'
          - type: 'null'
        paymentMethodStatus:
          type: string
          enum:
          - available
          - none
          - unavailable
          - not_configured
          description: 'Whether Stripe returned a payment method, confirmed that none is

            configured, or could not establish the answer. The not_configured

            state means the company has no Stripe customer id; show "No Stripe

            billing on file" without a Stripe portal action. An unavailable

            result must not be presented as "No payment method". Neither state

            permits displaying the stored payment-method summary as current.

            '
        paymentMethodSummary:
          type:
          - string
          - 'null'
        source:
          type: string
          enum:
          - median_subscription
          - stripe_resync
          - billing_plan_fallback
    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
    CheckoutSubscriptionPaymentMethod:
      type: object
      required:
      - brand
      - last4
      - expMonth
      - expYear
      properties:
        brand:
          type: string
        last4:
          type: string
        expMonth:
          type:
          - integer
          - 'null'
          minimum: 1
          maximum: 12
        expYear:
          type:
          - integer
          - 'null'
    CheckoutSubscriptionBilling:
      type: object
      description: 'What Stripe actually charges the subscription each period. Differs from

        the plan''s list price whenever a coupon applies — a comped company has

        an effectiveAmountCents of 0 against a non-zero listAmountCents.

        '
      required:
      - listAmountCents
      - effectiveAmountCents
      - interval
      - discountLabel
      - trialEndsAt
      - discountEndsAt
      properties:
        listAmountCents:
          type: integer
          minimum: 0
        effectiveAmountCents:
          description: 'The recurring charge each period once billing starts. While

            trialEndsAt is set this amount is not yet being charged.

            '
          type: integer
          minimum: 0
        interval:
          type: string
          enum:
          - month
          - year
        discountLabel:
          type:
          - string
          - 'null'
        trialEndsAt:
          description: 'Date the trial ends and effectiveAmountCents starts being charged.

            Non-null means nothing is due until then, and clients must show both

            the zero due now and the recurring amount with this date.

            '
          type:
          - string
          - 'null'
          format: date-time
        discountEndsAt:
          description: 'Date the coupon expires and listAmountCents resumes. Null when the

            coupon runs for the life of the subscription.

            '
          type:
          - string
          - 'null'
          format: date-time
    CheckoutSubscriptionPlan:
      type: object
      required:
      - id
      - name
      - priceCents
      - interval
      - features
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        priceCents:
          type: integer
          minimum: 0
        interval:
          type: string
          enum:
          - month
          - year
        features:
          type: array
          items:
            type: string
  responses:
    BadRequest:
      description: Request failed validation
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    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'
    ValidationError:
      description: Request failed validation
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
  parameters:
    companyId:
      name: companyId
      in: path
      required: true
      schema:
        type: string
        format: uuid
  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