Documentation
Surplus docs
One OpenAI-compatible API for every model, paid with CREDIT bought below face value on Robinhood Chain.
Get started
What Surplus is
Surplus is an LLM gateway billed in CREDIT. One CREDIT is $1 of inference. SURPLUS stakers earn CREDIT every hour and sell what they don't use on an order book, so buyers get the same models below list price.
Buyers
Buy CREDIT in USDG, activate it into an API balance, call any model with one key.
Stakers
Stake SURPLUS, earn CREDIT, use it yourself or list it for USDG.
Builders
Launch a token for your own Hugging Face model; if it graduates, Surplus 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 USDG. 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-surplus- and is shown once.
Open account →03
Send a request
Point any OpenAI-compatible client at the Surplus base URL. Model names, streaming and tool calls work as before.
See endpoints →
curl https://api.surplusllm.com/api/v1/chat/completions \
-H "Authorization: Bearer $SURPLUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5",
"messages": [{ "role": "user", "content": "Hello" }],
"max_tokens": 256
}'import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.surplusllm.com/api/v1",
apiKey: process.env.SURPLUS_API_KEY, // sk-surplus-…
});
const reply = await client.chat.completions.create({
model: "anthropic/claude-sonnet-5",
messages: [{ role: "user", content: "Hello" }],
max_tokens: 256,
});# Any client that reads the OpenAI env vars OPENAI_BASE_URL=https://api.surplusllm.com/api/v1 OPENAI_API_KEY=sk-surplus-…
API
Authentication
Base URL https://api.surplusllm.com/api/v1. Send your key as Authorization: Bearer sk-surplus-….
- 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 and context length. Cached for a few minutes.
Auth: None
OpenAI Chat Completions, streaming or not. Responses carry x-surplus-request-id, and x-surplus-cost-usd when not streaming.
Auth: Key
Your account id and API balance in USD.
Auth: Key
Your most recent requests: model, tokens, cost in USD, streaming or not.
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 Surplus 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 Robinhood Chain and emits an Activated event. The gateway credits your balance from that event, once per transaction log, within about a minute (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. Without max_tokens, output is capped to what your balance can pay for.
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.
Every request goes to zero-data-retention endpoints only. The gateway stores billing metadata (model, tokens, cost, timing), never prompts or responses.
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. |
| 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. |
| 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 order book
Sellers list CREDIT at a discount off face value; buyers pay USDG and take the deepest discount first.
- Face value
- 1 CREDIT = $1 of inference
- Decimals
- 6, like USDG
- 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
- ETH on Robinhood Chain
Buying from a contract or an agent
- quote(credits) prices the purchase against the book.
- Approve USDG 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 SURPLUS in Staking. A fixed amount of CREDIT per hour is split across stakers by stake × time. Claim it any time.
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 USDG. 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
LLM launchpad
Launch a Pons token for your own Hugging Face model. If it graduates, Surplus 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 Pons
You sign the launch from your own wallet, so Robinhood Chain records you as the deployer. The token trades on an ETH bonding curve.
03
Graduate at 4.2 ETH
When the curve fills, Pons moves the liquidity into a Uniswap v4 pool that is locked forever.
04
Go live on Surplus
We deploy the pinned commit and serve it through the Surplus API, paid in CREDIT like every other model.
Model requirements
- Public repo, no access gate
- Weights in safetensors, at most 9B parameters
- A supported decoder architecture (Llama, Mistral, Qwen, Gemma, Phi, Granite, OLMo)
- A chat template in tokenizer_config.json
- A license that allows commercial serving (Apache-2.0, MIT, BSD-3, Llama 3.x, Gemma)
- The line surplus-launcher: <your wallet> in README.md on main
Creator fee split
- 60%Hosting vault. Keeps your model's GPU running. Every spend is on-chain with an invoice reference.
- 30%You, the builder. Withdraw from your fee splitter any time, to any address you set. You also earn 30% of what your live model takes in on the Surplus API, as API balance.
- 10%Burns $SURPLUS. Buys $SURPLUS on the market and sends it to the burn address.
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.
Start on the launchpad.
Protocol
Contracts
Robinhood Chain · chain 4663. 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.
0x9975…16DA ↗USDG
Global Dollar: what buyers pay and sellers are paid in (ERC-20, 6 decimals). Gas is ETH.
0x5fc5…d168 ↗