# Quickstart (/docs/gateway)

Get a key, send your first request to ai.codai.ro, pick a wire format.

The codai gateway lives at `https://ai.codai.ro`. It speaks three wire formats — OpenAI Chat Completions, Anthropic Messages and the OpenAI Responses API — and one model name, `codai`. Whatever SDK you already use will work; the gateway translates under the hood.

<Steps>
<Step>

### Get an API key [#get-an-api-key]

Sign in to [hub.codai.ro](https://hub.codai.ro) and open **Keys → Create key**. Keys look like `codai_xxxxxxxx` and are shown once — store yours in an environment variable:

```powershell tab="PowerShell"
$env:CODAI_API_KEY = 'codai_xxxxxxxx'
```

```bash tab="bash"
export CODAI_API_KEY='codai_xxxxxxxx'
```

</Step>
<Step>

### Send your first request [#send-your-first-request]

<Tabs items={['curl', 'TypeScript', 'Python']}>
<Tab value="curl">

```bash
curl https://ai.codai.ro/v1/chat/completions \
  -H "Authorization: Bearer $CODAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "codai",
    "messages": [
      { "role": "user", "content": "Write a one-line Python function that returns the nth Fibonacci number." }
    ]
  }'
```

</Tab>
<Tab value="TypeScript">

```ts title="quickstart.ts"
import { Codai } from 'codai-sdk';

const codai = new Codai({ apiKey: process.env.CODAI_API_KEY! });

const res = await codai.chat({
  messages: [{ role: 'user', content: 'Write a one-line Python function that returns the nth Fibonacci number.' }],
});

console.log(res.content);
console.log(res.routedTo); // the upstream model that actually served
```

</Tab>
<Tab value="Python">

```python title="quickstart.py"
import os
from codai import Codai

client = Codai(api_key=os.environ["CODAI_API_KEY"])

result = client.chat([
    {"role": "user", "content": "Write a one-line Python function that returns the nth Fibonacci number."}
])

print(result.content)
print(result.routed_to)
```

</Tab>
</Tabs>

A successful response is a standard chat completion:

```json
{
  "id": "chatcmpl-…",
  "object": "chat.completion",
  "model": "codai",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "def fib(n): return n if n < 2 else fib(n - 1) + fib(n - 2)" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 27, "completion_tokens": 21, "total_tokens": 48 }
}
```

</Step>
<Step>

### Read the response headers [#read-the-response-headers]

Every response tells you what actually happened. The two you will use most:

| Header | Meaning |
| --- | --- |
| `x-codai-routed-to` | The upstream model that served the request. |
| `x-codai-cost-micro-usd` | The cost of this request in integer micro-USD (when known before the first byte — see [limits & pricing](./limits-pricing.mdx)). |

The full list is on the [request headers](./headers.mdx) page.

To see them, add `-i` to the curl request above:

```text
HTTP/2 200
x-codai-routed-to: claude-sonnet-5-5
x-codai-upstream: claude-sonnet-5-5
x-codai-cost-micro-usd: 1840
```

`1840` micro-USD is $0.00184. On native streams the cost is not known when headers are sent, so you get `x-codai-cost-estimate: pending` and the exact figure later from [`GET /v1/receipt`](./limits-pricing.mdx#cost-receipt).

</Step>
</Steps>

## `codai` or a pinned model? [#codai-or-a-pinned-model]

<Callout type="info" title="What `codai` does today">
`model: "codai"` is currently a chain of Anthropic's current Claude models with automatic failover between deployments: when one deployment is unavailable, the next one in the chain answers. It does not switch to other providers on its own. Pin a name when you need one model every time: a workload alias such as `codai-fast` or `codai-max`, or a direct upstream name on plans that allow it. Either way `x-codai-routed-to` tells you which model answered. codai's own model is in opt-in beta as `codai-1-beta` (ask for it by name; it is not listed). Details on [models](./models.mdx).
</Callout>

## Already using an SDK? [#already-using-an-sdk]

Point it at the gateway and keep your code.

<Tabs items={['OpenAI (Node)', 'OpenAI (Python)', 'Anthropic (Node)']}>
<Tab value="OpenAI (Node)">

```ts
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.CODAI_API_KEY,
  baseURL: 'https://ai.codai.ro/v1',
});

const res = await client.chat.completions.create({
  model: 'codai',
  messages: [{ role: 'user', content: 'Hello!' }],
});
console.log(res.choices[0].message.content);
```

</Tab>
<Tab value="OpenAI (Python)">

```python
import os

from openai import OpenAI

client = OpenAI(api_key=os.environ["CODAI_API_KEY"], base_url="https://ai.codai.ro/v1")
res = client.chat.completions.create(
    model="codai",
    messages=[{"role": "user", "content": "Hello!"}],
)
print(res.choices[0].message.content)
```

</Tab>
<Tab value="Anthropic (Node)">

```ts
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({
  apiKey: process.env.CODAI_API_KEY,
  baseURL: 'https://ai.codai.ro', // root, not /v1 — the SDK appends /v1/messages
});

const msg = await client.messages.create({
  model: 'codai',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello' }],
});
console.log(msg.content);
```

</Tab>
</Tabs>

<Callout type="info">
The OpenAI base URL includes `/v1`; the Anthropic base URL is the bare host. Getting this wrong produces a `404 not_found` that looks like an auth failure.
</Callout>

## Next steps [#next-steps]

<Cards>
  <Card title="Models" href="./models.mdx" description="What `codai` resolves to, the other aliases, effort and thinking." />
  <Card title="Wire formats" href="./wire-formats.mdx" description="Chat Completions, Messages and Responses — request and response shapes." />
  <Card title="Streaming" href="./streaming.mdx" description="SSE shapes per format and where usage lands." />
  <Card title="Clients" href="./clients.mdx" description="VS Code, Copilot CLI, Cursor, Continue, MCP." />
  <Card title="SDKs" href="../sdks/index.mdx" description="The official TypeScript and Python clients." />
  <Card title="Limits & pricing" href="./limits-pricing.mdx" description="Rate limits, spend caps and the error contract." />
</Cards>
