Sell from your own server
Run an open model on your own GPUs, put HTTPS in front, and paste one URL in the console. We test it, list it at your price, and send it buyers' requests when it is the best offer.
What you need
- An OpenAI-compatible APIIt answers
GET /v1/modelswith adatalist of models andPOST /v1/chat/completions, streamed (server-sent events) and not streamed. - Public HTTPSA host name on the internet with a certificate from a public authority (Let's Encrypt is fine), on port 443 or a port from 1024 up. Self-signed certificates and plain http are refused.
- A base URL ending in /v1We add
/modelsand/chat/completionsto what you paste, so paste the part before them:https://llm.example.com/v1. - A key, if you want oneOptional. If your server asks for one, we send it as
Authorization: Bearer <key>and nothing else. It is sealed with the URL when you save them, and never shown again.
Any model your server serves can be listed, as long as its licence allows commercial serving and no one else's API key is behind your server: that is the statement you accept before going live (own-server-v2).
Set up your server
Each setup below serves Qwen3 32B on 127.0.0.1:8000, where only the machine itself reaches it, and puts Caddy in front for HTTPS. Point a DNS record (llm.example.com) at the machine and open ports 80 and 443; Caddy gets the certificate on its first start.
HTTPS with Caddy (every setup)
# /etc/caddy/Caddyfile: Caddy gets and renews the certificate on its own
llm.example.com {
reverse_proxy 127.0.0.1:8000
}Then sudo systemctl reload caddy. Caddy passes streamed answers through as they come. Any other reverse proxy works if it has a public certificate and does not buffer server-sent events.
vLLM
export OWN_KEY=$(openssl rand -hex 32) # keep it: you paste it in the console
vllm serve Qwen/Qwen3-32B \
--host 127.0.0.1 --port 8000 \
--api-key "$OWN_KEY" \
--max-model-len 32768It lists the model as Qwen/Qwen3-32B, which is qwen3-32b here, with its context length.
Paste in the console: https://llm.example.com/v1 and your key.
SGLang
export OWN_KEY=$(openssl rand -hex 32)
python -m sglang.launch_server \
--model-path Qwen/Qwen3-32B \
--host 127.0.0.1 --port 8000 \
--api-key "$OWN_KEY"Paste in the console: https://llm.example.com/v1 and your key.
llama.cpp server
export OWN_KEY=$(openssl rand -hex 32)
llama-server -hf Qwen/Qwen3-32B-GGUF:Q4_K_M \
--alias qwen3-32b \
--host 127.0.0.1 --port 8000 \
--api-key "$OWN_KEY" \
--jinja -c 32768--alias is the id /v1/models lists: name it after the model you serve. --jinja uses the model's own chat template, which tool calls need.
Paste in the console: https://llm.example.com/v1 and your key.
Ollama, behind Caddy
Ollama has no key of its own and serves plain http, so Caddy does both: HTTPS, and a 401 for any request without your key.
# the model, by its size tag (listed as qwen3-32b), kept in memory
ollama pull qwen3:32b
OLLAMA_KEEP_ALIVE=-1 ollama serve # listens on 127.0.0.1:11434
# /etc/caddy/Caddyfile: TLS, and the key Ollama itself does not check
llm.example.com {
@nokey not header Authorization "Bearer {$OWN_KEY}"
respond @nokey 401
reverse_proxy 127.0.0.1:11434
}Start Caddy with OWN_KEY set in its environment. Pull models by their size tag: qwen3:32b is listed as qwen3-32b, but qwen3:latest keeps “latest” in its id and matches no model in our catalog.
Paste in the console: https://llm.example.com/v1 and your key.
Test it yourself
From another machine, before you paste the URL: the two calls we make first.
export BASE=https://llm.example.com/v1
export OWN_KEY=… # the key you set, if any
# 1. the model list: a "data" array with your model's id
curl -s $BASE/models -H "Authorization: Bearer $OWN_KEY"
# 2. a streamed answer: data: lines, then data: [DONE]; the last chunk carries "usage"
curl -sN $BASE/chat/completions -H "Authorization: Bearer $OWN_KEY" -H "Content-Type: application/json" \
-d '{"model": "Qwen/Qwen3-32B", "stream": true, "stream_options": {"include_usage": true}, "max_tokens": 16,
"messages": [{"role": "user", "content": "Say hi"}]}'Use the id the first call lists as model (qwen3-32b for llama.cpp and Ollama). The second call should print data: lines as the answer streams, a last chunk with usage, and data: [DONE].
Model ids
We read the ids at GET /v1/models and map each one to a model in our catalog: lowercased, the organisation before the last / dropped, an Ollama size tag joined to the name, Instruct dropped, then our alias table. So Qwen/Qwen3-32B, qwen3-32b and Ollama's qwen3:32b are the same model, and meta-llama/Llama-3.3-70B-Instruct is llama-3.3-70b. If two of your ids map to the same model, the first is offered.
A model in our catalog takes its official price as the reference, and you sell into its market. An id that maps to nothing we know is listed too, as its own model, at a price you set. Context length is read from your list (max_model_len, context_length): nothing to fill in.
What happens next
- 1Check keyIn Sell › Providers (open it), pick Your own server, paste the URL and the key, and Check key. The URL and key are sealed together, and we read your model list: a few seconds.
- 2Health test and identity checksOne short streamed request per model, whose answer must name the model, then a fixed prompt that checks token counts and max_tokens. A model that fails is not added; the wizard says why and links the fix below.
- 3PricingEvery model starts on Match the best offer: we keep your price one step under the best other offer, never under your floor. Or set your own price; a model with no reference needs one. Pricing has the details.
- 4Go liveAccept the own-server statement and go live, within about a minute. A request comes to you when your offer is the best one for its model; you earn your price on the tokens the buyer is billed for.
- 5Random checksWe test your models at random with real prompts, about once an hour per model. A model that fails is checked again at once with another prompt; if it fails again, a full identity check runs. It is not unlisted. A model that errors or times out while serving gets no traffic for a short pause that grows with each failure, until a request or our 5-minute ping succeeds. A request that fails is not billed to the buyer, and you are not paid for it.
- 6PayoutsEarnings are payable 7 days after the request is billed (pending until then, in case a buyer's card payment is reversed). Payouts are sent in batches once your balance reaches $5. They are USDC on Base, to a wallet signed in to your account. Earnings and payouts explains the rest.
Troubleshooting
The wizard links the entry for each failure.
- TLS or connection errors
We connect over HTTPS only and check the certificate like a browser: it must come from a public authority and name your host. Self-signed and private-CA certificates fail, and so does a bare IP address without one. Check that the port is open to the internet (443, or 1024 and up), that a firewall does not drop us, and that
curl https://llm.example.com/v1/modelsworks from another network. Caddy in front of your server solves most of this. - 401 or 403
Your server refused the key. The key in the console must be the one your server expects (vLLM's and SGLang's
--api-key, llama.cpp's--api-key, the Caddy check for Ollama), and it is sent asAuthorization: Bearer <key>. A server with no key needs the field left empty. While live, a 401 or 403 stops traffic to the server for an hour; fix the key with Rotate on Positions. - 404 on /models, or no models: the URL misses /v1
Paste the base URL, ending in
/v1: we add/modelsto it, sohttps://llm.example.comasks for/modelsand most servers answer 404. Paste nothing after/v1either.GET /v1/modelsmust answer 200 with{"data": [{"id": "…"}]}. We do not follow redirects: paste the final https address. An empty list means the server has not loaded a model yet. - A model id we don't know
Every id your server lists is offered, mapped by the rule in Model ids. An id that maps to no model in our catalog has no reference price: you set your own price for it. To sell into a known model's market, serve it under that model's id (vLLM and SGLang
--served-model-name, llama.cpp--alias). If the health test saysunavailable, your server answered 404 for the id: chat completions must accept the exact id/v1/modelslists. - Timeouts
/v1/modelsmust answer within 20 seconds. The health test waits 30 seconds for the first streamed token and 60 seconds in all. When live, a request waits about 10 seconds for your first token before it moves to the next source, so keep the model loaded and warm: a cold start or a model swapped out of memory looks like a timeout. For Ollama, setOLLAMA_KEEP_ALIVE=-1. - The address was refused
We only reach public addresses. The host name must resolve, and every address it resolves to must be public: private (10.x, 172.16-31.x, 192.168.x), loopback, link-local, carrier-grade NAT (100.64.x), IPv6 unique-local and other reserved ranges are refused. Names like
localhostor*.localnever work, and neither does a URL with a user name, a password, a query string or a port under 1024 other than 443. - Bad request, stream error or server error
Your server must take an OpenAI chat request as it is:
stream: truewithstream_options.include_usage, andtemperature,seed,max_tokensand tools when a buyer sends them. A stream must be server-sent events ending withdata: [DONE]. Run the test above: a 400 or a broken stream there is what the health test saw. Answers withoutusagestill work, but we then estimate the tokens. - Answers as another model, or identity checks failed
The
modelfield of each answer must be the id you listed (or left out). The identity checks then send a fixed prompt and compare the token counts your server reports with that model's, check thatmax_tokensis respected, and that nothing long is added to the prompt. A different model under a known model's id, a chat template that adds a long system prompt, or usage counts that are off fail them. List the model under its own id instead.