Whitelabel & Reseller Setups

Two technical patterns for putting Surplus behind your own product. Let Surplus provision and meter one key per end customer, or run your own gateway in front and call Surplus with a small pool of high-capacity keys. Both require a written arrangement with us before you launch.

Talk to us before you build on this. The standard Terms of Service §8 prohibit reselling, redistributing, or wholesale repackaging the Service or provider API access, and prohibit using the Service to build a directly competing routing service. Listing capacity as a Seller under §6 is the one resale path the standard Terms permit on their own, and it is not what this page describes.

So the patterns below are not self-serve entitlements. They are the shapes a reseller integration takes once we have agreed one in writing, which is how §20 provides for varying these Terms. Email support@surplusintelligence.ai or use the Enterprise contact form first; build second.

The right pattern depends on one question: who owns per-customer isolation and billing? If you want Surplus to be the system of record for each downstream customer, use Pattern A. If your gateway already owns customer identity, quotas, and billing, use Pattern B.

Where the customer boundary lives
  1. Pattern A
    one Surplus key per customer
  2. Pattern B
    your gateway, one Surplus org
In Pattern A each customer is a Surplus key, so Surplus enforces isolation and budgets. In Pattern B your gateway is the boundary and Surplus sees one tenant.

Pattern A: Surplus provisions per customer

You mint one scoped buyer key per customer through the provisioning API. Surplus enforces isolation, budgets, and usage per key.

Read more

Pattern B: your gateway in front

Your gateway owns per-customer isolation and billing. You call Surplus with a small pool of keys under one dedicated organization.

Read more

Pattern A: a Surplus key per customer

Best when you want Surplus to hold each downstream customer's budget and usage. You create an organization, then use an admin key to mint one scoped buyer key per customer through the /v1/keys provisioning API. Each key carries its own scope, budget, and usage attribution, enforced on the backend. The organization remains the billing account: every key spends from one prepaid balance, and the per-key budget is what bounds a customer (see Isolation, budgets, and caps).

Admin keys (inf_admin_...)

An admin key is a management key. It mints, scopes, rotates, and revokes buyer keys through /v1/keys, scoped to its own workspace.

An admin key holds the full capability vocabulary (key management, offers, usage and request-log reads, budgets, webhooks, and the rest). Two things it cannot do: run inference (its key type is rejected at the inference guard, independently of any capability it holds), and mint another admin key (only an organization owner or admin session can issue a management key). No money-moving route admits an admin key either, so in practice it provisions and reads but never spends or withdraws. If you have read older docs describing it as "key-management and usage-read only", that description is out of date.

An organization owner or admin creates the admin key from the dashboard or an owner/admin session. Treat it like a root credential: anyone holding it can provision and revoke every customer key in the workspace.

The provisioning API (/v1/keys)

Full CRUD plus rotate over the workspace's keys. Every route requires the keys.manage capability, which an admin key holds. Every write here requires an Idempotency-Key header (create, update, rotate, and revoke alike); omitting it is a 400 idempotency_key_required, not a silent success.

POST/v1/keys

Mint a buyer key for a customer, with an optional scope (models, providers, providers_blocked, endpoints, min_discount_pct, trusted_only) and budget. The inf_... secret is returned once.

GET/v1/keys

List the workspace's provisioned keys (redacted). GET /v1/keys/{id} reads one; an id outside your workspace is a 404.

PATCH/v1/keys/{id}

Re-scope, rename, or re-budget a customer's key.

POST/v1/keys/{id}/rotate

Rotate a customer's key: mints a successor that inherits the old key's scope, workspace, and budget, and retires the old one. The successor has a new id and a new secret, so distribute both. grace_hours (default 0, meaning revoke the old key immediately) keeps both keys live through a cutover window.

DELETE/v1/keys/{id}

Revoke a customer's key.

Provision a customer key
bash
POST /v1/keys
Authorization: Bearer inf_admin_xxx
Idempotency-Key: 9f8c1e2b-...     # required
{ "name": "customer-8842" }
# → { "id": "01JQ...", "key": "inf_...", "key_prefix": "inf_9f8c1e2b", "key_type": "buyer" }
bash
POST /v1/keys
Authorization: Bearer inf_admin_xxx
Idempotency-Key: a1b2c3d4-...
{
  "name": "customer-8842",
  "scope": { "models": ["claude-opus-4.6", "gpt-5.4"], "min_discount_pct": 20 },
  "budget": { "limit_month_micro": 250000000 }   // 250 USD/month, in micro-USD
}
bash
POST /v1/keys/{id}/rotate
Authorization: Bearer inf_admin_xxx
Idempotency-Key: c3d4e5f6-...     # required
{ "grace_hours": 24 }             # optional; 0 (default) revokes the old key at once
# → a NEW id + a NEW `key` secret; the old key is retired
bash
DELETE /v1/keys/{id}
Authorization: Bearer inf_admin_xxx
Idempotency-Key: d4e5f6a7-...     # required

Isolation, budgets, and caps

  • Isolation is per key, and it is enforced by scope plus budget, not by separate funds. Every key in the organization draws on the same prepaid balance, so what stops one customer spending another's money is the key's budget (hard_stop is on by default), not a wall between accounts. A key minted without a budget can spend the whole organization balance, so set one at mint time for every customer key. Usage is attributed per key regardless.
  • Budgets nest. A key's budget sits inside its member, workspace, and organization budgets, and every enclosing scope must have room. See budgets and spend limits.
  • Key caps are counts of active keys, not request-rate limits:
SurfaceCapWhat it counts
Self-serve (/v1/buyer/keys, /v1/seller/keys)25 active keys per wallet, per typeBuyer and seller keys are counted separately.
Provisioning (/v1/keys)200 active keys per workspaceThe admin-key surface for Pattern A.

If you expect more than a few hundred concurrent customer keys, prefer Pattern B or contact us about a dedicated organization.

Pattern B: your gateway in front

This is the AIPrime-style model, and the right one when your gateway already owns per-customer isolation, quotas, and billing. It is also the shape that most clearly needs the written arrangement above, since a gateway routing on top of us is exactly what Terms §8 addresses. Surplus does not need to know your customers. You call it with a small pool of high-capacity buyer keys under one dedicated organization, and reconcile cost back to your own accounts.

Rate limits and throughput

Two independent limits apply, and for a gateway the per-IP one usually binds first.

LimitCeilingScoped byOn breach
Application rate limit~1,200 requests per minute on the OpenAI-compatible completion path (/v1/chat/completions, /v1/completions); the other inference surfaces sit on a comparable per-minute bucketYour API key429 with Retry-After. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.
Edge WAF rule1,200 requests per 5-minute window, i.e. about 240 per minuteYour source IPBlocked at the edge, before the application sees the request. No X-RateLimit-* headers and no JSON error body.

The per-IP rule is not a looser backstop above the per-key limit. It is roughly five times tighter, and it counts every request from an address regardless of how many keys those requests carry. A gateway calling Surplus from one NAT address therefore tops out near 240 requests per minute no matter how its traffic is split across keys.

So a high-volume integration scales on two axes, and you need both:

  • Spread egress IPs. This is what actually lifts the binding ceiling for a gateway. Traffic split across N source addresses gets N times the per-IP allowance.
  • Pool keys. Once you are past the per-IP ceiling, several keys lift the per-key ceiling the same way. Under a dedicated org you provision these through the admin key. Pooling keys behind a single IP buys you nothing.
  • Plan high volume with us. Both ceilings are fixed guardrails rather than per-account tuning, so for sustained reseller traffic provision a dedicated organization and tell us your expected throughput and your egress addresses. We can then confirm upstream capacity and the per-IP allowance ahead of launch.

Beyond the rate limit, real throughput is bounded by your prepaid balance (a request is rejected if the balance cannot cover its estimated maximum cost) and upstream provider capacity for the models you route to. Requests are served by horizontally scaled fleets.

The rate limits documented on Seller Endpoints are a separate set of buckets covering the seller management routes (offers, discovery, key issuance). The limits above are what bound buyer throughput.

Automatic provider failover

You do not build failover yourself. The marketplace routes each request to the cheapest healthy seller for the model, marks a seller unhealthy on failure, and backs off, so traffic moves to the next seller automatically. You can also register your own provider keys as priority or fallback providers if you want your own capacity tried first or used as a safety net.

Reconciling Surplus cost against what you bill

Most requests expose their cost inline so you can attribute it to the downstream customer your gateway is billing. The inline figure is best-effort and wire-specific, so treat it as a fast path and the request log as the authority:

SurfaceWhat it gives you
x-si-buyer-cost-micro response headerNon-streamed responses only. The buyer cost of that request in integer micro-USD, also placed on usage.buyer_cost_micro in the body. Omitted entirely when the charge is not known at response time, rather than sent as a misleading 0.
usage.buyer_cost_micro in the final stream eventStreamed responses only, because HTTP headers freeze at the first byte. It rides the terminal usage event, so it requires stream_options: {"include_usage": true} and an upstream that actually emits usage. If either is missing, or the cost cannot be computed, the event is passed through untouched rather than failing the stream.
GET /v1/requests and GET /v1/requests/{id}The per-request log (model, tokens, cost, status). The list needs the requestlog.read capability; the per-request detail is also readable by the inf_... key that made the request, so a key can pull its own settlement and cost rows.
GET /v1/buyer/me and GET /v1/buyer/usage/exportUsage stats, and a CSV of your usage records for periodic reconciliation. The export is bounded at 50,000 rows (or a lower limit you pass) and is not guaranteed complete: a capped response carries x-si-export-truncated: true. Narrow the from/to window and page through it, or use the explorer below.
POST /v1/analytics/explorerFor high-volume reconciliation, an ad-hoc warehouse query over your own spend, grouped how you ask. Poll GET /v1/analytics/explorer/{queryId} for the result, or pull it as CSV from GET /v1/analytics/explorer/{queryId}/export. Needs the finops.read capability.

Use the inline figure for real-time margin where it is present, and reconcile against GET /v1/requests on a schedule. For a request whose cost never appeared inline (a stream without usage, or a charge not yet known), GET /v1/requests/{id} is the authoritative per-request record. Never infer a zero cost from a missing header or trailer.

Keep a balance buffer

Because a request is rejected when the balance cannot cover its estimated maximum, keep a buffer above your steady-state burn and enable automatic top-up so a busy hour never drains you to zero mid-stream.

A dedicated org for volume

Reselling is not permitted by the standard Terms without a written arrangement (see the note at the top of this page), so this always starts with a conversation rather than a signup. Beyond that, there is no separate technical "reseller tier." Capacity is architectural (horizontally scaled fleets) and everyone runs against the same guardrails: the per-key and per-IP rate limits above, and your prepaid balance. There is no per-account throttle to raise, so a reseller is not given a bigger bucket than anyone else. What a high-volume reseller gets is a dedicated organization so usage, billing, and keys are cleanly separated from everyone else, plus a direct line to plan capacity and the per-IP allowance before launch.

To provision one, open the Enterprise contact form on the site or email support@surplusintelligence.ai with your expected volume and the models you plan to route.

API Keys & Spend Limits

Buyer keys, the admin provisioning surface, scopes, and nested budgets.

Read more

Buyer Endpoints

Keys, per-key routing preferences, BYOK providers, and usage export.

Read more

Roles & Permissions

Who in an organization can mint keys, set budgets, and read request logs.

Read more

FAQ

Rate limits, key caps, reseller plans, reconciliation, and provider TOS.

Read more