Indraft Billing API

The billing API from Indraft — 3 operation(s) for billing.

GitHub OpenAPI

Operations 3

GET /billing/usage Plan, subscription status, and usage against every quota #
POST /billing/checkout Start a Stripe Checkout session for a plan #
POST /billing/portal Open the Stripe Customer Portal #

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/indraft-io:indraft-io-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

indraft-io-billing-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Indraft Io Billing API
  version: '1'
  description: 'Operations tagged billing across 2 of this provider''s published API definitions: indraft-io-openapi.json, indraft-io.json. Each path carries the servers of the definition it was published in.'
servers:
- url: https://api.indraft.io
security:
- bearerAuth: []
tags:
- name: Billing
paths:
  /billing/usage:
    get:
      summary: Plan, subscription status, and usage against every quota
      description: 'Plan, subscription state, and usage against every quota, served from the control plane rather than the workspace. That separation is deliberate: billing state has to be readable when a workspace is at its storage ceiling, and checking whether you are over budget must not consume the budget.'
      tags:
      - Billing
      operationId: get_billing_usage
      x-indraft-capability: crm:read
      x-indraft-scopes:
      - crm:read
      - crm:write
      - crm:configure
      - crm:admin
      - crm:revert
      - data:export
      responses:
        '200':
          description: Success
          headers:
            ratelimit-limit:
              description: Requests permitted in the window closest to refusing this caller.
              schema:
                type: integer
            ratelimit-remaining:
              description: Requests left in that window. Zero means the next request is refused.
              schema:
                type: integer
            ratelimit-reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            ratelimit-policy:
              description: Every window in force, not only the one reported above.
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                properties:
                  plan:
                    type: string
                  status:
                    type: string
                  metrics:
                    type: array
                    items:
                      type: object
                      properties:
                        metric:
                          type: string
                        used:
                          type: integer
                        limit:
                          type: integer
                      required:
                      - metric
                      - used
                      - limit
                      additionalProperties: true
                  activity:
                    type: object
                    properties:
                      interactions:
                        type: integer
                      tasks:
                        type: integer
                    required:
                    - interactions
                    - tasks
                    additionalProperties: true
                  capacity:
                    type: object
                    properties:
                      bytes:
                        type: integer
                      ceilingBytes:
                        type: integer
                      fractionUsed:
                        type: integer
                      warning:
                        type: string
                        enum:
                        - none
                        - approaching
                        - critical
                      operatorAlert:
                        type: boolean
                      projection:
                        type: object
                        properties:
                          observedDays:
                            type: integer
                          bytesPerDay:
                            type: integer
                          monthsToCeiling:
                            type: integer
                          reachesCeilingAt:
                            type: string
                        required:
                        - observedDays
                        - bytesPerDay
                        - monthsToCeiling
                        - reachesCeilingAt
                        additionalProperties: true
                      indexedRecords:
                        type: integer
                    required:
                    - bytes
                    - ceilingBytes
                    - fractionUsed
                    - warning
                    - operatorAlert
                    - projection
                    additionalProperties: true
                  overage:
                    type: object
                    properties:
                      pooled:
                        type: object
                        properties:
                          records:
                            type: integer
                          changes:
                            type: integer
                        required:
                        - records
                        - changes
                        additionalProperties: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            metric:
                              type: string
                              enum:
                              - records
                              - changes
                            over:
                              type: integer
                            blocks:
                              type: integer
                            blockSize:
                              type: integer
                            perBlockMinor:
                              type: integer
                            amountMinor:
                              type: integer
                          required:
                          - metric
                          - over
                          - blocks
                          - blockSize
                          - perBlockMinor
                          - amountMinor
                          additionalProperties: true
                      seatsMinor:
                        type: integer
                      totalMinor:
                        type: integer
                      cappedTo:
                        type: string
                      savedMinor:
                        type: integer
                    required:
                    - pooled
                    - lines
                    - seatsMinor
                    - totalMinor
                    - cappedTo
                    - savedMinor
                    additionalProperties: true
                required:
                - plan
                - status
                - metrics
                additionalProperties: true
        '401':
          description: No credential, or one that has been revoked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Authenticated, and this capability is not held.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Infrastructure protection tripped. This is not a product quota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers:
            ratelimit-limit:
              description: Requests permitted in the window closest to refusing this caller.
              schema:
                type: integer
            ratelimit-remaining:
              description: Requests left in that window. Zero means the next request is refused.
              schema:
                type: integer
            ratelimit-reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            ratelimit-policy:
              description: Every window in force, not only the one reported above.
              schema:
                type: string
            retry-after:
              description: Seconds to wait before retrying. The request itself was fine.
              schema:
                type: integer
        '500':
          description: A defect on our side. The hint says so, and carries an incident id.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    servers:
    - url: https://api.indraft.io
  /billing/checkout:
    post:
      summary: Start a Stripe Checkout session for a plan
      description: Starts a Stripe Checkout session and returns the URL to send the customer to. No card details reach Indraft at any point, and no CRM record reaches Stripe.
      tags:
      - Billing
      operationId: post_billing_checkout
      x-indraft-capability: billing:manage
      x-indraft-scopes: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                plan:
                  type: string
                  enum:
                  - solo
                  - team
                  - scale
                  - business
                interval:
                  type: string
                  enum:
                  - month
                  - year
              required:
              - plan
              additionalProperties: false
      responses:
        '200':
          description: Success
          headers:
            ratelimit-limit:
              description: Requests permitted in the window closest to refusing this caller.
              schema:
                type: integer
            ratelimit-remaining:
              description: Requests left in that window. Zero means the next request is refused.
              schema:
                type: integer
            ratelimit-reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            ratelimit-policy:
              description: Every window in force, not only the one reported above.
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                required:
                - url
                additionalProperties: true
        '401':
          description: No credential, or one that has been revoked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: A product quota is spent, or the subscription is not active.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Authenticated, and this capability is not held.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: 'A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '413':
          description: The body, or a single record inside it, exceeds its bound.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: The request does not satisfy the schema on this page.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Infrastructure protection tripped. This is not a product quota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers:
            ratelimit-limit:
              description: Requests permitted in the window closest to refusing this caller.
              schema:
                type: integer
            ratelimit-remaining:
              description: Requests left in that window. Zero means the next request is refused.
              schema:
                type: integer
            ratelimit-reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            ratelimit-policy:
              description: Every window in force, not only the one reported above.
              schema:
                type: string
            retry-after:
              description: Seconds to wait before retrying. The request itself was fine.
              schema:
                type: integer
        '500':
          description: A defect on our side. The hint says so, and carries an incident id.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '507':
          description: The workspace is at its storage ceiling.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    servers:
    - url: https://api.indraft.io
  /billing/portal:
    post:
      summary: Open the Stripe Customer Portal
      description: 'Opens the Stripe Customer Portal, where a customer changes their card, reads invoices, or cancels. Cancelling there is the whole path: there is no retention flow to get through.'
      tags:
      - Billing
      operationId: post_billing_portal
      x-indraft-capability: billing:manage
      x-indraft-scopes: []
      responses:
        '200':
          description: Success
          headers:
            ratelimit-limit:
              description: Requests permitted in the window closest to refusing this caller.
              schema:
                type: integer
            ratelimit-remaining:
              description: Requests left in that window. Zero means the next request is refused.
              schema:
                type: integer
            ratelimit-reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            ratelimit-policy:
              description: Every window in force, not only the one reported above.
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                properties:
                  url:
                    type: string
                required:
                - url
                additionalProperties: true
        '401':
          description: No credential, or one that has been revoked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: A product quota is spent, or the subscription is not active.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Authenticated, and this capability is not held.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: 'A conflict the caller can resolve: a stale expectedVersion, an idempotency key reused for different input, an ambiguous or duplicate identity, or a merge that no longer applies.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Infrastructure protection tripped. This is not a product quota.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers:
            ratelimit-limit:
              description: Requests permitted in the window closest to refusing this caller.
              schema:
                type: integer
            ratelimit-remaining:
              description: Requests left in that window. Zero means the next request is refused.
              schema:
                type: integer
            ratelimit-reset:
              description: Seconds until that window resets.
              schema:
                type: integer
            ratelimit-policy:
              description: Every window in force, not only the one reported above.
              schema:
                type: string
            retry-after:
              description: Seconds to wait before retrying. The request itself was fine.
              schema:
                type: integer
        '500':
          description: A defect on our side. The hint says so, and carries an incident id.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '507':
          description: The workspace is at its storage ceiling.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
    servers:
    - url: https://api.indraft.io
components:
  schemas:
    ErrorDetail:
      type: object
      additionalProperties: true
      description: The structured payload a recovery needs. Its shape differs per code; the keys below are the ones that recur, and anything else a code carries is present alongside them.
      properties:
        fieldErrors:
          type: object
          additionalProperties:
            type: string
          description: One message per field the caller sent, keyed by that field. The key `(body)` is the request body itself, which is what an unrecognised key reports under.
        reason:
          type: string
          description: One sentence, where the refusal is about the request rather than a field. A refusal that names alternatives puts them here.
        available:
          type: array
          items:
            type: string
          description: What could have been asked for instead. Present on a filter, sort or group-by the API does not serve, so a correction is one edit rather than a round trip to read the schema.
        options:
          type: array
          items:
            type: string
          description: The values an enum accepts, on a value it does not.
        currentVersion:
          type: integer
          description: What the record's version actually is, on `stale_version`. With the value you sent it is everything needed to decide whether to re-read and retry or to stop.
        expectedVersion:
          type: integer
          description: The version you sent, echoed back on `stale_version`.
        requiredScope:
          type: string
          description: 'The capability the credential lacks. Empty nowhere: a route no credential can reach is human-only and says so in its scopes instead.'
    Error:
      type: object
      required:
      - code
      - message
      - recoveryHint
      - requestId
      properties:
        code:
          type: string
          enum:
          - unauthorized
          - forbidden_scope
          - standing_override_refused
          - workspace_not_found
          - validation_error
          - record_not_found
          - ambiguous_identity
          - duplicate_identity
          - stale_version
          - invalid_stage_transition
          - idempotency_conflict
          - not_reversible
          - merge_conflict
          - rate_limited
          - quota_exceeded
          - payload_too_large
          - workspace_capacity
          - payment_required
          - billing_state_stale
          - operation_in_flight
          - internal_error
        message:
          type: string
        recoveryHint:
          type: string
        requestId:
          type: string
        detail:
          $ref: '#/components/schemas/ErrorDetail'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: An Indraft API token, or a WorkOS-issued session or MCP access token.
x-refined-from:
- indraft-io-openapi.json
- indraft-io.json