Scribiz Billing API

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

GitHub OpenAPI

Operations 5

POST /v1/billing/checkout Start a purchase #
POST /v1/billing/checkout/confirm Confirm a purchase after Stripe sends the buyer back #
GET /v1/billing/offer What is on sale #
POST /v1/billing/portal Open the billing portal #
POST /v1/billing/webhook Stripe's events #

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/scribiz:scribiz-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

scribiz-billing-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Scribiz Billing API
  version: 1.0.0
  description: 'Operations tagged Billing across 2 of this provider''s published API definitions: openapi.json, scribiz-openapi.json. Each path carries the servers of the definition it was published in.'
servers:
- description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
  url: https://scribiz.com/api
tags:
- name: Billing
paths:
  /v1/billing/checkout:
    post:
      description: 'Start a purchase with Stripe. Needs a signed-in session (a browser session or the session token of the device flow), not an API key. Send a plan name and nothing else: the price, the amount and the URLs are decided by the server, and a body with any other field is refused. The answer is the Stripe Checkout URL to send the buyer to; it is always a URL on stripe.com that Stripe returned. Until the owner switches payments on, and for any plan with no price set, this answers 501 `billing_not_configured`. 409 `not_on_sale` (set up but not open to the public), `already_owned` (Mac Lifetime is already on the account) or `already_subscribed` (Pro is already running: the error has `portal: true`). At most 10 starts an hour per account.'
      operationId: billingCheckout
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckoutRequest'
        description: JSON
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CheckoutStarted'
          description: The Checkout page to send the buyer to.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: session_required, bad_origin
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: not_on_sale, already_owned, already_subscribed
        '413':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: body_too_large
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: 'invalid_request: the plan, interval or pack is not valid (`error.field` says which).'
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: rate_limited
        '501':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: 'billing_not_configured: paid plans are not open for purchase yet.'
        '502':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: 'stripe_unavailable: nothing was charged.'
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: billing_misconfigured, busy
      security:
      - apiKey: []
      - bearer: []
      - cookie: []
      - {}
      summary: Start a purchase
      tags:
      - Billing
    servers:
    - description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
      url: https://scribiz.com/api
  /v1/billing/checkout/confirm:
    post:
      description: 'After the buyer comes back from Stripe: apply the purchase now when the webhook is late. Idempotent. A Stripe failure is `pending`, never an error. Only for the account that started that checkout (anything else is 404). At most 120 an hour per account.'
      operationId: billingCheckoutConfirm
      requestBody:
        content:
          application/json:
            schema:
              additionalProperties: false
              properties:
                sessionId:
                  description: The `cs_...` id from the success URL.
                  type: string
              required:
              - sessionId
              type: object
        description: JSON
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CheckoutConfirmed'
          description: Where the purchase stands.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: session_required, bad_origin
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: not_found
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: invalid_request
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: rate_limited
        '501':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: billing_not_configured
      security:
      - apiKey: []
      - bearer: []
      - cookie: []
      - {}
      summary: Confirm a purchase after Stripe sends the buyer back
      tags:
      - Billing
    servers:
    - description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
      url: https://scribiz.com/api
  /v1/billing/offer:
    get:
      description: 'What can be bought right now, with the prices. Public. `plans` holds only what the caller can buy: with nothing on sale it is empty (`configured: false` while payments are not set up at all). A signed-in preview account also sees a configured plan that is not public yet, marked `preview: true`. `mac-lifetime.amount` is what the next buyer pays (the early bird price while a place is left, otherwise the list price). Amounts are USD cents. Cached for 15 seconds for anonymous callers; at most 60 requests a minute per visitor.'
      operationId: billingOffer
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingOffer'
          description: The offer.
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: rate_limited
      security:
      - apiKey: []
      - bearer: []
      - cookie: []
      - {}
      summary: What is on sale
      tags:
      - Billing
    servers:
    - description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
      url: https://scribiz.com/api
  /v1/billing/portal:
    post:
      description: Open Stripe's billing portal for the account (receipts, card, cancelling Pro). Needs a signed-in session, not an API key. The answer is a short-lived stripe.com URL. 409 `no_billing_account` when the account has never started a checkout. At most 20 an hour per account.
      operationId: billingPortal
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  url:
                    type: string
                required:
                - url
                type: object
          description: The portal URL.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: session_required, bad_origin
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: no_billing_account
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: rate_limited
        '501':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: billing_not_configured
        '502':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: stripe_unavailable
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: billing_misconfigured
      security:
      - apiKey: []
      - bearer: []
      - cookie: []
      - {}
      summary: Open the billing portal
      tags:
      - Billing
    servers:
    - description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
      url: https://scribiz.com/api
  /v1/billing/webhook:
    post:
      description: For Stripe only. Stripe signs every call (`Stripe-Signature`, HMAC-SHA256 over the timestamp and the raw body, five minute window) and a call without a good signature is refused with 400 before anything is read. No account, key or cookie is involved and nothing here is for programs. 501 `billing_not_configured` while payments are not set up.
      operationId: billingWebhook
      requestBody:
        content:
          application/json:
            schema:
              type: object
        description: A Stripe event.
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  received:
                    const: true
                type: object
          description: Received.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: invalid_signature, invalid_payload
        '413':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: body_too_large
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: 'rate_limited: too many bad signatures from one address.'
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: 'retry_later: not handled yet, Stripe sends it again.'
        '501':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: billing_not_configured
        '503':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: busy
      summary: Stripe's events
      tags:
      - Billing
    servers:
    - description: 'The one public base for every client: https://scribiz.com/api (Better Auth at /api/auth, remote MCP at https://scribiz.com/mcp). The proxy routes both paths to this API.'
      url: https://scribiz.com/api
components:
  schemas:
    CheckoutConfirmed:
      properties:
        captionCredits:
          description: Caption wallet balance for a caption purchase; null for other purchases.
          type:
          - integer
          - 'null'
        kind:
          enum:
          - pro
          - mac-lifetime
          - topup
        lifetimeMac:
          type: boolean
        minutesTopup:
          type: number
        paid:
          description: 'True when Stripe says the checkout was paid. A `pending` state with `paid: false` is not a payment (the checkout is still open, or Stripe could not be asked): do not tell the buyer one went through.'
          type: boolean
        plan:
          enum:
          - free
          - pro
          - lifetime
        planUntil:
          type:
          - number
          - 'null'
        state:
          enum:
          - active
          - pending
          - expired
          - failed
      required:
      - state
      - kind
      - plan
      - planUntil
      - lifetimeMac
      - minutesTopup
      - paid
      type: object
    Error:
      properties:
        error:
          additionalProperties: true
          properties:
            code:
              description: snake_case.
              type: string
            engineCode:
              description: The engine's own code (QUOTA, SOURCE_UNAVAILABLE, ...) when there is one.
              type: string
            hint:
              type: string
            message:
              type: string
          required:
          - code
          - message
          type: object
      required:
      - error
      type: object
    CheckoutRequest:
      additionalProperties: false
      properties:
        datafastSessionId:
          type: string
        datafastVisitorId:
          type: string
        interval:
          description: Pro only. Default month.
          enum:
          - month
          - year
        pack:
          description: Extra minutes only.
          enum:
          - small
          - medium
          - large
        plan:
          enum:
          - pro
          - mac-lifetime
          - topup
        ref:
          description: Where the visitor came from (1 to 40 of a-z, 0-9, dot, dash, underscore).
          type: string
      required:
      - plan
      type: object
    CheckoutStarted:
      properties:
        amount:
          description: 'What this Checkout page charges, in cents, before tax: the price the buyer will see there. Compare it with the price the page showed before sending the buyer on.'
          type: integer
        currency:
          description: Lower case ISO code, `usd`.
          type: string
        earlyBird:
          description: True when the page is at the Mac Lifetime early bird price.
          type: boolean
        expiresAt:
          description: Epoch milliseconds.
          type: number
        sessionId:
          type: string
        url:
          description: A Stripe Checkout URL.
          type: string
      required:
      - url
      - sessionId
      - expiresAt
      - amount
      - currency
      - earlyBird
      type: object
    BillingOffer:
      properties:
        configured:
          description: False while payments are not set up at all.
          type: boolean
        plans:
          description: Only what the caller can buy now. Empty when nothing is on sale.
          properties:
            mac-lifetime:
              properties:
                amount:
                  description: What the next buyer pays, in cents.
                  type: integer
                buyers:
                  description: Paid purchases, net of refunds and disputes.
                  type: integer
                currency:
                  const: usd
                earlyBird:
                  properties:
                    left:
                      type: integer
                    places:
                      type: integer
                  type:
                  - object
                  - 'null'
                listAmount:
                  type: integer
                preview:
                  type: boolean
              type: object
            pro:
              properties:
                intervals:
                  items:
                    properties:
                      amount:
                        type: integer
                      currency:
                        const: usd
                      interval:
                        enum:
                        - month
                        - year
                    type: object
                  type: array
                preview:
                  type: boolean
              type: object
            topup:
              properties:
                captionPacks:
                  items:
                    properties:
                      amount:
                        type: integer
                      captions:
                        type: integer
                      currency:
                        const: usd
                      id:
                        enum:
                        - captions-200
                        - captions-1200
                        - captions-5000
                    type: object
                  type: array
                packs:
                  items:
                    properties:
                      amount:
                        type: integer
                      currency:
                        const: usd
                      id:
                        enum:
                        - small
                        - medium
                        - large
                      minutes:
                        type: integer
                    type: object
                  type: array
                preview:
                  type: boolean
              type: object
          type: object
        signInRequired:
          type: boolean
        taxAtCheckout:
          type: boolean
      required:
      - configured
      - signInRequired
      - taxAtCheckout
      - plans
      type: object
  securitySchemes:
    apiKey:
      description: 'An API key (sbz_live_...), as X-API-Key. Keys are made in the dashboard or by `scribiz login`. Each key has one scope, named in an operation''s security requirement. `all`: Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read. `mcp`: The remote MCP server at /mcp. Includes read. `read`: Read jobs and their events.'
      in: header
      name: X-API-Key
      type: apiKey
      x-scopes:
        all: 'Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read.'
        mcp: The remote MCP server at /mcp. Includes read.
        read: Read jobs and their events.
    bearer:
      description: 'An API key (sbz_live_...) or a session token from the device flow. Each key has one scope, named in an operation''s security requirement. `all`: Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read. `mcp`: The remote MCP server at /mcp. Includes read. `read`: Read jobs and their events. A session token has every scope.'
      scheme: bearer
      type: http
      x-scopes:
        all: 'Everything a key can do: start jobs, upload, ask, cancel, the Gemini proxy and listing keys. Includes read.'
        mcp: The remote MCP server at /mcp. Includes read.
        read: Read jobs and their events.
    cookie:
      description: The browser session (same-origin /api/*).
      in: cookie
      name: better-auth.session_token
      type: apiKey
x-refined-from:
- openapi.json
- scribiz-openapi.json