# Quickstart

> Go from a private request to your first metered chat completion with an OpenAI SDK.

Source: https://cairva.xyz/docs/quickstart

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:

1. [Sign in](https://cairva.xyz/sign-in) and create a buyer organization.
2. 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](https://cairva.xyz/market).
3. When a supplier issues a firm quote, review it in the deal room and accept that version. Only an organization admin can accept.
4. The supplier countersigns. For a live agreement you pay the invoice and Cairva operations confirm it. Sandbox agreements skip payment.
5. Activation checks run and the allocation goes live, or becomes `ready` if its window hasn't opened yet.

The full sequence is in [How Cairva works](https://cairva.xyz/docs/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:

```bash
export CAIRVA_API_KEY="cv_test_XXXXXXXX_..."
```

Sandbox allocations get `cv_test_` keys and live allocations get `cv_live_` keys. See [API keys](https://cairva.xyz/docs/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.

```bash curl
curl https://cairva.xyz/v1/models \
  -H "Authorization: Bearer $CAIRVA_API_KEY"
```

```javascript JavaScript
// 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
```

```python Python
# 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 covers
```

## 4. Send a request

```bash curl
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
  }'
```

```javascript JavaScript
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 allowance
```

```python Python
completion = 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 allowance
```

Replace `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](https://cairva.xyz/docs/rate-limits).

## 5. Watch the meter

```bash
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 [`GET /v1/usage`](https://cairva.xyz/docs/usage) 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](https://cairva.xyz/docs/errors).
