Skip to content

Billing & usage

Subscription plans, Stripe checkout, payment history, cancellation, and per-user LLM spend. Billing endpoints are only mounted on hosted deployments (ON_PREMISE_MODE off).

Endpoints

MethodPathPurpose
GET/subscriptions/plans/Available plans
POST/subscriptions/checkout-session/Start a Stripe checkout
POST/subscriptions/cancel/Cancel my subscription
GET/subscriptions/history/Payment history
GET/microservices/cost-tracker/users/{username}/costsMy LLM usage and cost

GET /subscriptions/plans/

Available plans

Auth: Session token · In the app: Plans page

Response 200 — Plans (hidden plans excluded).

Array of:

FieldTypeDescription
idinteger
codestringStable key used for checkout and UI theming.
namestring
monthly_pricenumber
yearly_pricenumber
trial_daysinteger
monthly_workflow_runsinteger, nullablenull = unlimited.
included_tokensinteger, nullable
storage_bytesinteger, nullable
run_history_daysinteger, nullable
live_build_sessionsinteger, nullable
featuresobjectFeature flags keyed by feature name.
support_tierstring
is_self_servebooleanfalse = contact sales; checkout refuses it.

Example

bash
curl -X GET "https://api.example.com/subscriptions/plans/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /subscriptions/checkout-session/

Start a Stripe checkout

Creates a Stripe Checkout session for a self-serve plan and returns its URL; redirect the user there. Stripe redirects back to the app's payment-success / payment-cancel pages. The subscription is activated by Stripe's webhook, not by the redirect.

Auth: Session token · In the app: Plans → Subscribe

Request body (application/json)

FieldTypeRequiredDescription
plan_codestringnoPlan code (preferred).
plan_idintegernoLegacy alternative to plan_code.
intervalstring ("monthly", "yearly")noDefault: "monthly".
quantityintegernoSeats. Default: 1.
json
{
  "plan_code": "pro",
  "interval": "yearly"
}

Response 200 — Checkout URL.

FieldTypeDescription
urlstring (uri)
json
{
  "url": "https://checkout.stripe.com/c/pay/cs_test_…"
}

Response 400 — Bad interval, non-self-serve plan, or no Stripe price for that interval.

json
{
  "error": "path is required"
}

Response 404 — Unknown plan.

Example

bash
curl -X POST "https://api.example.com/subscriptions/checkout-session/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"plan_code":"pro","interval":"yearly"}'

POST /subscriptions/cancel/

Cancel my subscription

Cancels the Stripe subscription immediately and marks the local subscription inactive.

Auth: Session token · In the app: Profile → Billing → Cancel

Response 200 — Cancelled.

FieldTypeDescription
messagestring
json
{
  "message": "Subscription canceled successfully."
}

Response 404 — No active subscription.

json
{
  "error": "path is required"
}

Example

bash
curl -X POST "https://api.example.com/subscriptions/cancel/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /subscriptions/history/

Payment history

Stripe invoices for the user's subscription.

Auth: Session token · In the app: Profile → Billing

Response 200 — Invoices.

Array of:

FieldTypeDescription
idstring
amount_paidnumberIn the currency's major unit.
currencystring
statusstring
pdfstring (uri)
json
[
  {
    "id": "in_1P…",
    "amount_paid": 49,
    "currency": "usd",
    "status": "paid",
    "pdf": "https://pay.stripe.com/invoice/…"
  }
]

Response 404 — No payment history.

json
{
  "error": "path is required"
}

Example

bash
curl -X GET "https://api.example.com/subscriptions/history/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /microservices/cost-tracker/users/{username}/costs

My LLM usage and cost

Token usage and cost for the signed-in user over the last days days (you may only query your own username). No trailing slash on this path.

Auth: Session token · In the app: Profile → Usage; Overview card

Path parameters

FieldTypeRequiredDescription
usernamestringyes

Query parameters

FieldTypeRequiredDescription
daysintegernoDefault: 30.

Response 200 — Usage report (cost-tracker service response).

FieldTypeDescription
statusstring
usernamestring
summaryobject
summary.total_costnumber
summary.request_countinteger
dailyobject[]
daily[].datestring (date)
daily[].costnumber
daily[].requestsinteger
by_modelobject[]
by_model[].modelstring
by_model[].total_costnumber
by_model[].input_tokensinteger
by_model[].output_tokensinteger
json
{
  "status": "ok",
  "username": "jane",
  "summary": {
    "total_cost": 12.41,
    "request_count": 318
  },
  "daily": [
    {
      "date": "2026-09-21",
      "cost": 0.82,
      "requests": 21
    }
  ],
  "by_model": [
    {
      "model": "gpt-4.1",
      "total_cost": 9.9,
      "input_tokens": 812000,
      "output_tokens": 140000
    }
  ]
}

Response 403 — Not your username.

json
{
  "detail": "Authentication credentials were not provided."
}

Response 503 — Cost tracker not configured.

Example

bash
curl -X GET "https://api.example.com/microservices/cost-tracker/users/jane/costs?days=30" \
  -H "Authorization: Token $FINBLADE_TOKEN"

Finblade documentation