Quickstart
Two calls: open a session for one of your customers, and stream the reply. Cerver runs the model, stores the conversation, and tells you what each customer costs. No session store, no key plumbing, no cost accounting to build.
In your dashboard → API keys → new key, pick a project. You get a ck_… key. Your provider key stays in the project's vault — Cerver runs the model with it; it never touches your app.
Tag it with app_user_id — whoever this chat is for. That's how every token gets attributed back to the right customer.
# → { "session_id": "34920a6e-…" }
curl https://gateway.cerver.ai/v2/sessions \
-H "Authorization: Bearer $CERVER_KEY" \
-H "Content-Type: application/json" \
-d '{
"compute": { "provider": "online" },
"metadata": { "session_type": "chat", "app_user_id": "cust_amy" }
}'
const h = { Authorization: `Bearer ${process.env.CERVER_KEY}`, "Content-Type": "application/json" };
const session = await fetch("https://gateway.cerver.ai/v2/sessions", {
method: "POST", headers: h,
body: JSON.stringify({
compute: { provider: "online" },
metadata: { session_type: "chat", app_user_id: "cust_amy" },
}),
}).then(r => r.json()); // → session.session_id
Post the customer's message to /run-llm. The reply streams back word by word (text_delta events); a final usage event tells you what that message cost.
curl -N https://gateway.cerver.ai/v2/sessions/$SID/run-llm \
-H "Authorization: Bearer $CERVER_KEY" \
-H "Content-Type: application/json" \
-d '{ "input": "How do I reset my password?",
"model": "claude-haiku-4-5-20251001" }'
# event: text_delta → {"content":"Sure — "} …streams…
# event: usage → {"cost_estimate_usd":0.0004}
# event: done → {"ok":true}
const res = await fetch(`https://gateway.cerver.ai/v2/sessions/${session.session_id}/run-llm`, {
method: "POST", headers: h,
body: JSON.stringify({ input: "How do I reset my password?", model: "claude-haiku-4-5-20251001" }),
});
// stream the tokens as they arrive
let buf = "";
for await (const chunk of res.body) {
buf += Buffer.from(chunk).toString();
for (const f of buf.split("\n\n")) {
if (/event: text_delta/.test(f)) process.stdout.write(JSON.parse(/data: (.*)/.exec(f)[1]).content);
}
buf = buf.slice(buf.lastIndexOf("\n\n") + 2);
}
Every message is attributed to the app_user_id you named. Your dashboard rolls it up per customer — so you know who to cap, and who to upsell.
| cust_amy | 1,204 messages | $18.40 |
| cust_devs_inc | 612 messages | $9.07 |
| cust_jordan | 2,918 messages | $41.85 |
That's the whole point. The backend for an AI feature is mostly the boring, load-bearing parts — and they're already here:
Prefer a full runnable file? examples/quickstart.mjs in the repo does all three steps in ~15 lines — CERVER_KEY=ck_… node quickstart.mjs "Hello!".
No card, no credits. You bring your own provider keys — they never leave your vault.