Start here
Quickstart
Go from a private request to your first metered chat completion with an OpenAI SDK.
On this page
This walks from nothing to a metered chat completion. On the sandbox route today the whole flow takes a few minutes and costs nothing, because sandbox agreements settle with no charge.
1. Get an allocation
An API key only works against an allocation, and an allocation only exists after an agreement activates. In the Cairva workspace:
- Sign in and create a buyer organization.
- Open Requests and send a private request for the model, token volume and delivery window you need. Pick at least one verified supplier, or request terms directly on a lot from the market.
- When a supplier issues a firm quote, review it in the deal room and accept that version. Only an organization admin can accept.
- The supplier countersigns. For a live agreement you pay the invoice and Cairva operations confirm it. Sandbox agreements skip payment.
- Activation checks run and the allocation goes live, or becomes
readyif its window hasn't opened yet.
The full sequence is in How Cairva works.
2. Create a key
Open API keys in the workspace, choose the allocation, give the key a name and pick its scopes. Use inference to call models and usage:read to read the allocation and usage. The secret is shown once. Store it as an environment variable on the machine that will make requests:
export CAIRVA_API_KEY="cv_test_XXXXXXXX_..."Sandbox allocations get cv_test_ keys and live allocations get cv_live_ keys. See API keys.
3. Check what the key can call
GET /v1/models returns the single model your allocation covers. That id is the only value model can take.
curl https://cairva.xyz/v1/models \
-H "Authorization: Bearer $CAIRVA_API_KEY"// npm install openai
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.CAIRVA_API_KEY,
baseURL: "https://cairva.xyz/v1",
});
const { data } = await client.models.list();
console.log(data[0].id); // the one model your allocation covers# pip install openai
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["CAIRVA_API_KEY"], base_url="https://cairva.xyz/v1")
print(client.models.list().data[0].id) # the one model your allocation covers4. Send a request
curl https://cairva.xyz/v1/chat/completions \
-H "Authorization: Bearer $CAIRVA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemma4:e2b",
"messages": [{"role": "user", "content": "Name three uses for a token allowance."}],
"max_tokens": 300
}'const completion = await client.chat.completions.create({
model: "gemma4:e2b",
messages: [{ role: "user", content: "Name three uses for a token allowance." }],
max_tokens: 300,
});
console.log(completion.choices[0].message.content);
console.log(completion.usage);
console.log(completion.cairva); // request id, allocation id, remaining allowancecompletion = client.chat.completions.create(
model="gemma4:e2b",
messages=[{"role": "user", "content": "Name three uses for a token allowance."}],
max_tokens=300,
)
print(completion.choices[0].message.content)
print(completion.usage)
print(completion.model_extra["cairva"]) # request id, allocation id, remaining allowanceReplace gemma4:e2b with whatever /v1/models returned for your key. Any other value fails with model_not_permitted.
Tip
Set max_tokens to what you actually need. Cairva holds that many output tokens from your allowance while the request runs, and caps it at what's left. See Rate limits and holds.
5. Watch the meter
curl https://cairva.xyz/v1/allocations/current \
-H "Authorization: Bearer $CAIRVA_API_KEY"remaining drops by the tokens the provider reported for your request. Each request also appears in once its usage is booked.
If something fails
| You see | Likely cause |
|---|---|
401 unauthenticated | The key is missing, mistyped or revoked |
403 scope_missing | The key doesn't have inference (for completions) or usage:read (for allocation and usage) |
403 model_not_permitted | model isn't the id from /v1/models |
403 allocation_not_started | The delivery window hasn't opened |
502 upstream_error | The route didn't complete the request. Nothing was charged |
Every code is listed in Errors.