> ## Documentation Index
> Fetch the complete documentation index at: https://docs.routor.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Build Your First App with Routor in Node.js

> Starting from nothing? Build a small working Node.js script that talks to Routor, step by step.

This is for the "I have nothing yet" case. If you already have an app calling OpenAI or Anthropic and just want to point it at Routor, see the [Quickstart](../quickstart) instead - it's a 3-line change. This guide builds a small script from a blank folder so you can see every piece.

***

## What You'll Build

A tiny Node.js script that sends a few different questions to Routor and prints which model answered each one, what tier it was classified into, and how much cheaper it was than always using a flagship model.

***

## Prerequisites

* Node.js 18 or later (`node --version` to check)
* A terminal

***

## Step 1 - Get an API Key

1. Sign up at [routor.io](https://routor.io) - free, no credit card. New accounts start with a small welcome credit, so you can run this guide without topping up first.
2. In the dashboard, go to **API Keys** and create one. It starts with `sk-routor-`.
3. Copy it now - it's only shown once.

***

## Step 2 - Set Up the Project

```bash theme={null}
mkdir routor-first-app
cd routor-first-app
npm init -y
npm install openai
```

Routor is OpenAI-compatible, so the official `openai` package is all you need - no Routor-specific SDK to install.

Set your key as an environment variable instead of hardcoding it:

```bash theme={null}
export ROUTOR_API_KEY="sk-routor-YOUR_KEY_HERE"
```

***

## Step 3 - Write the Script

Create `index.js`:

```javascript theme={null}
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.ROUTOR_API_KEY,
  baseURL: "https://api.routor.io/v1",
});

async function ask(question) {
  const response = await client.chat.completions.create({
    model: "auto", // let Routor decide
    messages: [{ role: "user", content: question }],
  });

  const answer = response.choices[0].message.content;
  const routing = response.routor; // Routor's routing decision, on every response

  console.log(`\nQ: ${question}`);
  console.log(`A: ${answer}`);
  console.log(
    `[routed to ${routing.model} · ${routing.tier} tier · ${routing.savingsPct.toFixed(1)}% cheaper than the baseline]`,
  );
}

await ask("What's the capital of France?");
await ask("Write a Python function that removes duplicates from a list while keeping order.");
await ask("Prove that the square root of 2 is irrational.");
```

`package.json` needs `"type": "module"` for top-level `await` and `import` - `npm init -y` doesn't add this by default, so add it yourself:

```json theme={null}
{
  "type": "module"
}
```

***

## Step 4 - Run It

```bash theme={null}
node index.js
```

You'll see three answers print, each with a line showing which model Routor picked for that specific question. The trivial question and the proof question are unlikely to route to the same model - that's the point. You never chose a model in the code above; `model: "auto"` is the only routing-related line.

***

## Step 5 - See the Full Decision

Every response's `response.routor` object carries the full decision, not just the model name:

```json theme={null}
{
  "model": "google/gemini-3.5-flash",
  "tier": "SIMPLE",
  "category": "simple_qa",
  "profile": "auto",
  "confidence": 0.83,
  "savingsPct": 91.2,
  "qualityPct": -3.1,
  "method": "rules"
}
```

`tier` and `category` tell you how the prompt was classified, `confidence` is how sure the classifier was, `savingsPct` is versus the baseline comparison model, and `qualityPct` is the routed model's benchmark score relative to that same baseline (negative means somewhat below it, which is expected and fine for genuinely simple requests). You can also check any prompt's routing decision *before* spending a real request, using the [Debug Endpoint](../api/debug) - useful while you're still deciding whether the defaults fit your use case.

Your dashboard's **Logs** page shows the same information for every request you've made, in one place.

***

## Where to Go Next

* [How routing decisions are made](../how-it-works) - the mechanics behind `model: "auto"`
* [Controlling the tier](../tiers#controlling-the-tier) - pin, floor, or cap which tier a request can use
* [Set up a routing profile](../playground/create-profile) - save a reusable policy (cost cap, required capabilities, tier range) as its own API key
* [Add image understanding](vision) - the same `client.chat.completions.create` call, with an image attached
