# Bu0y — agent / integration reference > Best-execution inference router. OpenAI-compatible. Prepaid microdollars. > Site https://bu0y.com · API https://api.bu0y.com · Index https://bu0y.com/llms.txt ## Hard rules (read first) 1. **Prepaid only.** Credits are non-refundable. No withdraw. 2. **Always set `max_tokens` (or `max_completion_tokens`).** Bu0y reserves worst-case COGS and bill against your balance **before** the fill. If you omit a ceiling, the gateway imposes **4096**. That can reject thin balances. For agent/tool loops prefer an explicit ceiling (e.g. `8192`–`32768`). Reasoning models (Kimi, DeepSeek, etc.) often bill `completion_tokens` **above** your `max_tokens`; the reserve floors output tokens at 1024 so tiny probes do not fail. That floor is a reserve rule only — your `max_tokens` is sent upstream exactly as you set it, so a request for 400 comes back at 400, not 1024. 3. **No fill below the margin floor.** Under the floor → **503**, not a loss-making fill. 4. **Money is integer microdollars** (`$1 = 1_000_000`). Floating-point money never touches a balance. 5. **Idempotency-Key** reuse returns **409** with the prior `request_id`. 6. **Credits are non-refundable.** No cash-out path. ## Money and fill path On `POST /v1/chat/completions`: 1. Authenticate (`Authorization: Bearer bu0y_…`). 2. Quote every source in parallel. A `null` quote is normal (source cannot serve). 3. Price with adaptive margin. Discard anything under `MIN_MARGIN_RATE` (15%). 4. **Reserve the worst case** against the account: estimated input (with template pad) + max(`max_tokens`, output reserve floor) at sell rates. Never the expected cost. Cache discounts ignored for the reserve. 5. Execute at the cheapest survivor. With `stream: true` the answer is relayed token by token and the budget is an **idle** one: 150s for the first token (a pod can sit queued), then a silence budget learned per model — three times the longest mid-answer pause a completed stream of that model has shown in the last day, held between 20s and 180s, 60s until it has history — and 480s absolute. Without it the answer is buffered and the budget is total wall-clock (~12s plus ~40s per 1k output tokens, floored at 1024 tokens like the reserve, capped at 480s — sized for a marketplace pod running around 25 tokens/sec). A failing source may fail over to another; a source that runs out of budget does **not** — it may already be generating, and paying twice for one answer is worse than returning an error. Once the first streamed token is out, this source is the answer: there is nothing left to fail over to. 6. Settle the real bill (`costFloor`), release unused hold, enqueue marketplace COGS. 7. Settle completes **before** the terminal response frame (streaming included). Minimum charge covers settlement gas (~$0.002). A quote that cannot clear the floor returns 503. ## Auth ### Agents (Solana wallet → key) ``` GET /v1/auth/challenge?address= POST /v1/auth/keys body: { "message": "", "signature": "", "label"?: "…" } → { "key": "bu0y_…", "accountId", "wallet" } ``` Then `Authorization: Bearer bu0y_…` on account, deposits, and fills. Agents are not humans and do not get a terms click. Minting a key, calling the API, or sending USDC accepts https://bu0y.com/terms and waives claims as those terms state. Challenges are single-use, ~5 minute TTL. Cap: 25 active keys per wallet. Prefer a dedicated agent wallet. Reference script: repo `scripts/agent-mint-key.ts`. ### Humans (passkeys → session → key) 1. Register / login via `/v1/auth/passkey/*` from https://bu0y.com/account 2. Session via HttpOnly cookie 3. Mint keys within ten minutes of passkey authentication: `POST /v1/account/keys` → secret shown once ## Funding - **Solana USDC:** `GET /v1/deposits/solana` → send USDC → `POST /v1/deposits/solana/sync` - **Base USDC:** `GET /v1/deposits/base` → send USDC → `POST /v1/deposits/base/sync` - **Robinhood Chain USDG:** `GET /v1/deposits/robinhood/usdg` → send USDG contract `0x5fc5360d0400a0fd4f2af552add042d716f1d168` → `POST /v1/deposits/robinhood/usdg/sync` Min on-chain deposit $1. Credits are prepaid usage rights only. ## Model ids (canonical slugs) Use Bu0y catalog ids from `GET /v1/models` or https://bu0y.com/models — **not** every OpenAI/Anthropic marketing name. Punctuation is usually stripped (`gpt-4o` → `gpt4o`). Wrong ids → **404**. | Common ask | Bu0y `model` id | |------------|-----------------| | GPT-4o | `gpt4o` (also accepts `gpt-4o`) | | Gemini 2.5 Flash | `gemini25flash` | | Kimi K3 | `kimik3` | | Kimi K2.5 | `kimik25` | | Kimi K2.7 Code | `kimik27code` | | DeepSeek V3.1 | `deepseekv31` | | GLM 4.6 | `glm46` | | Claude Opus 5 | `claudeopus5` | Full live list: `GET https://api.bu0y.com/v1/models`. Prefer copying from /models. Dots and hyphens are punctuation, not a different model: `glm4.6` and `gemini-3.7-flash` are `glm46` and `gemini37flash`. A `:batch` suffix is a different product. ## Quote (free) ```bash curl https://api.bu0y.com/v1/quote \ -H 'content-type: application/json' \ -d '{"model":"glm4.6","inputTokens":1500,"maxOutputTokens":800}' ``` ```json { "model": "glm4.6", "inputTokens": 1500, "maxOutputTokens": 800, "best": { "reserveMicros": 32, "inputPer1m": 150, "outputPer1m": 600, "confidence": 0.9 }, "available": { "low": 32, "average": 74, "high": 116 }, "market": { "low": 32, "average": 74, "high": 116 }, "errors": [{ "kind": "below_floor" }] } ``` `best.reserveMicros` is the worst-case hold for this exact request, at the price you would be charged. `available` is the range across every offer that could actually fill it; `market` also counts offers that could not - including any route currently sat out for refusing a recent request. `errors` gives the reason each excluded offer was excluded - `below_floor`, `insufficient_capacity`, `upstream`, `timeout`. No marketplace is named, here or anywhere else. Quote and fill agree by construction: `/v1/quote` routes against the same exclusions the fill path does, so `best` is the route a fill would actually take. ## Fill example ```bash export BU0Y_KEY=bu0y_… curl https://api.bu0y.com/v1/chat/completions \ -H "Authorization: Bearer $BU0Y_KEY" \ -H 'content-type: application/json' \ -d '{ "model": "glm4.6", "messages": [{"role":"user","content":"hi"}], "max_tokens": 256 }' ``` OpenAI SDK: `baseURL: "https://api.bu0y.com/v1"`, `apiKey: bu0y_…`. **Always send `max_tokens`.** Omitting it reserves against the imposed 4096 ceiling. ## Hermes Agent `custom_providers` **must be a YAML list** (each entry starts with `-`). A dict causes `Unknown provider 'custom:bu0y'`. ```yaml # ~/.hermes/config.yaml custom_providers: - name: bu0y base_url: https://api.bu0y.com/v1 api_key: bu0y_… model: default: glm4.6 provider: custom:bu0y ``` Or: `hermes model` → Custom endpoint (writes the list form). Leave base URL at `/v1`. ## Agent mint example ```bash curl "https://api.bu0y.com/v1/auth/challenge?address=$PUBKEY" curl https://api.bu0y.com/v1/auth/keys \ -H 'content-type: application/json' \ -d '{"message":"…","signature":"…","label":"agent"}' curl -H "Authorization: Bearer $KEY" https://api.bu0y.com/v1/deposits/solana # send USDC, then: curl -X POST -H "Authorization: Bearer $KEY" \ https://api.bu0y.com/v1/deposits/solana/sync ``` ## Tool calling and request parameters Bu0y is a transparent OpenAI-compatible router. **Send the request you would send to any OpenAI-compatible endpoint.** **Tools** work end to end, buffered and streamed: - `tools` and `tool_choice` (`auto` / `none` / `required` / a named function) are forwarded to the marketplace verbatim. - Responses carry `choices[0].message.tool_calls` with `content: null`, and `finish_reason: "tool_calls"` whenever calls are present — even if the upstream labelled it `stop`, because agent loops branch on that. - Streaming relays `delta.tool_calls` as index-keyed fragments in the standard shape. Accumulate by `index` exactly as you would against OpenAI. - Continue the conversation normally: an assistant turn with `content: null` plus `tool_calls`, then a `role: "tool"` message carrying `tool_call_id`. - `role: "developer"` is accepted as a system turn. `content` may be a string, `null` (with `tool_calls`), or an array of text parts. **Generation parameters** pass straight through — `temperature`, `top_p`, `stop`, `seed`, `response_format`, `presence_penalty`, `frequency_penalty`, `logit_bias`, `logprobs`, and open-model extras like `top_k`, `min_p` and `repetition_penalty`. Anything Bu0y does not itself own reaches the provider untouched, so a parameter your model supports is a parameter you can use. A few fields are refused with a 400 rather than forwarded, because they add cost the token counts cannot see and so cannot be reserved or billed honestly: `best_of` (multiplies generated tokens with no way to count them), `plugins`, `web_search_options`, `modalities`, `audio` and `image_config` (priced upstream per result or on a non-token scale). Bu0y owns these fields and will not let them be overridden from elsewhere in the body: `model`, `messages`, `max_tokens`, `max_completion_tokens`, `stream`, `stream_options`, `tools`, `tool_choice`, `n`, and the routing hint `provider`. These decide what a request costs, how it is framed, or where it fills. `n` is supported up to 8. Each completion runs to your ceiling and is billed for it, so the reserve scales with `n` — a large `n` and a large `max_tokens` together can return 402 on a thin balance. Every choice comes back: buffered as `choices[i]`, streamed as chunks carrying their own `choices[0].index`, each closing on its own `finish_reason`. **Images** work on vision models: send `content` as an array with `{"type":"image_url","image_url":{"url":"…"}}` parts, either an https URL or a `data:` URL, up to 20 per message. `detail` is accepted and forwarded but does not change what we reserve — the providers that price images have no such field and charge purely on resolution, so one fixed allowance covers every image whatever the hint says. The reserve holds a fixed allowance per image rather than measuring the payload, because an image's cost is set by the provider's tiling and has nothing to do with the bytes you upload — a 500KB base64 photo is roughly 1500 tokens. You are billed for the tokens actually reported, as always; the allowance only sizes the hold, so a large multi-image request can 402 on a thin balance even though the eventual bill is small. **Audio and video parts are refused with a 400.** The line is whether a worst-case reserve can be sized: an image is capped by tiling, an hour of video is not, and Bu0y does not fill what it cannot bound. A clear refusal beats a silent under-reserve. ## Pricing: what you are quoted vs what you pay `GET /v1/models` lists **prices, inclusive of margin** — micros per 1M tokens, at the cheapest source for each model, quoted at the ceiling margin. Treat it as "you will not be charged more than this", not as an exact rate; real fills are usually cheaper. Every published rate is on this basis. `/v1/models`, the model tables on bu0y.com, and `/v1/harbor` all quote the ceiling price you would be billed, and `/v1/quote` prices your exact request against the same book. If two of them disagree for a model, that is a bug worth reporting — they are the same number computed from the same catalog. Alongside them, `input` and `output` give the **range across every source quoting that model** — `low`, `average`, `high`. Bu0y fills at the cheapest source that will actually serve you, so **if the cheapest one cannot take your request, a dearer one may fill it**, and that range is how far the price could move. When `low` equals `high`, only one source carries the model and there is nothing to shop against. Two ways to stay in control: - `POST /v1/quote` prices your exact request across every source before you commit. Free, no fill. - `max_input_per_1m` / `max_output_per_1m` on a fill are hard ceilings in micros per 1M tokens, compared against what you would be **billed**. Any source above either is skipped; if none remain you get a 503 naming the cheapest that was available, instead of a surprise on the invoice. - `max_price_multiple` on a fill is the same ceiling relative to the market: at most N times the cheapest rate any source printed for the model on that request (the low end of `bu0y.market`), per axis. For a caller whose cheap band comes and goes, "never more than 4x the cheap band" without tracking the band. A fixed ceiling set alongside still applies, whichever is lower. - `min_tokens_per_sec` / `max_seconds` on a fill ask for a route that finishes. `max_seconds` is turned into a decode-speed floor against your `max_tokens`; the stricter of the two applies. A route whose recent record is slower is skipped even when it is cheapest; the cheapest of the rest fills, whether or not it has a record yet. If every route is known to be slower, 503 `unmet_speed`, naming the fastest known. Speed is a property of a route, not a venue: this never names or picks a source. The response says which case you got: `bu0y.speed_floor` is `verified` when the filling route was known to meet your floor and `unverified` when it had no record yet (a route's speed is the median of its completed streams in the last fifteen minutes, so a fresh deploy or a quiet model has none, and one slow stream does not speak for the route). `max_seconds` is judged against your `max_tokens`, so a very large ceiling with a short deadline asks for a speed no route has and gets `unmet_speed`; set the ceiling you actually need when you send a deadline. ## Checking best execution on every response Every fill carries its numbers in `bu0y`: `billed_micros`, `reserved_micros`, `latency_ms`, `max_tokens_served`, and two price ranges. ```json "bu0y": { "request_id": "...", "reserved_micros": 3200, "billed_micros": 1240, "latency_ms": 812, "max_tokens_served": 1024, "market": { "low": 1240, "average": 9100, "high": 25800 }, "available": { "low": 1240, "average": 11700, "high": 25800 } } ``` `reserved_micros` is what was held against your balance for the worst case; `billed_micros` is what you were actually charged when it settled. Bu0y's own cost and markup are not published. Both are what **this** request would have cost at each source, for the tokens you actually used — not rates, and not worst-case reserves. `available` covers the offers that could be filled (cleared the margin floor and your own `max_*_per_1m`); `market` also counts the ones that could not. **`billed_micros` equal to `available.low` means you were filled at the best price purchasable.** That is the whole check, and it rides every response. - `billed_micros` above `available.low`: a cheaper offer existed but the fill did not land there — a failover after the cheapest source failed mid-request. - `available.low` above `market.low`: the cheapest seller in the market was not serving your request at all - it either could not price it, or it refused a recent request for this model and is sat out for the hour. This is the case worth watching: your bill moved because supply moved, not because anything about your request changed. - `low` equal to `high`: one offer, nothing to shop against. Small requests floor at the minimum charge, so on a short answer every source prices identically and both ranges collapse to the floor — `low`, `average` and `high` all read 2000, and `billed_micros` equals every one of them. That is a real answer, not a missing one: at that size the bill is settlement gas, not a market quote, and there is genuinely nothing to shop. Send a request large enough for real cost to clear the floor and the ranges open up again. What is not published, on any endpoint: which marketplace quoted what, what that marketplace charged Bu0y, and the margin taken. Not in a fill response, a quote, the catalog, `/health`, or your usage history. Those are Bu0y's side of the trade; the price you paid and the range around it are yours, and the range is what makes the price checkable. Remaining credits are at `GET /v1/account` (bearer or session): `balanceMicros` is what is on the account, `reservedMicros` is held by in-flight fills, and `availableMicros = balance - reserved` is what a new fill can draw — the number to show as "credits left". Per-request history is at `GET /v1/account/usage` (bearer or session). There is no `/v1/usage`. ## Reasoning models and small `max_tokens` Reasoning models spend output budget thinking before they answer, and thinking is billed inside `completion_tokens`. On a small `max_tokens` the whole budget can go to reasoning, and you get **200 OK with `content: ""` and `finish_reason: "length"`** — correct, and easy to mistake for a silent failure. Check `usage.completion_tokens_details.reasoning_tokens`: if it is equal to `completion_tokens` and content is empty, the model never reached the answer. Retry with a larger ceiling. Measured on `kimik3`: 16 and 32 both returned empty; 64 and above answered. **A floor of 128 is a safe default for reasoning models.** `max_tokens` is a ceiling passed to the provider as you set it, and providers honour it approximately, and downward only to a point: measured across a run of ceilings on `kimik3`, 17 returns 17, while 16, 8, 4, 2 and 1 all return 16. A pod will not stop mid-reasoning-block. The floor is the provider's — Bu0y sends your ceiling untouched — and it cannot cost you anything: sixteen output tokens on the dearest model in the catalog is far under the minimum charge, so any request small enough to hit the floor is already billing the minimum anyway. Budget from `usage`, which is always the truth, rather than assuming `completion_tokens <= max_tokens` exactly. Bu0y reserves against a 1024-token floor underneath your ceiling precisely so this cannot overrun what was held. ## Prompt caching Automatic on models whose market prices it — nothing to enable, no `cache_control` blocks, no headers. When a request repeats an identical prompt prefix, the provider serves the cached slice and the bill prices it at the cache-read rate instead of the input rate — typically around a tenth of the input price. `usage.prompt_tokens_details.cached_tokens` reports how many prompt tokens the cache served, on every response path, so you can verify a prompt layout is caching without reverse-engineering the bill. What makes a hit: - The prefix must be **byte-identical**: same system prompt, same earlier messages, same tool schemas, in the same order. A timestamp or random id near the top of the prompt kills every hit; keep volatile content at the end. - Providers cache from the front, usually past a minimum prefix (~1024 tokens). Small prompts do not hit, and bills under the minimum charge (~$0.002) are floored there regardless. - Not every model's market prices cache reads. Where none is quoted, cached tokens bill at the input rate — never more, never for free. The reserve is unchanged: it is the worst case at full rates, and a cache hit only ever shrinks the real bill inside it. Agent loops that resend a long conversation every turn are exactly the shape that benefits. ## Errors agents should expect | Status | Meaning | |--------|---------| | 401 | Missing / bad Bearer or session | | 400 | Bad body, below deposit minimum | | 402 | Insufficient prepaid balance for the **reserved** worst case | | 404 | Model unknown to every source (check catalog slug) | | 409 | Idempotency-Key reuse | | 413 | Request body over 4MB. Applies to every endpoint that takes a body | | 429 | Rate limit | | 502 | Upstream marketplace error after failover exhausted, or a non-failover kind (`timeout`, `auth`, `malformed_response`). Body `error.message` / `type` carry detail — not a Cloudflare outage by itself | | 400 | Bad body — and also: every source refused a request carrying optional fields (a `temperature` out of range, a tool schema, an image). The model is available; the request is not acceptable. Retry without the optional fields to confirm. | | 503 | No offer clears the margin floor, no source is within your `max_*_per_1m` ceiling, no route is known to reach your `min_tokens_per_sec` / `max_seconds` (`type: unmet_speed`), or deposits not configured. When a smaller ceiling would have filled, `error.retry_max_tokens` is the largest `max_tokens` that does — retry at exactly that instead of switching providers | **Reasoning / overrun:** Bu0y reserves at least 1024 output tokens and sends that ceiling upstream. If a marketplace still bills more tokens than reserved, the fill succeeds and the account is charged for actual usage (at least COGS), topping up from available balance past the hold when needed — so under-reserve cannot free-ride on operator cost. **Drop-in compatibility:** everything Bu0y adds is optional and additive. Bu0y-only request fields (`max_*_per_1m`, `min_tokens_per_sec`, `max_seconds`) can be omitted or sent through an SDK's `extra_body`; Bu0y-only response data lives in the top-level `bu0y` object and inside `error`, which SDKs ignore. Note that the OpenAI SDKs decide retries on HTTP status alone, never on `error.type`: a 400 is never retried by the SDK, which is right — the same request cannot succeed. A 503 (`below_floor`, `unmet_speed`) is retried by the SDK with backoff before it surfaces; harmless, but a client that reads `error.type` can skip straight to another model. SDK default request timeouts (600s in the official clients) already cover the 480s fill ceiling. **`retry_max_tokens`:** a 503 `below_floor` (and a 404 from `/v1/quote`) carries `error.retry_max_tokens` whenever some smaller ceiling would have cleared. It is exact, not a guess: that value fills and one token more does not. Fillability is monotone in the ceiling — worst-case cost rises with `max_tokens` while a source's book does not — so if the field is absent from a margin-floor refusal, no ceiling works and the model is genuinely unavailable right now. Two 503s share the `below_floor` name and only the first carries the hint. If the message says no source is within your `max_input_per_1m` / `max_output_per_1m` ceiling, the refusal is about the RATE, not the size of your ask — rates are per million tokens, so no smaller `max_tokens` changes the answer and the field is correctly absent. The model is available; your price bound is what excluded it, and the message names the cheapest rate on offer so you can decide whether to raise the bound. A 402 is a third case again: there the balance is short of the worst-case reserve, and a smaller ceiling genuinely would fill — the response does not currently compute that number for you. **Large `max_tokens`:** your ceiling is passed through as sent. Marketplace pods reserve KV against it, so under load a source can refuse a large ask and accept a small one for the identical prompt. Bu0y also retries the same source once on a transient upstream error, asking for `min(your ceiling, 4096)` — failover needs somewhere to fail over to, and when one marketplace is briefly not quoting the survivor is the only candidate. When the retry is what got through: the answer comes back with `finish_reason: "length"` and `bu0y.max_tokens_served` tells you the ceiling actually used, so a client can continue instead of falling back. Note the reserve is worst-case against your ceiling — a 32768 ask on a pooled source can hold ~$0.50 per in-flight request, so a thin balance plus a big ceiling can return 402 while a smaller ceiling fills. ### Streaming `"stream": true` relays the upstream answer as it is produced, in the standard OpenAI SSE shape: a role frame, `choices[0].delta.content` chunks, then a terminal frame carrying `finish_reason`, `usage` and the `bu0y` block, then `data: [DONE]`. Why it is worth using for anything long: - **First token in ~1s** instead of waiting out the whole generation. Clients with a 60s or 120s read timeout stop dying on large answers. - **No total deadline.** The buffered path has to assume the worst and caps at 480s; a stream only has to keep producing bytes. Measured live: a 123s generation that the previous 120s ceiling could not have completed at all. - **Settlement still lands before `[DONE]`.** The terminal frame is withheld until the ledger write returns, so a `[DONE]` you have seen is a request that is finished on our side too — the same guarantee the buffered path gives. **Reasoning models.** Chain-of-thought arrives in `choices[0].delta.reasoning`, kept out of `delta.content` so a client concatenating content gets the answer and nothing else. It is billed — it counts inside `completion_tokens` — and on a small `max_tokens` a model like kimi-k3 can spend the whole budget thinking and return `finish_reason: "length"` with an empty answer. Give reasoning models room. Hang up mid-stream and you are billed for the tokens that already reached you, estimated from what we sent and rounded down. You are not billed for the rest of an answer you never got. The same rule when the provider stops mid-answer (a stall, or a stream cut before its usage frame): the error frame carries `bu0y.billed_micros` and `completion_tokens` for what reached you, and a stream that broke before any output was delivered costs nothing. The pod keeps generating either way, and a completed answer read off the socket is a completed answer. A source that ignores the flag and answers in one piece is replayed as a single chunk rather than failed, so adding `stream: true` can never make a model stop working. **Dead routes.** A marketplace can list a model at five prices and refuse to serve it at three of them. When a route answers "model not available", Bu0y remembers that for an hour and quotes the next-cheapest route that actually works — at its own real price. The first request to discover a broken route still fails; the ones after it do not. **Timeouts / stalls:** buffered (non-streaming) fills spend a total budget of ~12s plus ~40s per 1k output tokens (floored at 1024, the same floor the reserve uses, so a small ask on a reasoning model is not cut off mid-answer), capped at 480s, so a large `max_tokens` is given time to land rather than being cut off. Set your client read timeout above the budget for the ceiling you send — a `max_tokens` of 2000 can legitimately wait ~90s on a loaded pod, and nothing reaches you until the whole answer is done. **Streaming removes that wait**: bytes start in about a second and the deadline becomes 60s of silence rather than a total, so long generations are limited by the model, not by us. Transient and capacity errors may try another source; `timeout`, `auth` and `malformed_response` do **not** fail over — in each case the upstream may already have billed, and a second execute would pay for a second answer you never asked for. A timeout returns 502 and your hold is released. ## Privacy Bu0y does not store prompts or completions. Billing metadata only. The filling marketplace still receives the prompt to run it. ## Changelog **2026-09-02 — slow and broken fills.** - Withdrawn the same day: for a few hours a large `max_tokens` was refused up front (400 `unservable_max_tokens`) when the model's recent speed could not finish it inside the ceiling. A ceiling is not a forecast, and the refusal cost agent loops a 400 and a retry on every request. A long answer that reaches the wall is handled by the wall, the route strikes and delivered-output billing, not refused in advance. - Timeout errors now say which clock ran out: our first-byte budget, the model's silence budget, the absolute wall, or the source's own gateway giving up before any byte (upstream 524/504). The venue is still never named. - New request hints `min_tokens_per_sec` and `max_seconds`: pay more for a route that finishes. Routes known to be slower are skipped; 503 `unmet_speed` when none is known to qualify. - A broken stream can be billed: when the provider stops mid-answer, the closing error frame carries `bu0y.billed_micros` and `bu0y.completion_tokens` for the output delivered. Keep the partial output; it was paid for. A stream that breaks before any output costs nothing. - Longer fills: absolute ceiling 480s (was 300s); mid-answer silence budget learned per model, 20s to 180s, 60s until a model has history. Set any client-side timeout above 480s. - Internal, no client change: a route that fails to finish three times in fifteen minutes leaves routing for an hour; timeout and broken-stream records now say which deadline fired and how the stream ended. ## Site map | URL | Purpose | |-----|---------| | https://bu0y.com/llms.txt | Short index | | https://bu0y.com/llms-full.txt | This file | | https://bu0y.com/docs | Human how-to (Cursor, Hermes, SDK) | | https://bu0y.com/docs.md | Markdown twin | | https://bu0y.com/models | Searchable catalog; copy model ids | | https://bu0y.com/points | Fill spend as points | | https://bu0y.com/account | Passkey desk | | https://discord.gg/85ebxAjKgz | Support | ## Out of scope for customers - No withdraw API - Operator CCTP / profit sweep are ops rails - Customers may deposit Base USDC for credits; they never approve Surplus SettlementV2