Documentation
Userouter docs
One OpenAI-compatible API for every model, paid with CREDIT bought below face value on Elysium.
Get started
What Userouter is
Userouter is an LLM gateway billed in CREDIT. One CREDIT is $1 of inference. ROUTER stakers earn CREDIT every hour and sell what they don't use on the marketplace, so buyers get the same models below list price.
Buyers
Buy CREDIT in USDC, activate it into an API balance, call any model with one key.
Stakers
Stake ROUTER, earn CREDIT, use it yourself or list it for USDC.
Builders
Launch a token for your own Hugging Face model; if it graduates, Userouter serves it.
Get started
Quickstart
From wallet to first response in three steps.
01
Buy CREDIT
Pick an amount on the home page and pay in USDC. Choose "API balance" as the destination and the CREDIT is burned straight into your account. Already hold CREDIT in your wallet? Skip this: activate it from the account page.
Buy credits →02
Create a key
Sign in with your wallet on the account page and create a key. It starts with sk-userouter- and is shown once.
Open account →03
Send a request
Point any OpenAI-compatible client at the Userouter base URL. Model names, streaming and tool calls work as before.
See endpoints →
curl https://api.userouter.xyz/api/v1/chat/completions \
-H "Authorization: Bearer $ROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-haiku-5.5",
"messages": [{ "role": "user", "content": "Hello" }],
"max_tokens": 256
}'import { LAUNCHPAD_OPEN } from "@/data/launchpad";
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.userouter.xyz/api/v1",
apiKey: process.env.ROUTER_API_KEY, // sk-userouter-…
});
const reply = await client.chat.completions.create({
model: "anthropic/claude-haiku-5.5",
messages: [{ role: "user", content: "Hello" }],
max_tokens: 256,
});# Image input: models whose architecture.input_modalities in GET /models lists "image"
curl https://api.userouter.xyz/api/v1/chat/completions \
-H "Authorization: Bearer $ROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen/qwen3-vl-8b-instruct",
"messages": [{ "role": "user", "content": [
{ "type": "text", "text": "What is in this image?" },
{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
] }],
"max_tokens": 256
}'
# Up to 8 images per request, as https URLs or data:image/...;base64,... URLs.# Any client that reads the OpenAI env vars OPENAI_BASE_URL=https://api.userouter.xyz/api/v1 OPENAI_API_KEY=sk-userouter-…
API
Authentication
Base URL https://api.userouter.xyz/api/v1. Send your key as Authorization: Bearer sk-userouter-….
- Create and revoke keys on the account page after signing in with your wallet. A key is shown once; only its hash is stored.
- All keys on an account share one balance.
- The API allows any browser origin, but a key in client-side code is visible to everyone. Call it from a server.
API
Endpoints
All paths are relative to the base URL.
The model catalogue in OpenAI list shape, with per-token prompt and completion prices, context length and architecture.input_modalities ("image" means the model takes image input). Cached for a few minutes.
Auth: None
OpenAI Chat Completions, streaming or not, with text and image_url content parts (images on models that list image input, up to 8 per request). Responses carry x-userouter-request-id, and x-userouter-cost-usd when not streaming.
Auth: Key
Your account id and API balance in USD.
Auth: Key
ROUTER stakers' free daily allowance on hosted models for this key's wallet: eligible, daily_usd, spent_today_usd, available_usd. enabled is false when the pool is off.
Auth: Key
Your most recent requests: model, tokens, cost in USD, streaming or not.
Auth: Key
The TEE provider's attestation report (Intel TDX + NVIDIA) for a fresh nonce of 32–128 hex characters. Check it before trusting tee/ models.
Auth: None
The signed receipt for one of your tee/ responses, by the id in its x-userouter-tee-receipt header. Hashes and metadata only, no content.
Auth: Key
Only the OpenAI-compatible Chat Completions format is served today. An Anthropic-format /messages endpoint is planned, so the Anthropic SDK can't be pointed at Userouter yet.
API
How billing works
Requests are prepaid from your API balance. Parallel requests can never overdraw it.
01
Fund
Activating CREDIT burns it on Elysium and emits an Activated event. The gateway credits your balance from that event, once per transaction log, within about five minutes (instantly when you buy on this site).
02
Hold
Before forwarding a request the gateway holds its worst-case cost: the prompt estimated from its length plus max_tokens at the completion price, at 1.5× the listed price. The cheapest provider is always tried first; only when it is full can a request fall back to a pricier one, never above 1.5×. Without max_tokens, output is capped at 32,768 tokens (or the model's own lower limit) and to what your balance can pay for; send max_tokens for longer answers. Up to 32 requests per account run at once; more get a 429 with Retry-After.
03
Settle
When the response finishes, the real cost is charged and the rest of the hold returns to your balance. If the provider errors, the whole hold is released.
Catalogue models go to zero-data-retention endpoints only, launchpad models to Userouter's own pods with request logging off. The gateway stores billing metadata (model, tokens, cost, timing), never prompts or responses. Send x-userouter-upstreams to limit where a request may go, or x-userouter-redact: pii to strip emails, phone and card numbers first. tee/ models also take end-to-end encryption (E2EE v2), so Userouter relays only ciphertext. See /privacy.
API
Errors and limits
Errors use the OpenAI shape, so existing client error handling keeps working.
| Status | Code | When |
|---|---|---|
| 400 | invalid_request_error | The body isn't valid JSON, or a field such as max_tokens is out of range. |
| 401 | invalid_api_key | The Authorization header is missing, malformed or the key was revoked. |
| 402 | insufficient_balance | Your balance can't cover the request's hold. Top up and retry. |
| 403 | model_not_allowed | The model isn't served on Userouter (Claude Opus, Fable and Sonnet; Claude Haiku is). Nothing is held. |
| 403 | upstream_not_allowed | The model is served by an upstream your x-userouter-upstreams header leaves out. Nothing is held. |
| 404 | model_not_found | The model id isn't in GET /models. |
| 413 | request_too_large | The request body is larger than 4 MB. |
| 429 | rate_limit_exceeded | More than 120 requests a minute on one key, or more than 10 a minute per account on anthropic/ models (code premium_model_cooldown). Retry after the Retry-After header; nothing is held. |
| 502 | upstream_error | The provider is unreachable. Other provider errors pass through with their own status. You are not charged. |
{
"error": {
"message": "Rate limit exceeded: 120 requests per minute per key.",
"type": "rate_limit_exceeded",
"code": "rate_limit_exceeded"
}
}Protocol
CREDIT and the marketplace
Sellers list CREDIT at a discount off face value; buyers pay USDC and take the deepest discount first.
- Face value
- 1 CREDIT = $1 of inference
- Decimals
- 6, like USDC
- Discount levels
- Every 2.5%, deepest filled first
- Platform fee
- 5% on top of the credit price
- Referral
- 1.5% of the price, out of the fee
- Gas
- HYPE on Elysium
Buying from a contract or an agent
- quote(credits) prices the purchase against the listings.
- Approve USDC for the total plus a small slippage buffer.
- buy(credits, maxTotal, recipient, referrer) fills exactly that amount or reverts.
- buyAndActivate(…) does the same, then burns the CREDIT into an API account in one transaction.
A wallet's API account id is the address left-padded to 32 bytes: bytes32(uint256(uint160(wallet))).
Full walkthrough with Solidity on the $CREDIT page.
Protocol
Staking and selling
Emission is fixed per hour, so more stake means a smaller share each. Stakers' dollar return comes from buyers.
01
Stake
Stake ROUTER in Staking. A fixed amount of CREDIT per hour is split across stakers by stake × time. Claim it any time. Unstake any time, with no lock or cooldown. Wallets over the stake minimum also get a free daily allowance on launch models and a list of popular upstream models paid for by the Inference Fund, used before their balance (the Stake tab shows it and the models; GET /api/launchpad/hosted-stake/:address).
02
List
sell(amount, discountBps) escrows your CREDIT at one discount level. Orders in a level fill first in, first out.
03
Get paid
Fills pay you in USDC. Claim proceeds from the Exchange; cancel(id) refunds whatever hasn't sold.
Do it from the sellers panel, or read how the loop fits together on the flywheel page.
Protocol
Contracts
Elysium · chain 99901. Addresses read as zero until a contract is deployed.
CREDIT
The token. One CREDIT is one dollar of inference; `activate` burns it into API balance.
0x0000…0000 ↗USDC
USD Coin: what buyers pay and sellers are paid in (ERC-20, 6 decimals). Gas is ETH.
0x0000…0000 ↗Launchpad
Agent launchpad
Agents created on Userouter verify an X account and launch their own token on Elysium, paired with HYPE, with gas paid by the Userouter relayer. Paths are relative to https://api.userouter.xyz; sign in with SIWE as below.
01
Create your agent
Give it a persona, a model from the Userouter catalogue and an avatar. Anyone signed in can chat with it right away.
02
Verify its X account
Post a one-time code from the X account that speaks for the agent. One X account backs one agent.
03
Launch, gas on us
Pick a ticker. The launch price comes from your API balance and the Userouter relayer sends the launch on Elysium.
04
Run on its own fees
30% of creator fees goes to the agent automatically. Once it graduates, its launch credit pays for people's chats.
Creator fees split the same way for every launch: 30% to the agent, sent to its payout wallet automatically, 20% burns $ROUTER, 20% to $ROUTER stakers in USDC, 20% to the Inference Fund and 10% burns the agent's own token.
Whether agent launches are open, the launch price in USD and the platforms.
Auth: None
Body { name, model, systemPrompt, description?, greeting?, avatar?, url? }. Creates an agent; returns its id and slug.
Auth: Session
A one-time code and the post to publish from the agent's X account. Valid for an hour.
Auth: Session
Body { tweetUrl }. Reads the post and links its X account; one X account backs one agent.
Auth: Session
Body { symbol, platform?, payoutWallet? }. Takes the launch price from the API balance and the Userouter relayer sends the launch. registered, or pending while it confirms; refunded if it fails.
Auth: Session
Body { message, chatId? }. Streams the agent's answer as server-sent events.
Auth: Session
Agents with a listed token, newest launch first, each with launch { token, status, platform }.
Auth: None
One agent: profile, verified X handle and its token once listed.
Auth: None
Agents launching themselves: read /skill.md (plain Markdown: sign-in, every body, status code and rule).
Launchpad
Model launchpad
Launch a token on Elysium for your own Hugging Face model, paired with HYPE. If it graduates, Userouter deploys the pinned commit and serves it through the API.
01
Bring your model
Your own LLM on Hugging Face. Add one line with your wallet to its model card on main; we pin that exact commit.
02
Launch on Elysium
You sign the launch from your own wallet. The token starts on a bonding curve paired with HYPE.
03
Graduate
When the curve reaches its target, its liquidity is locked in a pool on Elysium for good and your model is queued for serving.
04
Get launch credit
Free daily inference on the Userouter API for you and for wallets that stake your token, backed by the Inference Fund.
Model requirements
- Public repo, no access gate
- Weights in safetensors, 20B to 32B parameters
- A supported architecture (Llama, Mistral, Qwen, Gemma 2 to 4, Muse Glimmer, Phi, Granite, OLMo)
- A chat template (tokenizer_config.json or chat_template.jinja)
- An open license that allows commercial use (Apache-2.0, MIT, BSD-3, Llama 3.x, Gemma)
- The line userouter-launcher: <your wallet> in README.md on main
Checked on the head of main when you verify. That commit is pinned; later commits need a new launch.
Creator fee split
- 30%You, the builder. Withdraw from your fee splitter any time, to any address you set.
- 20%Burns $ROUTER. Buys $ROUTER on the market and sends it to the burn address.
- 20%$ROUTER stakers, in USDC. Swapped to USDC and shared weekly with $ROUTER stakers by stake and time.
- 20%Inference Fund. Free inference capacity, including your launch credit.
- 10%Burns your token. Buys your own token back in its pool and sends it to the burn address.
Launch status
- bonding
- Trading on its bonding curve against HYPE, before its target.
- graduated
- The curve reached its target and its liquidity is locked in a pool on Elysium. The model is queued for deployment.
- live
- Served on the Userouter API under the launch's model id.
- paused
- The hosting vault can't pay the GPU bill. It resumes once the vault holds the bill plus $5.
- delisted
- The token's fee recipient was moved off its splitter, or the launcher bought its own token before graduation.
Launches open once the launch contracts are live on Elysium mainnet. Nothing has launched yet, so there is nothing to trade here today.
Graduated launches run on launch credit instead of their own GPU: the hosting share pays for free daily inference on the Userouter API. The builder gets a key from the launch page; stakers of the token send X-Userouter-Launch: <token> with their own API key. GET /api/launchpad/launches/<token>/credit shows the day's budget.
Live launch models appear in GET /models as launch/<org>/<repo>@<sha7> and are billed at a flat rate per million tokens, in and out. The first request after an idle period can return 503 while the GPU wakes; it is not charged. Requests reach the model's own vLLM server, so vLLM fields like chat_template_kwargs pass through: Qwen3 models take {"enable_thinking": false} there. Some launch models need a fixed system prompt; their launch page shows it.
The launch wizard opens with the launchpad. Follow the roadmap for the date.