Quickstart
Create an account, copy its API key and call a model from curl, Python or JavaScript.
1. Create an account
Open app.example.com/login and sign in with an Ethereum wallet: the first sign-in creates your account. The wallet signs a message, which costs no gas. There is no username, password, email address, phone number or name.
2. Copy your API key
Your API key is a session token that starts with sk-sv-user-. Open the account page and copy it. The key on the account page belongs to that browser session: signing out of the web app revokes it. For scripts and servers, sign in once more in another browser window, copy that key and close the window without signing out: each sign-in is a separate session, so it survives signing out in your usual browser.
A session token is valid for 14 days. Keep it secret: anyone who has it can spend your credit. Authentication covers expiry, revocation and wallet accounts.
To use the key in OpenCode, Claude Code, Codex, Cline or another coding tool, follow Integrations for the client's configuration and API requirements.
3. Get credit
Paid models are charged per token from your account's credit. If your wallet holds enough of the Sevren token, its free try and the holder plan's free tokens of the day on that model are spent first. Prices, plans and spending order are in Billing; the free tokens per model are in Holder benefits.
To add credit, open the account page and pay with ETH or USDG on Robinhood Chain. The whole payment becomes credit after 900 block confirmations, usually 1 to 2 minutes later. Payments are final and public: they cannot be withdrawn or refunded. Payments has the details.
4. Call a model
Send the key as a bearer token. Reasoning models spend part of max_tokens on thinking before they answer, so give them room.
export SEVREN_API_KEY="sk-sv-user-…"
curl https://api.example.com/v1/chat/completions \
-H "Authorization: Bearer $SEVREN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "sevren-lite-27b",
"max_tokens": 4096,
"messages": [
{"role": "system", "content": "Answer briefly."},
{"role": "user", "content": "What does an abliterated model mean?"}
]
}'The answer is an OpenAI chat.completion object. The text is in choices[0].message.content and the token counts are in usage.
Python
The official openai package works unchanged with the Sevren base URL.
# pip install openai
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.example.com/v1",
api_key=os.environ["SEVREN_API_KEY"],
)
response = client.chat.completions.create(
model="sevren-lite-27b",
max_tokens=4096,
messages=[{"role": "user", "content": "Write a haiku about entropy."}],
)
print(response.choices[0].message.content)
print(response.usage)Streaming works the same way. Ask for include_usage to receive the token counts in the last chunk.
stream = client.chat.completions.create(
model="sevren-lite-27b",
max_tokens=4096,
stream=True,
stream_options={"include_usage": True},
messages=[{"role": "user", "content": "List three uses of a hash function."}],
)
for chunk in stream:
if chunk.choices:
delta = chunk.choices[0].delta
# Thinking text arrives as delta.reasoning before the answer.
reasoning = getattr(delta, "reasoning", None)
if reasoning:
print(reasoning, end="", flush=True)
if delta.content:
print(delta.content, end="", flush=True)
if chunk.usage:
print("\n", chunk.usage)The OpenAI packages require an api_key. Use your Sevren API key; an invalid or expired key is rejected with 401.
JavaScript
A streaming request with fetch and no dependencies. Thinking text goes to standard error and the answer to standard output.
// stream.mjs — run with: SEVREN_API_KEY=sk-sv-user-… node stream.mjs (Node 18 or later)
const response = await fetch("https://api.example.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + process.env.SEVREN_API_KEY,
},
body: JSON.stringify({
model: "sevren-lite-27b",
max_tokens: 4096,
stream: true,
stream_options: { include_usage: true },
messages: [{ role: "user", content: "Summarize how TLS works." }],
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(response.status + " " + error.code + ": " + error.message);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
for (;;) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
let end;
while ((end = buffer.indexOf("\n\n")) !== -1) {
const event = buffer.slice(0, end);
buffer = buffer.slice(end + 2);
for (const line of event.split("\n")) {
if (!line.startsWith("data: ")) continue;
const data = line.slice(6);
if (data === "[DONE]") continue;
const chunk = JSON.parse(data);
if (chunk.error) throw new Error(chunk.error.code + ": " + chunk.error.message);
const delta = chunk.choices[0]?.delta ?? {};
if (delta.reasoning) process.stderr.write(delta.reasoning);
if (delta.content) process.stdout.write(delta.content);
if (chunk.usage) console.error("\n", chunk.usage);
}
}
}Run this on a server or from the command line. Browsers block requests to the API from pages on other origins.
Next steps
- Models: catalog fields, context windows and output limits.
- Chat completions: every accepted field and the streaming format.
- Errors: error codes and how to retry.
