Cavuno Billing API

Your account's platform subscription, entitlements, checkout, upgrade, and Stripe Connect status.

Operations 9

POST /billing/checkout Create hosted checkout for a plan #
POST /billing/portal Create a billing portal session #
POST /billing/upgrade Upgrade the account plan #
GET /billing/subscription Get the account platform subscription #
GET /billing/connect Get payment connection status #
DELETE /billing/connect Disconnect the payment connection #
GET /billing/builder-credits Get Builder credit history #
GET /billing/tax Get tax collection settings #

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/cavuno-com:cavuno-com-billing-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

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

cavuno-com-billing-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Cavuno v1 REST Billing API
  version: 1.0.0
  description: 'The Cavuno API is organized around REST. Our API has predictable resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs. ## Base URL


    Production: `https://api.cavuno.com/v1`


    All API requests must be made over HTTPS. Calls made over plain HTTP will fail. ## Authentication


    The Cavuno API uses API keys to authenticate requests. You can view and manage your API keys in the Cavuno dashboard, under Settings → Developer → API keys. Cavuno API keys have the prefix `cavuno_live_`. Your API keys carry many privileges, so be sure to keep them secure. Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth. Authentication to the API is performed via Bearer auth. Provide your API key as the bearer token in the `Authorization` header:


    ```bash

    curl https://api.cavuno.com/v1/jobs \

    -H "Authorization: Bearer YOUR_SECRET_API_KEY"

    ```


    API requests without authentication will fail. ## Rate limits


    The Cavuno API has rate limits in place to ensure stability and reliability. By default, API keys are limited to 100 requests per minute. If you exceed your limit, requests return an HTTP 429 response with a `Retry-After` header indicating when you can try again. If you have a use case that needs a higher limit, contact support. ## Idempotency


    The API supports idempotency for safely retrying requests without accidentally performing the same operation twice. For example, if a request to create a job fails due to a network connection error, you can safely retry the request with the same idempotency key, and we''ll guarantee that only one job is created. To perform an idempotent request, provide an additional `Idempotency-Key` header on any `POST`, `PATCH`, or `DELETE` request:


    ```bash

    curl https://api.cavuno.com/v1/jobs \

    -X POST \

    -H "Authorization: Bearer cavuno_live_..." \

    -H "Idempotency-Key: $(uuidgen)" \

    -H "Content-Type: application/json" \

    -d ''{ "title": "Senior Engineer" }''

    ```


    ## Errors


    Cavuno uses conventional HTTP response codes to indicate the success or failure of an API request. In general: codes in the `2xx` range indicate success, codes in the `4xx` range indicate an error that failed given the information provided (e.g., a required parameter was omitted), and codes in the `5xx` range indicate an error with Cavuno''s servers (these are rare). Error responses include a JSON body with details:


    ```json

    {

    "error": {

    "code": "validation_bad_request",

    "message": "Field ''title'' is required.",

    "requestId": "req_..."

    }

    }

    ```


    Some errors carry an additional `details` field with structured context, such as per-field validation issues. ### Plan upgrade hints


    When an Operator API request is refused because of the board''s Cavuno plan, the error also carries an `upgrade` object. It names the capability that blocked the request, the cheapest self-serve plan that unlocks it (when that can be told), and the hosted billing endpoints that start the upgrade:


    ```json

    {

    "error": {

    "code": "settings_plan_required_for_branding_removal",

    "message": "Removing Cavuno branding requires a plan that includes branding removal.",

    "requestId": "req_...",

    "upgrade": {

    "capability": "canRemoveBranding",

    "requiredPlan": "basic",

    "checkout": { "method": "POST", "path": "/v1/billing/checkout" },

    "changePlan": { "method": "POST", "path": "/v1/billing/upgrade" }

    }

    }

    }

    ```


    Call `GET /v1/billing/subscription` first. With no active subscription, use `checkout`; with one, use `changePlan`. Send `{ "planKey": "" }` and give the returned `url` to a person: both endpoints return a hosted page where a person confirms the purchase. Nothing is charged until they do. Each `path` is relative to the API origin (`https://api.cavuno.com`), like `Location` headers and list `url` fields, so do not join it to a base URL that already ends in `/v1`.'
  contact:
    name: Cavuno
    url: https://cavuno.com
servers:
- url: https://api.cavuno.com/v1
  description: Production
security:
- bearerAuth: []
tags:
- name: Billing
  description: Your account's platform subscription, entitlements, checkout, upgrade, and Stripe Connect status.
paths:
  /billing/checkout:
    post:
      summary: Create hosted checkout for a plan
      description: Returns a hosted human-consent URL for the target plan. Requires `billing.manage`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BillingCheckoutBody'
      responses:
        '200':
          description: Hosted checkout session created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingCheckout'
        default:
          description: An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: createCheckoutSession
  /billing/portal:
    post:
      summary: Create a billing portal session
      description: Returns a hosted billing portal URL for the Board's own Cavuno subscription, the same portal the dashboard's Manage billing button opens. A person uses it to view invoices, update payment methods, and manage the subscription. Each call issues a fresh URL. Returns `billing_portal_unavailable` (409) when the Board has never subscribed; start a subscription with `POST /v1/billing/checkout` instead. Requires `billing.manage`.
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateBillingPortalSessionBody'
      responses:
        '200':
          description: Billing portal session created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingPortalSession'
        '400':
          description: The request was malformed or `returnUrl` is not allowed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: The Board has no billing account yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: The billing portal could not be opened.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: createBillingPortalSession
  /billing/upgrade:
    post:
      summary: Upgrade the account plan
      description: Creates a hosted human-consent handoff for an upgrade. It never charges a saved payment method directly. Requires `billing.manage` and an `Idempotency-Key` header.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BillingUpgradeBody'
      responses:
        '200':
          description: Upgrade completed or checkout required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingUpgrade'
        default:
          description: An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: upgradeSubscription
  /billing/subscription:
    get:
      summary: Get the account platform subscription
      description: Returns the Board's Cavuno plan, status, renewal state, and included product capabilities. Provider identifiers are never returned.
      responses:
        '200':
          description: The account billing subscription.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingSubscription'
        default:
          description: An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: getBillingSubscription
  /billing/connect:
    get:
      summary: Get payment connection status
      description: 'Returns the Board''s payment connection readiness: whether payments and payouts are enabled, the connected Stripe account id, the tax collection status, and the names of any details Stripe still needs.'
      responses:
        '200':
          description: The Board payment connection status.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingConnect'
        default:
          description: An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: getBillingConnect
    delete:
      summary: Disconnect the payment connection
      description: 'Disconnects the Board''s payment account, as the dashboard''s Disconnect action does. The Board stops taking payments through it straight away: paid plans can no longer be checked out and the job-seeker paywall is unpublished. Nothing changes inside the payment account itself: collected money, payouts, customers, and existing subscriptions stay there and keep renewing, but buyers lose the self-serve billing link on the Board until you reconnect. The synced tax status is cleared. Reconnect later with `POST /v1/billing/connect/onboarding-link`. Disconnecting a Board that is not connected succeeds. Sandbox boards use a platform-provisioned test connection and are refused with `sandbox_connect_managed` (409). Requires `plans.manage`.'
      responses:
        '204':
          description: Payment connection removed.
        '409':
          description: Sandbox boards cannot disconnect.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: disconnectBillingConnect
  /billing/builder-credits:
    get:
      summary: Get Builder credit history
      description: 'Returns the Board''s Builder credit ledger: automatic top-up settings, the newest credit grants, and recent credit spend per day, month and billing period. Credit amounts are in tenths of a credit, like GET /usage, which carries the current balances.'
      responses:
        '200':
          description: The Board Builder credit history.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingBuilderCredits'
        default:
          description: An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: getBillingBuilderCredits
  /billing/tax:
    get:
      summary: Get tax collection settings
      description: 'Returns the Board''s tax collection settings, read live from its connected Stripe account: default tax behavior and tax code, head office country, and active tax registrations. Cavuno only reads these settings; change them in Stripe. When Stripe is not connected the response has `connected: false`.'
      responses:
        '200':
          description: The Board tax collection settings.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingTax'
        default:
          description: An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: getBillingTax
  /billing/connect/onboarding-link:
    post:
      summary: Create a Stripe Connect onboarding link
      description: 'Returns a hosted Stripe onboarding URL for the Board''s payment connection, creating the connected account first if the Board has none. The URL is single-use and expires within minutes: hand it to a human immediately, then poll `GET /v1/billing/connect` until `acceptingPayments` and `payoutsEnabled` are both true. Calling this again issues a fresh link, so request a new one if the human did not finish in time. When the human finishes or the link expires, Stripe sends them to the Board''s payment settings in the dashboard. Sandbox boards use a platform-provisioned test connection and are refused with `sandbox_connect_managed` (409). Requires `plans.manage`.'
      responses:
        '200':
          description: Onboarding link created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingConnectOnboardingLink'
        default:
          description: An error. Every non-2xx response uses the same envelope; see the Errors section of the introduction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      x-audience: operator
      tags:
      - Billing
      operationId: createBillingConnectOnboardingLink
components:
  schemas:
    BillingConnect:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_connect
        connected:
          type: boolean
        acceptingPayments:
          type: boolean
        payoutsEnabled:
          type: boolean
        detailsSubmitted:
          type: boolean
        actionRequired:
          type: boolean
        stripeAccountId:
          type:
          - string
          - 'null'
          description: The Board's connected Stripe account id (`acct_...`), or null when Stripe is not connected. Use it to find the account in the Stripe Dashboard.
        taxCollectionStatus:
          type:
          - string
          - 'null'
          enum:
          - active
          - pending
          - null
          description: '`active`: Stripe Tax is set up and checkouts collect tax. `pending`: Stripe Tax setup was started but is not finished. Null when tax collection was never set up. Details are on GET /billing/tax.'
        requirements:
          type:
          - object
          - 'null'
          properties:
            currentlyDue:
              type: array
              items:
                type: string
              description: Names of the details Stripe needs now to keep the account enabled, for example `external_account`.
            pastDue:
              type: array
              items:
                type: string
              description: Names of the details whose deadline has passed. Payments or payouts stay paused until they are provided.
          required:
          - currentlyDue
          - pastDue
          description: What Stripe still needs from the account holder, as requirement names only. Null when Stripe is not connected.
      required:
      - object
      - connected
      - acceptingPayments
      - payoutsEnabled
      - detailsSubmitted
      - actionRequired
      - stripeAccountId
      - taxCollectionStatus
      - requirements
    BillingCheckout:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_checkout
        funding:
          $ref: '#/components/schemas/BillingHostedCheckoutFunding'
        url:
          type: string
          format: uri
          description: Short-lived hosted checkout URL.
        planKey:
          type: string
          enum:
          - starter
          - basic
          - grow
          - advanced
          - scale
          - enterprise
          description: Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve.
        interval:
          type: string
          enum:
          - monthly
          - annual
      required:
      - object
      - funding
      - url
      - planKey
      - interval
    BuilderCreditUsagePeriod:
      type: object
      properties:
        kind:
          type: string
          enum:
          - day
          - month
          - billing
          description: 'Window the counter covers: a UTC day, a UTC month, or the billing period of the plan.'
        periodKey:
          type: string
          description: Stable key of the window, in the same form as the `periodKey` fields of GET /usage.
        usedTenths:
          type: integer
          minimum: 0
          description: Credits spent in the window. In tenths of a credit, like GET /usage (10 is one credit).
        runCount:
          type: integer
          minimum: 0
          description: Metered Builder chat runs counted in the window.
      required:
      - kind
      - periodKey
      - usedTenths
      - runCount
    BuilderCreditAutoTopup:
      type: object
      properties:
        available:
          type: boolean
          description: Whether automatic top-ups are offered at all. When false, no automatic top-up runs, whatever `enabled` says.
        canTopUp:
          type: boolean
          description: Whether the Board's plan allows buying credits. When false, no automatic top-up runs, whatever `enabled` says.
        enabled:
          type: boolean
          description: Whether the Board opted in to automatic credit top-ups. False when it never did. Top-ups only run when `available` and `canTopUp` are also true.
        packTenths:
          type: integer
          minimum: 0
          description: Credits bought by each automatic top-up. In tenths of a credit, like GET /usage (10 is one credit).
        monthlyCapUsdCents:
          type:
          - integer
          - 'null'
          minimum: 0
          description: Most that automatic top-ups may spend in one UTC month, in US cents. Null means no cap.
        disabledReason:
          type:
          - string
          - 'null'
          description: Why automatic top-ups are paused, as `{code}|{month}` (for example a declined card), or null. A pause only lasts for the month it names.
        consentedAt:
          type:
          - string
          - 'null'
          description: ISO-8601 time a person on the Board opted in to automatic top-ups, or null when they never did.
      required:
      - available
      - canTopUp
      - enabled
      - packTenths
      - monthlyCapUsdCents
      - disabledReason
      - consentedAt
    BillingBuilderCredits:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_builder_credits
        autoTopup:
          $ref: '#/components/schemas/BuilderCreditAutoTopup'
        grants:
          type: array
          items:
            $ref: '#/components/schemas/BuilderCreditGrant'
          description: The 20 newest credit grants (refreshes and purchases), newest first.
        usagePeriods:
          type: array
          items:
            $ref: '#/components/schemas/BuilderCreditUsagePeriod'
          description: 'Recent credit spend: up to 14 days, 6 months and 6 billing periods, each newest first.'
      required:
      - object
      - autoTopup
      - grants
      - usagePeriods
    BillingUpgrade:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_upgrade
        funding:
          $ref: '#/components/schemas/BillingHostedCheckoutFunding'
        status:
          type: string
          enum:
          - human_action_required
        url:
          type: string
          format: uri
        planKey:
          type: string
          enum:
          - starter
          - basic
          - grow
          - advanced
          - scale
          - enterprise
          description: Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve.
      required:
      - object
      - funding
      - status
      - url
      - planKey
    BillingHostedCheckoutFunding:
      type: object
      properties:
        type:
          type: string
          enum:
          - hosted_checkout
      required:
      - type
    BillingSubscription:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_subscription
        active:
          type: boolean
        status:
          type:
          - string
          - 'null'
        planKey:
          type:
          - string
          - 'null'
        currentPeriodEnd:
          type:
          - number
          - 'null'
          description: Subscription period end as a millisecond epoch.
        cancelAtPeriodEnd:
          type: boolean
        capabilities:
          type: object
          properties:
            activeJobsLimit:
              type:
              - number
              - 'null'
            subscriberLimit:
              type:
              - number
              - 'null'
            teamSeatLimit:
              type:
              - number
              - 'null'
            canBePublic:
              type: boolean
            canRemoveBranding:
              type: boolean
            apiAccess:
              type: boolean
          required:
          - activeJobsLimit
          - subscriberLimit
          - teamSeatLimit
          - canBePublic
          - canRemoveBranding
          - apiAccess
      required:
      - object
      - active
      - status
      - planKey
      - currentPeriodEnd
      - cancelAtPeriodEnd
      - capabilities
    CreateBillingPortalSessionBody:
      type: object
      properties:
        returnUrl:
          type: string
          format: uri
          description: Where to send the person when they leave the portal. Must be an https URL on the Cavuno dashboard origin. Defaults to the Board billing settings page in the dashboard.
      additionalProperties: false
    BillingTaxRegistration:
      type: object
      properties:
        country:
          type: string
          description: Two-letter ISO country code of the tax registration.
        type:
          type: string
          description: Stripe registration type for the country, for example `standard`, `oss_union`, `oss_non_union` or `ioss`.
      required:
      - country
      - type
    BillingUpgradeBody:
      type: object
      properties:
        planKey:
          type: string
          enum:
          - starter
          - basic
          - grow
          - advanced
          - scale
          - enterprise
          description: Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve.
        interval:
          type: string
          enum:
          - monthly
          - annual
          description: Billing interval. Defaults to monthly when omitted.
      required:
      - planKey
    BillingTax:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_tax
        connected:
          type: boolean
          description: Whether the Board has a connected Stripe account. When false, every other field is null.
        taxCollectionStatus:
          type:
          - string
          - 'null'
          enum:
          - active
          - pending
          - null
          description: '`active`: checkouts collect tax. `pending`: setup was started but is not finished. Null when tax collection was never set up.'
        livemode:
          type:
          - boolean
          - 'null'
          description: Whether the Stripe account is in live mode. False for a test account. Null when Stripe is not connected.
        taxBehavior:
          type:
          - string
          - 'null'
          enum:
          - inferred_by_currency
          - inclusive
          - exclusive
          - null
          description: 'Whether prices include tax by default: `inclusive`, `exclusive`, or `inferred_by_currency`. Null when not set or when Stripe could not be reached.'
        taxCode:
          type:
          - string
          - 'null'
          description: Default Stripe product tax code, for example `txcd_10000000`. `txcd_00000000` means nontaxable. Null when not set or when Stripe could not be reached.
        taxCodeName:
          type:
          - string
          - 'null'
          description: Name of the default tax code, or null.
        headOfficeCountry:
          type:
          - string
          - 'null'
          description: Two-letter ISO country code of the head office address set in Stripe Tax, or null.
        registrations:
          type:
          - array
          - 'null'
          items:
            $ref: '#/components/schemas/BillingTaxRegistration'
          description: Active tax registrations, up to 100. An empty list means no registrations, so no tax is collected anywhere. Null when Stripe is not connected or the list could not be loaded.
      required:
      - object
      - connected
      - taxCollectionStatus
      - livemode
      - taxBehavior
      - taxCode
      - taxCodeName
      - headOfficeCountry
      - registrations
    BillingPortalSession:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_portal_session
        url:
          type: string
          format: uri
          description: Short-lived hosted billing portal URL. Hand it to a human straight away; request a new one if it expires.
      required:
      - object
      - url
    BillingCheckoutBody:
      type: object
      properties:
        planKey:
          type: string
          enum:
          - starter
          - basic
          - grow
          - advanced
          - scale
          - enterprise
          description: Self-serve plan key. enterprise is not self-serve and returns plan_not_self_serve.
        interval:
          type: string
          enum:
          - monthly
          - annual
          description: Billing interval. Defaults to monthly when omitted.
      required:
      - planKey
    BuilderCreditGrant:
      type: object
      properties:
        source:
          type: string
          enum:
          - refresh
          - topup
          - auto-topup
          description: '`refresh`: a one-time refresh of the plan allowance. `topup`: credits a person bought. `auto-topup`: credits bought automatically.'
        tenths:
          type: integer
          minimum: 0
          description: Credits granted. In tenths of a credit, like GET /usage (10 is one credit).
        remainingTenths:
          type: integer
          minimum: 0
          description: Credits of this grant not yet spent. In tenths of a credit, like GET /usage (10 is one credit).
        refundedTenths:
          type: integer
          minimum: 0
          description: Credits taken back after a refund or a lost dispute. In tenths of a credit, like GET /usage (10 is one credit).
        priceUsdCents:
          type:
          - integer
          - 'null'
          minimum: 0
          description: Price paid for a purchase, in US cents. Null for a refresh, which is free.
        createdAt:
          type: string
          description: ISO-8601 time the grant was created.
        expiresAt:
          type:
          - string
          - 'null'
          description: ISO-8601 time the unspent credits expire, or null when they never expire (purchases).
      required:
      - source
      - tenths
      - remainingTenths
      - refundedTenths
      - priceUsdCents
      - createdAt
      - expiresAt
    PlanUpgradeHint:
      type: object
      properties:
        capability:
          type: string
          enum:
          - activeJobsLimit
          - teamSeatLimit
          - canBePublic
          - canRemoveBranding
          - apiAccess
          description: The plan capability that blocked the request, named as in `GET /v1/billing/subscription` `capabilities`.
        requiredPlan:
          type: string
          enum:
          - starter
          - basic
          - grow
          - advanced
          - scale
          description: The cheapest self-serve plan that unlocks the action. Pass it as `planKey`. Omitted when it cannot be told without more information; read `GET /v1/billing/subscription` and pick a higher plan.
        checkout:
          type: object
          properties:
            method:
              type: string
              enum:
              - POST
            path:
              type: string
              enum:
              - /v1/billing/checkout
          required:
          - method
          - path
          description: Starts a hosted checkout when the board has no active subscription (for example during a trial).
        changePlan:
          type: object
          properties:
            method:
              type: string
              enum:
              - POST
            path:
              type: string
              enum:
              - /v1/billing/upgrade
          required:
          - method
          - path
          description: Starts a hosted plan change when the board already has an active subscription.
      required:
      - capability
      - checkout
      - changePlan
      description: 'Present only on Operator API errors caused by the board''s Cavuno plan. Read `GET /v1/billing/subscription` to choose between `checkout` and `changePlan`, call it with `{ "planKey": requiredPlan }`, and give the returned `url` to a person to confirm. Each `path` is relative to the API origin, not to a `/v1` base URL. Both endpoints need `billing.manage`. Board API errors never include it.'
    BillingConnectOnboardingLink:
      type: object
      properties:
        object:
          type: string
          enum:
          - billing_connect_onboarding_link
        url:
          type: string
          format: uri
          description: Single-use hosted Stripe onboarding URL. Hand it to a human straight away; it expires within minutes.
        expiresAt:
          type: string
          format: date-time
          description: ISO 8601 time after which the URL no longer works.
      required:
      - object
      - url
      - expiresAt
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Machine-readable error code, such as `validation_bad_request` or `jobs_not_found`.
            message:
              type: string
              description: Human-readable explanation.
            requestId:
              type: string
              description: Unique id for this request. Include it when contacting support.
            details:
              description: Structured context for some errors, such as per-field validation issues.
            upgrade:
              $ref: '#/components/schemas/PlanUpgradeHint'
          required:
          - code
          - message
          - requestId
      required:
      - error
      description: The error envelope returned by every non-2xx response.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: cavuno_live_<keyId>_<secret>
      description: Use your secret API key to authenticate. Pass it as a Bearer token in the `Authorization` header. You can view and manage your API keys in the Cavuno dashboard.
externalDocs:
  description: Cavuno API reference
  url: https://cavuno.com/docs/api