// getting started · 8 min

Customers & spend

This is the page that makes Ringside click. Talking to OpenAI, there is just you and a bill. On Ringside there is you, the people who use your app, and a meter that knows which of them spent what. Get this model and the rest of the API stops being confusing.

The three roles

There are three things in play, and keeping them straight is the whole game.

  • ·

    You are the developer. You hold the API key, you top up the wallet, you build the app.

  • ·

    A customer is one of your end-users: a tenant in your SaaS, a client of your agency, a single seat. They never see a Ringside key. They exist so spend can be attributed to them.

  • ·

    The wallet is your prepaid balance. Every call draws from it. Ringside records, per call, which customer it was for, so you can see and cap spend per customer even though it all comes out of one balance.

Why this exists

If you are building anything multi-tenant, an AI feature inside a SaaS, a chatbot you resell, an agency running campaigns for clients, you eventually need to answer "how much did customer X cost me this month" and "stop customer Y if they burn through their allowance". Doing that on raw OpenAI means building your own metering and budgeting layer. Ringside is that layer. You tag each call with a customer and it does the accounting.

If you are not multi-tenant, you can ignore all of this. Leave the customer off and every call just bills the wallet. The feature is there when you need it, invisible when you do not.

Tagging a call with a customer

You create a customer once and get back an id like cus_.... The create body takes display_name for the human-readable label and external_id for your own identifier. From then on, add the FC-Customer header (or the SDK passthrough) to any call and that spend is attributed to them. The call itself is otherwise identical.

# 1. create the customer once (store the cus_ id against your tenant)
curl https://api.fightclub.pro/v1/customers \
  -H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
  -d '{"display_name":"Acme Corp","external_id":"tenant_42"}'
# => { "id": "cus_abc", ... }

# 2. attribute any call to them with the FC-Customer header
curl https://api.fightclub.pro/v1/chat/completions \
  -H "Authorization: Bearer $FC_API_KEY" \
  -H "FC-Customer: cus_abc" \
  -H "Content-Type: application/json" \
  -d '{"model":"fc:openai/gpt-4o-mini","messages":[{"role":"user","content":"hi"}]}'

The field is display_name, not name — a name key is not recognized and is silently dropped, leaving the customer unlabelled. The id format is cus_... (an older docs example showed cust_42 — that was a typo; the real prefix is cus_). external_id is your own identifier for the tenant, so you can map your user back to a Ringside customer without keeping a second table.

Budgets: capping a customer

Give a customer a budget and Ringside enforces it. The field is monthly_budget_usd, set at create or by a later PATCH. When their attributed spend would exceed it, calls tagged with that customer start returning a 402 with a clear code (customer_budget_exceeded) instead of silently running up your bill. Your wallet still has money; this is a per-customer ceiling, not a global one.

So the failure you handle is: a 402 on a customer-tagged call means that customer hit their cap. Show them an upgrade prompt, or raise the budget. A 402 with wallet_empty is different: that is your whole balance gone, top it up.

# set (or change) a customer's monthly ceiling
curl -X PATCH https://api.fightclub.pro/v1/customers/cus_abc \
  -H "Authorization: Bearer $FC_API_KEY" -H "Content-Type: application/json" \
  -d '{"monthly_budget_usd": 50}'

# calls past the cap now fail fast:
# 402 { "error": { "code": "customer_budget_exceeded", ... } }

monthly_budget_usd is the recognized field. A budget_usd key is not read, so it is dropped without error and no budget is ever set — the calls you expected to be capped keep running.

Seeing the spend

Every call records the customer, the model, the tokens and the cost. GET /v1/customers/<id> returns the customer with totals like lifetime_spend_usd, monthly_budget_usd and wallet_balance_usd. For spend over a period, broken down by day, use GET /v1/customers/<id>/usage, which is the endpoint that computes per-period figures. The dashboard renders the same data, and you can pull it over the API for your own billing.

This is what lets you put real usage-based pricing in front of your customers: you know exactly what each one cost, including a margin you set, so you can mark it up and bill them.

# the customer record: lifetime totals, budget, balance
curl https://api.fightclub.pro/v1/customers/cus_abc \
  -H "Authorization: Bearer $FC_API_KEY"

# spend over a period, grouped by day
curl "https://api.fightclub.pro/v1/customers/cus_abc/usage?group_by=day" \
  -H "Authorization: Bearer $FC_API_KEY"

Two ways to bill your customers

Once you can see per-customer cost, you charge for it however you like. Two common shapes: you keep a prepaid wallet per tenant in your own app and decrement it from the Ringside numbers, or you let Ringside bill your end-customers directly through its Stripe integration and take your cut. Either way the metering is the same; only who collects the money differs.

Recap: one key, one wallet, many customers. Tag calls with FC-Customer to attribute spend, set monthly_budget_usd to cap them, read /usage to bill them. Next: choosing which model each call runs on.