Advanced guide / Chapter 4 of 7
Per-customer budgets for SaaS and agent platforms.
If your product runs AI agents for your customers, they all share your provider account. One customer's runaway agent, or a malicious prompt, can use up the budget and the rate limit for everyone. Tenants fix that. Each of your customers gets their own budget and rate limit, checked before every call.
Integrate in six steps
- Pick a tenant id. Use your own customer or workspace id, such as
customer_4821. Letters, digits and. _ : @ -. - Send it with every call.
const client = new OpenAI({ baseURL: "https://acp.examopotamia.com/v1", apiKey: process.env.ACP_KEY, defaultHeaders: { "X-Upstream-Key": process.env.OPENAI_API_KEY }, }); // Per request, for the customer you are serving: await client.chat.completions.create( { model: "gpt-5-mini", messages }, { headers: { "X-ControlPlane-Tenant-Id": customer.id, "X-ControlPlane-Session-Id": task.id } }, ); - Set a default for every customer on Console → Limits → "Every tenant", for example $25 a month and 60 requests a minute.
- Set each customer's own limit from your code when they sign up or change plan:
Node.js
await fetch(`https://acp.examopotamia.com/v1/controlplane/tenants/${customer.id}`, { method: "PUT", headers: { Authorization: `Bearer ${process.env.ACP_ADMIN_KEY}`, "content-type": "application/json" }, body: JSON.stringify({ monthlyBudgetUsd: plan.aiBudgetUsd, requestsPerMinute: plan.rpm }), });Python
import os, requests requests.put( f"https://acp.examopotamia.com/v1/controlplane/tenants/{customer_id}", headers={"Authorization": f"Bearer {os.environ['ACP_ADMIN_KEY']}"}, json={"monthlyBudgetUsd": 200, "requestsPerMinute": 300}, ) - Handle the customer's limit in your product. A call refused for a tenant returns HTTP 402
tenant_budget_exhaustedor 429tenant_rate_limited. Show your own message, or offer that customer an upgrade. - Show customers their usage with
GET /v1/controlplane/tenants/{id}: spend this month, money held for calls in progress, requests and tokens.
| Call | Does |
|---|---|
PUT /v1/controlplane/tenants/{id} | Sets monthlyBudgetUsd and requestsPerMinute; null means no limit. Applies to the next call. |
GET /v1/controlplane/tenants/{id} | Usage this month and the limits that apply (own or default). |
GET /v1/controlplane/tenants | All tenants by spend; ?search=, ?limit=. |
DELETE /v1/controlplane/tenants/{id} | Removes the customer's own limit; the default applies again. |
Tip. To cut off an abusive customer right away, set their budget to 0. Their next call is refused and nobody else notices.
Good to know. The tenant API needs a key with admin access. Keep that key on your servers. It should never ship inside a browser or mobile app.