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.

  1. 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 →
  2. 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 →
  3. 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
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
  }'
OpenAI SDK
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,
});
Vision
# 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.
Env vars
# 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.

GET/models

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

POST/chat/completions

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

GET/balance

Your account id and API balance in USD.

Auth: Key

GET/allowance

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

GET/usage?limit=20

Your most recent requests: model, tokens, cost in USD, streaming or not.

Auth: Key

GET/tee/attestation?nonce=<hex>

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

GET/tee/receipts/{id}

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.

  1. 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).

  2. 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.

  3. 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.

StatusCodeWhen
400invalid_request_errorThe body isn't valid JSON, or a field such as max_tokens is out of range.
401invalid_api_keyThe Authorization header is missing, malformed or the key was revoked.
402insufficient_balanceYour balance can't cover the request's hold. Top up and retry.
403model_not_allowedThe model isn't served on Userouter (Claude Opus, Fable and Sonnet; Claude Haiku is). Nothing is held.
403upstream_not_allowedThe model is served by an upstream your x-userouter-upstreams header leaves out. Nothing is held.
404model_not_foundThe model id isn't in GET /models.
413request_too_largeThe request body is larger than 4 MB.
429rate_limit_exceededMore 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.
502upstream_errorThe provider is unreachable. Other provider errors pass through with their own status. You are not charged.
Error body
{
  "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

  1. quote(credits) prices the purchase against the listings.
  2. Approve USDC for the total plus a small slippage buffer.
  3. buy(credits, maxTotal, recipient, referrer) fills exactly that amount or reverts.
  4. 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.

  1. 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).

  2. 02

    List

    sell(amount, discountBps) escrows your CREDIT at one discount level. Orders in a level fill first in, first out.

  3. 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 ↗

Staking

Stake ROUTER here. Settles and mints each finalized hour's CREDIT.

0x0000…0000 ↗

Exchange

The marketplace: `sell`, `buy`, `buyAndActivate`, and seller claims.

0x0000…0000 ↗

ROUTER

The token you stake for CREDIT, on Elysium mainnet.

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

GET/api/agents/config/launch

Whether agent launches are open, the launch price in USD and the platforms.

Auth: None

POST/api/agents

Body { name, model, systemPrompt, description?, greeting?, avatar?, url? }. Creates an agent; returns its id and slug.

Auth: Session

POST/api/agents/:id/x/challenge

A one-time code and the post to publish from the agent's X account. Valid for an hour.

Auth: Session

POST/api/agents/:id/x/verify

Body { tweetUrl }. Reads the post and links its X account; one X account backs one agent.

Auth: Session

POST/api/agents/:id/launch

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

POST/api/agents/:id/chat

Body { message, chatId? }. Streams the agent's answer as server-sent events.

Auth: Session

GET/api/agents?launched=1

Agents with a listed token, newest launch first, each with launch { token, status, platform }.

Auth: None

GET/api/agents/:slug

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.

  1. 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.

  2. 02

    Launch on Elysium

    You sign the launch from your own wallet. The token starts on a bonding curve paired with HYPE.

  3. 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.

  4. 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.