Overview
apitokens.rent is an inference API. There is no subscription and no card.
$API generates creator fees on every trade, 30 basis points of it, forever. A keeper collects those once a minute and they pay for everything served here. Hold 10,000 $API and the API is open to you, unmetered.
POST /v1/chat/completions | Text, vision and image generation. |
GET /v1/models | The catalogue, with prices. |
GET /v1/access | Whether a key can run anything, and why. |
GET /api/state | The public ledger. No key required. |
GET /api/series?days= | Daily activity, hourly at one day. |
Access
How it works
There is no balance, no quota and no credit. Holding $API is the entire subscription. Hold at least 10,000 $API and you can run every model in the catalogue as much as you like; hold less and you can run nothing.
How much you hold changes nothing. It is a threshold, not a weight. A wallet holding a million tokens gets exactly the same service as one holding 10,000, because what is being shared is a service rather than a pot of money to divide.
Nothing to claim | Access is on as soon as the balance clears 10,000. |
Nothing to stake | The tokens stay in your own wallet. Nothing is locked or transferred. |
Checked live | Every request reads the balance from the chain, cached for a minute. Sell and access stops within a minute; buy and it starts within a minute. |
Limits
Unmetered does not mean unbounded. The treasury is one shared pool paying one upstream bill, so there are rails, and they are rate limits rather than balances.
120 / minute | Per wallet, always on. It exists to stop a runaway loop, which is what almost every accidental spend actually is. |
Daily ceilings | A request count and a spend figure, both off by default. They are there so an operator has a lever if one script starts drinking the treasury, not as a quota you are expected to watch. |
Who pays
You never do. $API generates creator fees on every trade, and a keeper collects them into the treasury once a minute. The treasury is one ordinary Solana wallet: the same one $API was launched from, because pump.fun pays those fees only to that address and the field can never be reassigned.
Inference is bought from an upstream provider that bills in dollars, so the two do not touch directly. The operator moves value from the treasury to the upstream account. Nothing about that step is automatic, and this page will not pretend otherwise: it is a person converting SOL and topping up a balance.
What is automatic is the measurement. Rewards claimed and inference served are both counted as they happen, and the runway on the front page is the treasury divided by the last seven days of real spend. That figure is what tells an operator when to top up, and it is what tells you whether this can keep going.
Authentication
Two ways in, one wallet
This is the question the site gets asked most, so plainly: there are two front doors, and both of them are asking the same question about the same wallet.
The chat on this site | Authenticated by a wallet signature stored in a session cookie. No key is involved, which is why a model page never asks for one. You sign once and the browser is authorised. |
The API | Authenticated by a bearer key, because your own script has no wallet and cannot sign anything. That is the only reason keys exist: to say which wallet is asking. |
Either way the holding is what decides the answer. Both paths run through the same code and appear in the same usage log: chat requests are tagged chat, API requests show the last four characters of the key that made them.
Creating a key
Connect a wallet holding 10,000 $API on the API keys page and press New key. The secret is shown once, in a dialog, and never again.
export API_TOKEN_KEY="sk-api-..."A wallet's keys all carry the same access. Several exist so you can revoke one without disturbing the rest, not so you can divide anything between them.
Where keys live
Only the SHA-256 of a key is stored. That is enough to look one up on the hot path and not enough to reconstruct it from a database dump, which is why there is no reveal endpoint: a lost key is replaced, not recovered.
Chat completions
Request
Wire-compatible with OpenAI chat completions. Change the base URL and the key; change nothing else.
The body is forwarded upstream almost unchanged, so parameters this page has never heard of work as soon as the upstream supports them. Only usage is overridden, because cost accounting is not optional here.
curl https://apitokens.rent/v1/chat/completions \
-H "Authorization: Bearer $API_TOKEN_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-opus-5",
"messages": [
{"role": "user", "content": "Write a haiku about creator fees."}
]
}'x-credits-remaining-usd | Balance at the time the request was admitted, in dollars. |
x-ratelimit-remaining | Requests left in the current minute. |
Streaming
Server-sent events, byte for byte the upstream's. Cost is only known once a stream finishes, so the debit lands after the last chunk. A client that disconnects early leaves the request unbilled.
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://apitokens.rent/v1",
apiKey: process.env.API_TOKEN_KEY,
});
const stream = await client.chat.completions.create({
model: "anthropic/claude-opus-5",
messages: [{ role: "user", content: "Hello" }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}Sending images
Any model whose card shows vision accepts pictures. Send a message whose content is an array of parts rather than a string. Data URLs and public https URLs both work.
client.chat.completions.create(
model="anthropic/claude-opus-5",
messages=[{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}},
{"type": "text", "text": "What is in this screenshot?"},
],
}],
)In the browser chat, drop a file onto the composer, paste from the clipboard, or use the attach button. Images are capped at 4 MB each because base64 inflates by a third and the whole conversation is resent on every turn.
Generating images
Models that answer with pictures rather than words are requested the same way and answer differently: not streamed, because an image arrives as one blob at the end. Generated files are written to storage server-side and returned as URLs, so a response is a link rather than two megabytes of base64.
{
"text": "",
"media": [
{ "url": "https://.../token-media/<wallet>/<hash>.png", "mimeType": "image/png" }
],
"model": "google/gemini-3-pro-image",
"costUsd": 0.039
}Models
Unauthenticated. What models exist and what they cost is the offer, and an offer nobody can read before signing up is not much of one. Prices are USD per million tokens, with whatever margin this deployment is configured for already applied.
curl https://apitokens.rent/v1/modelsThe catalogue is fetched live from the upstream and cached for ten minutes, so a model listed here is a model that works right now. Pass any id as model.
Checking access
Cheap enough to poll. Useful before a long job, so a script finds out its wallet no longer qualifies before a batch is half done rather than after.
curl https://apitokens.rent/v1/access \
-H "Authorization: Bearer $API_TOKEN_KEY"{
"object": "access",
"active": true,
"holding": 138400,
"required": 10000,
"requests": 412,
"spent_usd": 3.91
}spent_usd is what this wallet's requests have cost the treasury. It is shown for transparency and is not a bill, a limit, or anything you are asked to settle.
Public data
Every figure the site states about itself is served from the same two endpoints it renders from, so a scraper and a visitor cannot be told different numbers.
# claimed, issued, spent, coverage, holders, market data
curl https://apitokens.rent/api/state
# the chart series: hourly at one day, daily beyond
curl "https://apitokens.rent/api/series?days=30"Errors
The envelope is OpenAI's, so your client library already raises the right exception for each of these. Upstream errors are relayed verbatim rather than reshaped, and nothing is charged for a request that produced no tokens.
401 invalid_api_key | Unknown or revoked key. |
403 not_a_holder | This wallet holds fewer than 10,000 $API. Hold that much and the next request goes through, within a minute. |
403 not_launched | The coin does not exist yet, so nobody holds it. |
429 rate_limit_exceeded | More than 120 requests in one minute. |
429 daily_limit_reached | A daily ceiling was hit. Both are off by default; if you see this, an operator turned one on. |
502 upstream_unreachable | The model provider could not be reached. |
503 upstream_unconfigured | This deployment has no upstream inference key set. An operator problem, not yours. |
Rate limits
120 requests per minute per wallet, counted in a fixed window shared by both front doors. A fixed window lets through at most two windows' worth across a boundary, which is fine for a limit whose job is to stop a runaway loop rather than to meter anything.