Concepts
Allocations & balance
Reservation lifecycle, holds, non-refilling semantics, increases, revocation.
Reservation lifecycle
- Connect —
min(requested_allocation_mc, available)moves from the user’savailablebalance intoreserved, ring-fenced to the new connection. - Lower the cap — the delta returns to
availableimmediately. - Raise the cap — needs
availablefunds, or triggers a top-up. Your app can only request an increase; the user approves it. - Reversal — a refunded charge credits back to the connection’s reserved pool,
or to
availableif the connection is revoked.
Non-refilling
An allocation does not refill on a schedule. When consumed_mc reaches
allocation_mc, the connection is exhausted and every call 402s until the cap
is raised. A refilling cap would mean a compromised app bleeds the balance every
period.
Authorization holds
Each in-flight request holds its estimated max cost:
allocation_remaining = allocation_mc − consumed_mc − held_mc
The estimate is counted input tokens + max_tokens at the model’s rate, ×
multiplier, + ~5% margin. If it doesn’t fit, the call is rejected before any
provider spend. On completion the real cost is written and the rest released.
Holds auto-expire after ~5 minutes, so a crashed request can’t strand funds, and
they make concurrent requests on one connection safe.
If max_tokens is omitted, the hold cap resolves:
request → feature max_tokens → app default_max_tokens → model ceiling.
Requesting an increase
POST /v1/connections/{id}/allocation-requests
{ "target_allocation_mc": 2500000000, "reason": "Heavy user, raising cap" }
→ 200
{ "id": "acr_55", "status": "pending",
"current_allocation_mc": 1000000000, "target_allocation_mc": 2500000000,
"approval_url": "https://dashboard.usewind.app/allocation-requests/acr_55" }
It applies only after the user approves. Learn the outcome via the
allocation_change.approved / .denied webhooks or by polling the connection.
A connection has at most one pending request. Filing a new one replaces it: the
old request becomes superseded and its approval_url points the user at the
new one, so ask again whenever your number changes.
Top-ups
The user tops up their balance on dashboard.usewind.app (Stripe). It never
happens through the API, and — in sandbox — not at all: the sandbox balance is
fake and effectively unlimited.
Revocation
The user can revoke a connection unilaterally, any time, from the dashboard. Your
app should treat 403 connection_revoked as terminal: mark the user
disconnected and prompt a re-connect.
Paused connections
Wind’s risk layer watches each connection’s pace of spending. Chat calls are
compared with their usual rate, and voice sessions with a
normal conversation’s spend per minute on that model. Spend that is fast but
not alarming is flagged, and your app gets a connection.risk_warning webhook
(at most every 10 minutes per connection). Spend far past normal pauses the
connection (status: frozen):
- Your app gets a
connection.frozenwebhook, and calls fail with403 connection_frozen. A live voice session on it ends withend_reason: connection_frozen. - The user gets an email linking to the connection’s review page (the
review_urlin the webhook and the error). There they can resume the connection, allow it to spend faster (up to 3× Wind’s usual thresholds), or revoke it. - When they resume, your app gets
connection.resumedand calls work again on the same tokens. The user can also reconnect from scratch.
Treat connection_frozen as “waiting on the user”: stop calling, show
review_url, and keep the stored grant.
The reserved allocation is a security boundary
Token theft in plain OAuth is a data leak; here it is someone spending the user’s money. The cap bounds the total loss and the velocity limit bounds the rate — pair them with short-lived access tokens, mandatory PKCE, and refresh rotation.