# Quickstart

Go from signup to a streamed, billed model call in five steps. You need a browser, `curl` and an email address.

One RouterPlus key works on two APIs:

| API | Endpoint | Works with |
|---|---|---|
| OpenAI-compatible | `POST https://demo-api.routerplus.com/v1/chat/completions` | OpenAI SDKs, any OpenAI-format client |
| Anthropic-compatible | `POST https://demo-api.routerplus.com/v1/messages` | Anthropic SDKs, Claude Code |

Every chat model works on both APIs. Image models use [POST /v1/images/generations](/docs/api-images).

> [!TIP]
> To set up with a coding agent, give it the runbook on [Coding agents](/docs/install).
> Complete browser signup first, then let the agent configure your client.

## 1. Sign up and save your key

1. Open [Sign up](https://demo.routerplus.com/signup) and complete Clerk authentication and email verification.
2. Save the `tm_vk_` API key shown after your first verified sign-in. You can copy it again later from its row at [API keys](https://demo.routerplus.com/console/keys).
3. Buy credits in [Billing](https://demo.routerplus.com/console/billing) before your first call. Signup does not add free credit.

If purchase matching is offered for your account, Billing shows the cap and remaining matching credit.

If you have an account, [sign in](https://demo.routerplus.com/login) with the same verified email and create a key at [API keys](https://demo.routerplus.com/console/keys). Your balance and keys stay.

You can create an account only in the browser. `POST /v1/signup` is removed. See [Authentication](/docs/authentication).

Export the key:

```bash
export TM_API_KEY=tm_vk_...
```

## 2. Pick a model

```bash
# Public catalog, no auth: ids, prices, context windows, provider retention
curl -s https://demo.routerplus.com/api/models.json

# Models your key can call, in your SDK's list shape
curl -s -H "Authorization: Bearer $TM_API_KEY" https://demo-api.routerplus.com/v1/models
```

`GET /v1/models` returns the OpenAI list shape. It returns the Anthropic shape when you send an `anthropic-version` header. See [Models & catalog](/docs/models).

> [!NOTE]
> An id that is not in the catalog returns a `404` with `error_type: model_unavailable`
> and the id you sent. RouterPlus does not substitute another model.

## 3. Make a streamed call on the OpenAI API

This calls a Claude model in the OpenAI format:

```bash
curl -N https://demo-api.routerplus.com/v1/chat/completions \
  -H "Authorization: Bearer $TM_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-haiku-4-5",
    "stream": true,
    "max_tokens": 60,
    "messages": [{"role": "user", "content": "Say hello in five words."}]
  }'
```

The stream sends a role delta, content deltas, a finish chunk, a **usage chunk**, then `data: [DONE]`. The usage chunk holds the cost:

```json
{
  "prompt_tokens": 13,
  "completion_tokens": 9,
  "total_tokens": 22,
  "prompt_tokens_details": { "cached_tokens": 0, "cache_write_tokens": 0 },
  "completion_tokens_details": { "reasoning_tokens": 0 },
  "cost": 0.000058
}
```

`cost` is in USD. RouterPlus computes it with the same integer micro-USD math as the ledger. It covers the full request, including attempts that failed over before your answer started. You can compute it again from the token counts and the public prices. See [Pricing & billing](/docs/pricing).

With the OpenAI SDK, change only `base_url` and the key:

```python
import os
from openai import OpenAI

client = OpenAI(base_url="https://demo-api.routerplus.com/v1", api_key=os.environ["TM_API_KEY"])

stream = client.chat.completions.create(
    model="claude-haiku-4-5",
    max_tokens=60,
    stream=True,
    messages=[{"role": "user", "content": "Say hello in five words."}],
)
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")
    if chunk.usage:  # the final chunk before [DONE]
        print(f"\ncost: ${chunk.usage.cost}")
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://demo-api.routerplus.com/v1",
  apiKey: process.env.TM_API_KEY,
});

const stream = await client.chat.completions.create({
  model: "claude-haiku-4-5",
  max_tokens: 60,
  stream: true,
  messages: [{ role: "user", content: "Say hello in five words." }],
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
```

> [!TIP]
> Before dispatch, RouterPlus reserves the cost of the call: about (estimated input +
> `max_tokens`) at the model's prices. Without `max_tokens` it reserves at most 32,768
> output tokens. After the call, it settles to the real usage. On a small balance, keep
> `max_tokens` low. If the reservation is larger than your balance, you get
> `insufficient_quota` before RouterPlus calls a provider. See [Rate limits & spend caps](/docs/limits).

## 4. Use the same key on the Anthropic API

This calls a GPT model in the Anthropic format:

```bash
curl -N https://demo-api.routerplus.com/v1/messages \
  -H "x-api-key: $TM_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "stream": true,
    "max_tokens": 60,
    "messages": [{"role": "user", "content": "Say hello in five words."}]
  }'
```

The last `message_delta` event has the usage: `input_tokens`, `output_tokens`, `cache_read_input_tokens`, `cache_creation_input_tokens` and `cost` in USD.

```python
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://demo-api.routerplus.com",
    api_key=os.environ["TM_API_KEY"],
)

with client.messages.stream(
    model="gpt-4o-mini",
    max_tokens=60,
    messages=[{"role": "user", "content": "Say hello in five words."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="")
```

> [!NOTE]
> Both endpoints accept both auth headers: `Authorization: Bearer` and `x-api-key`.
> Use the one your SDK sends. See [Authentication](/docs/authentication).

## 5. Check the cost

```bash
curl -s -H "Authorization: Bearer $TM_API_KEY" https://demo-api.routerplus.com/v1/usage
```

```json
{
  "balance_usd": 4.999942,
  "credited_usd": 5.0,
  "spent_usd": 0.000058,
  "recent_attempts": [
    {
      "request_id": "5a2e…",
      "deployment": "anthropic",
      "model": "claude-haiku-4-5",
      "outcome": "completed",
      "usage_provenance": "observed",
      "input_tokens": 13,
      "output_tokens": 9,
      "cost_usd": 0.000058,
      "billing_source": "house",
      "at": "2026-09-04T10:14:03.201Z"
    }
  ]
}
```

The example is shortened. Each attempt also has its price snapshot and inference cost. `recent_attempts` lists your last 20 attempts. See [GET /v1/usage](/docs/api-usage).

For the full audit of one request, pass the `x-request-id` header of any response. The audit shows every attempt, including failovers, cache splits, and reserved and settled cost:

```bash
curl -s -H "Authorization: Bearer $TM_API_KEY" \
  "https://demo-api.routerplus.com/v1/generation?id=REQUEST_ID"
```

Both endpoints return metadata only: token counts, timings, outcomes and cost. See [Data policy](/docs/data-policy).

You can also see usage and each request in the console: open [Usage](https://demo.routerplus.com/console/usage) or [Logs](https://demo.routerplus.com/console/logs).

## Rules to know

- An unknown model id returns a `404`. RouterPlus does not substitute another model. See [Routing & failover](/docs/routing).
- `n > 1` returns a `400 invalid_request`.
- The first key shown after verified sign-in starts at 20 requests per minute. Until your organization buys credit, all its keys together stay at 20 requests per minute. After the first purchase, keys you create in the console get 300. Every organization also has token-per-minute and concurrency limits. See [Rate limits & spend caps](/docs/limits).
- Every error body has a stable `error_type`, on both APIs, in your SDK's error shape. See [Errors](/docs/errors).

## Next steps

- [Agent integration guide](/docs/agent-integration) - the page an AI agent follows to build RouterPlus into your product
- [Coding agents](/docs/install) - set up Claude Code, Codex, Cursor, Cline or OpenCode
- [Migrate](/docs/migration) - move an existing codebase with one prompt
- [Streaming](/docs/streaming) - event order, keep-alives and mid-stream failures
- [Pricing & billing](/docs/pricing) - the math behind `usage.cost`
