Chronary Billing API

The Billing API from Chronary — 5 operation(s) for billing.

Operations 5

GET /v1/billing Get billing status #
POST /v1/billing/upgrade-requests Ask a human to upgrade to Pro #
GET /v1/billing/upgrade-requests/{id} Get an upgrade request #
POST /v1/billing/upgrade-requests/{id}/cancel Cancel an upgrade request #
POST /v1/billing/upgrade-requests/{id}/decline Decline an upgrade request (console only) #

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/chronary-ai:chronary-ai-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

chronary-ai-billing-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Chronary Billing API
  version: 1.0.0
  description: 'Calendar-as-a-service API for AI agents.


    Manage calendars, events, and availability for AI and human agents.

    All endpoints require an API key passed as a Bearer token.


    **Authentication:** `Authorization: Bearer chr_sk_...` or `Authorization: Bearer chr_ak_...`


    **Rate limit:** 10 requests/second per API key. Exceeds return HTTP 429.


    **Quotas:** Monthly operation limits by plan — see Billing & plans and Rate limits.


    **Agent bootstrap:** Custom extensions prefixed `x-agent-*` describe the self-signup flow for AI agents. These are not part of any registered OpenAPI extension — they are a Chronary convention.'
  contact:
    name: Chronary Support
    email: support@chronary.ai
    url: https://docs.chronary.ai
servers:
- url: https://api.chronary.ai
  description: Production
security:
- BearerAuth: []
tags:
- name: Billing
paths:
  /v1/billing:
    get:
      operationId: getBilling
      summary: Get billing status
      description: Plan, subscription status, renewal or cancellation date, Pro pricing and any pending upgrade request. Never contains payment-provider ids. Works even when the org has hit its usage limit. Org-level API keys or a console session; agent-scoped keys receive 403.
      tags:
      - Billing
      responses:
        '200':
          description: Billing summary
          headers:
            X-Chronary-Plan:
              description: The current plan of the authenticated organization (free | pro | scale)
              schema:
                type: string
                enum:
                - free
                - pro
                - scale
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingSummary'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden — quota exceeded or operation not permitted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/billing/upgrade-requests:
    post:
      operationId: createUpgradeRequest
      summary: Ask a human to upgrade to Pro
      description: 'Creates an upgrade request and emails the account owner. Give `approval_url` to your human — only a human can pay. At most one request is pending per org: a repeat call returns it with `reused: true` (200). Poll `GET /v1/billing/upgrade-requests/{id}` at most once a minute. Org-level API keys only; signed-in humans use the console Billing page instead. Honors `Idempotency-Key`.'
      tags:
      - Billing
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUpgradeRequest'
      responses:
        '200':
          description: 'A pending request already existed (`reused: true`)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpgradeRequest'
        '201':
          description: Upgrade request created; the owner is notified
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpgradeRequest'
        '400':
          description: Validation error — invalid request body or query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Agent-scoped key, console session (`use_billing_page`), or unverified email (`email_verification_required`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: '`already_subscribed`, `unsupported_plan` (with `contact_url`), `founding_offer_pending` (early-access account — the founding offer opens at launch), or `upgrade_request_recently_declined` (with `retry_after`)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: '`upgrade_request_limit` — at most 3 new requests per 24 hours (with `retry_after`)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Billing is not configured on this environment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/billing/upgrade-requests/{id}:
    get:
      operationId: getUpgradeRequest
      summary: Get an upgrade request
      description: Poll at most once a minute. After `completed`, wait about 15 seconds before retrying the call that hit the plan limit.
      tags:
      - Billing
      parameters:
      - schema:
          type: string
          example: upr_V1StGXR8Z5jd
          description: Upgrade request ID
        required: true
        description: Upgrade request ID
        name: id
        in: path
      responses:
        '200':
          description: Upgrade request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpgradeRequest'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden — quota exceeded or operation not permitted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/billing/upgrade-requests/{id}/cancel:
    post:
      operationId: cancelUpgradeRequest
      summary: Cancel an upgrade request
      description: Withdraw a pending upgrade request.
      tags:
      - Billing
      parameters:
      - schema:
          type: string
          example: upr_V1StGXR8Z5jd
          description: Upgrade request ID
        required: true
        description: Upgrade request ID
        name: id
        in: path
      responses:
        '200':
          description: Upgrade request canceled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpgradeRequest'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden — quota exceeded or operation not permitted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: The request is no longer pending — `error.status` carries its current status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /v1/billing/upgrade-requests/{id}/decline:
    post:
      operationId: declineUpgradeRequest
      summary: Decline an upgrade request (console only)
      description: 'Human-only: requires a console session and the `X-Chronary-CSRF: 1` header. API keys receive 403 `human_only`. A decline blocks new requests from the org for 72 hours.'
      tags:
      - Billing
      security:
      - SessionAuth: []
      parameters:
      - schema:
          type: string
          example: upr_V1StGXR8Z5jd
          description: Upgrade request ID
        required: true
        description: Upgrade request ID
        name: id
        in: path
      responses:
        '200':
          description: Upgrade request declined
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpgradeRequest'
        '401':
          description: Missing or invalid console session — these endpoints require a console JWT, not an API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden — quota exceeded or operation not permitted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: The request is no longer pending — `error.status` carries its current status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    BillingSummary:
      type: object
      properties:
        plan:
          type: string
          example: free
        plan_source:
          type:
          - string
          - 'null'
        plan_expires_at:
          type:
          - string
          - 'null'
          format: date-time
        status:
          type:
          - string
          - 'null'
          description: Subscription status (active, trialing, past_due, canceled, …); null if never subscribed
        interval:
          type:
          - string
          - 'null'
          enum:
          - month
          - year
          - null
          example: month
        current_period_end:
          type:
          - string
          - 'null'
          format: date-time
        cancel_at:
          type:
          - string
          - 'null'
          format: date-time
          description: When a scheduled cancellation takes effect
        cancel_at_period_end:
          type: boolean
        renews_at:
          type:
          - string
          - 'null'
          format: date-time
        price:
          type:
          - object
          - 'null'
          properties:
            amount:
              type: integer
              example: 2900
            currency:
              type: string
              example: usd
            interval:
              type: string
              enum:
              - month
              - year
              example: month
            tax_exclusive:
              type: boolean
              enum:
              - true
          required:
          - amount
          - currency
          - interval
          - tax_exclusive
        has_billing_account:
          type: boolean
        self_serve_upgrade:
          type: boolean
        upgrade_options:
          type: array
          items:
            type: object
            properties:
              plan:
                type: string
                enum:
                - pro
              interval:
                type: string
                enum:
                - month
                - year
                example: month
              amount:
                type: integer
                example: 2900
                description: Minor units (cents)
              currency:
                type: string
                example: usd
              savings_vs_monthly:
                type: integer
                example: 0
            required:
            - plan
            - interval
            - amount
            - currency
            - savings_vs_monthly
        upgrade_url:
          type:
          - string
          - 'null'
        manage_url:
          type: string
        contact_url:
          type:
          - string
          - 'null'
        pending_upgrade_request:
          allOf:
          - $ref: '#/components/schemas/UpgradeRequest'
          - type:
            - object
            - 'null'
        offer:
          allOf:
          - $ref: '#/components/schemas/BillingOffer'
          - type:
            - object
            - 'null'
            description: Founding-member offer for early-access accounts; null otherwise
      required:
      - plan
      - plan_source
      - plan_expires_at
      - status
      - interval
      - current_period_end
      - cancel_at
      - cancel_at_period_end
      - renews_at
      - price
      - has_billing_account
      - self_serve_upgrade
      - upgrade_options
      - upgrade_url
      - manage_url
      - contact_url
      - pending_upgrade_request
      - offer
    CreateUpgradeRequest:
      type: object
      properties:
        interval:
          type: string
          enum:
          - month
          - year
          example: month
          description: Defaults to month
        reason:
          type: string
          maxLength: 500
          example: Need scoped keys for the support agents.
        feature:
          type: string
          example: scoped_keys
          description: The `feature` from a plan_required error
        metric:
          type: string
          example: api_calls
          description: The `metric` from a quota error
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            type:
              type: string
              example: invalid_request
            message:
              type: string
              example: The field "name" is required.
            request_id:
              type: string
              example: req_01H9X4M2P5R8T6V0
            required_plan:
              type: string
              example: pro
              description: 'plan_required: the plan that unlocks the feature'
            feature:
              type: string
              description: 'plan_required: the gated feature'
            metric:
              type: string
              description: 'quota_exceeded and count caps: the metric at its limit (a PLAN_LIMITS key, accepted by POST /v1/billing/upgrade-requests)'
            limit:
              type: integer
              description: 'quota_exceeded and count caps: the plan''s limit for `metric`'
            upgrade_url:
              type: string
              description: Where a human upgrades the plan
            docs_url:
              type: string
            contact_url:
              type: string
              description: 'Contract-managed plans: where to contact sales'
            retry_after:
              type: integer
              description: Seconds until the request may be retried
          required:
          - type
          - message
          - request_id
      required:
      - error
    BillingOffer:
      type: object
      properties:
        kind:
          type: string
          enum:
          - founding
        status:
          type: string
          enum:
          - upcoming
          - available
          - redeemed
          description: '`upcoming` — early-access account; the offer opens at launch (checkout returns 409 `founding_offer_pending` until then). `available` — free Pro until `ends_at`; subscribe before then at the founding discount. `redeemed` — the subscription was created on founding terms.'
        ends_at:
          type:
          - string
          - 'null'
          format: date-time
          description: 'available: when free Pro and the offer end'
        trial_until:
          type:
          - string
          - 'null'
          format: date-time
          description: 'available: billing starts on this date if you subscribe now (null in the last ~2 days: billing starts at checkout). redeemed: trial end while trialing.'
        discount_percent:
          type:
          - integer
          - 'null'
          example: 50
        discount_months:
          type:
          - integer
          - 'null'
          example: 12
          description: 'Paid months the discount covers (annual: the first year)'
        renewal_consent:
          type:
          - string
          - 'null'
          enum:
          - required
          - given
          - null
          description: 'redeemed: `required` while a trial with a Washington DC billing address waits for the human to choose "Continue to paid Pro" on the console Billing page (otherwise the subscription ends at the trial end, with no charge); `given` once they have. Null otherwise. Agents cannot give this consent.'
      required:
      - kind
      - status
      - ends_at
      - trial_until
      - discount_percent
      - discount_months
      - renewal_consent
    UpgradeRequest:
      type: object
      properties:
        id:
          type: string
          example: upr_V1StGXR8Z5jd
        status:
          type: string
          enum:
          - pending
          - completed
          - declined
          - canceled
          - expired
          example: pending
        plan:
          type: string
          enum:
          - pro
        interval:
          type: string
          enum:
          - month
          - year
          example: month
        reason:
          type:
          - string
          - 'null'
          description: Note from the agent, shown to the human as plain text on the approval page. Never emailed.
        feature:
          type:
          - string
          - 'null'
          example: scoped_keys
          description: Pro feature that triggered the request
        metric:
          type:
          - string
          - 'null'
          example: null
          description: Usage limit that triggered the request
        requested_via:
          type: string
          enum:
          - api
          - mcp
        requested_by_key_prefix:
          type:
          - string
          - 'null'
          description: First 20 characters of the requesting key; never the full key
        approval_url:
          type:
          - string
          - 'null'
          example: https://console.chronary.ai/settings/billing/requests/upr_V1StGXR8Z5jd
          description: Give this to your human. Null once the request is no longer pending.
        created_at:
          type: string
          format: date-time
        expires_at:
          type: string
          format: date-time
          description: Pending requests expire 7 days after creation
        completed_at:
          type:
          - string
          - 'null'
          format: date-time
        declined_at:
          type:
          - string
          - 'null'
          format: date-time
        canceled_at:
          type:
          - string
          - 'null'
          format: date-time
        owner_notification:
          type: string
          enum:
          - queued
          - not_configured
          - skipped_internal
          - already_notified
          description: Create responses only — whether the account owner was emailed
        reused:
          type: boolean
          description: Create responses only — true when a pending request already existed; do not create again
      required:
      - id
      - status
      - plan
      - interval
      - reason
      - feature
      - metric
      - requested_via
      - requested_by_key_prefix
      - approval_url
      - created_at
      - expires_at
      - completed_at
      - declined_at
      - canceled_at
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: 'API key with `chr_sk_*` for org-level access or `chr_ak_*` for agent-scoped access. Pass in the Authorization header: `Authorization: Bearer chr_sk_...`'
    SessionAuth:
      type: apiKey
      in: cookie
      name: chronary_session
      description: Console session JWT (HS256), issued by sign-in and sent as the `chronary_session` cookie (a Bearer JWT is also accepted). This is NOT a chr_sk_*/chr_ak_* API key — API keys are rejected with 401 on these endpoints.
x-agent-self-signup:
  url: https://api.chronary.ai/v1/agent/sign-up
  verify_url: https://api.chronary.ai/v1/agent/verify
  restricted_key_returned: true
  human_in_the_loop: otp_email
  rate_limit: 5 requests per 60s per client IP
x-agent-bootstrap-script:
  npx: npx @chronary/agent-init@latest
  shell: https://chronary.ai/agent-init.sh
  description: One-liner that performs sign-up, prompts for OTP, verifies, and creates a smoke calendar. Accepts CHRONARY_EMAIL and CHRONARY_OTP env vars for non-interactive flows.
x-llms-txt: https://docs.chronary.ai/llms.txt
x-llms-full-txt: https://docs.chronary.ai/llms-full.txt
x-mcp-server-card: https://chronary.ai/.well-known/mcp/server-card.json
x-api-catalog: https://chronary.ai/.well-known/api-catalog