Reference
Errors & types
The error envelope, every code, and the shapes you get back.
Error envelope
Every non-2xx response:
{ "error": {
"code": "allocation_exhausted",
"message": "This connection has spent its reserved allocation.",
"type": "insufficient_funds",
"connection_id": "conn_1a2b",
"increase_url": "https://dashboard.usewind.app/connections/conn_1a2b",
"review_url": null
} }
increase_url is set when raising the allocation would help. review_url is
set only on connection_frozen. It links the user to
dashboard.usewind.app/connections/{id}?review=paused, where they can resume the
connection, allow it to spend faster, or revoke it. Both are null otherwise.
Codes
| Status · code | Meaning | What to do |
|---|---|---|
400 invalid_request | malformed body, missing Idempotency-Key, unknown or retired model, unfetchable image, a voice session on a non-realtime model, or a mock session’s ticket used for a WebRTC offer | fix the request; not billed |
400 feature_model_not_configured | POST /v1/ai/features/{slug} on a feature with no default_model | set one in the console, or call /v1/ai/{model} |
401 invalid_ticket | voice offer exchange with a ticket that’s wrong, expired (~60 s) or already used | create a new session; tickets are single use |
401 unauthorized | access token missing, invalid or past its ~15 min TTL | refresh, retry once |
402 allocation_exhausted | connection spent its cap | prompt top-up / raise limit; deep-link increase_url, or POST /v1/connections/{id}/allocation-requests |
402 feature_cost_exceeded | one call blew the feature’s per-call guardrail | surface to the user; the call was not billed |
403 connection_revoked | user revoked the grant | mark disconnected, prompt re-connect |
403 connection_frozen | Wind’s risk layer paused the connection after abnormal spend | stop calling and show the user review_url. They can resume it there (you get connection.resumed) or reconnect. See Paused connections |
403 app_suspended | the app is switched off — by Wind, or by you in the console | stop calling and show it; keep stored grants, they work again once it’s lifted |
403 model_not_allowed | the app sets allowed_models and this model isn’t in it | bug — fix the model string or widen the allowlist |
409 idempotency_key_reused | same Idempotency-Key sent with a different body | use a fresh key for a new request |
429 rate_limited | a feature’s rate_limit reached | back off per Retry-After |
429 risk_throttled | Wind is throttling an unusual spend burst on this connection | back off per Retry-After |
429 daily_limit_reached | this connection’s 24-hour spend limit reached | tell the user; resumes as older spend ages out of the window |
429 app_spend_limited | your app’s daily spend limit for its tier reached (limited live) | back off per Retry-After; apply for full live if you’re outgrowing it |
429 too_many_sessions | the connection already has 2 pending or live voice sessions | end one first |
429 sandbox_live_cost_limited | Wind’s daily allowance for live-model calls in sandbox is used up and you have no key for that model’s provider | add your own provider key on the console’s Sandbox page, switch the app to mock mode, or wait |
502 provider_error | upstream provider failed | retry with the same Idempotency-Key — not billed |
The wind block
Present on every successful POST /v1/ai/* response:
| Field | Type | Meaning |
|---|---|---|
feature | string · null | the X-Wind-Feature slug, or null |
provider_cost_mc | int | what Wind paid the provider |
wind_fee_mc | int | Wind’s service fee |
dev_margin_mc | int | your multiplier margin |
user_charge_mc | int | debited from the user’s balance |
allocation_remaining_mc | int | allocation − consumed − held for this connection |
Conventions
- Money — integer micro-cents, USD.
_mcfields; a_displaystring accompanies headline amounts. - IDs — prefixed opaque strings:
wac_,app_,conn_,led_,acr_,evt_,rts_(voice session),rtt_(voice ticket). Tokens andcodeare opaque, unprefixed, and secret. - Time — RFC 3339 UTC.