---
title: "Route"
description: "POST /api/v1/router — analyze a request and return the model that should handle it, with fallbacks."
canonical_url: "https://scholarxiv.com/developers/docs/router-api/route"
markdown_url: "https://scholarxiv.com/developers/docs/router-api/route.md"
---

> For the complete documentation index, see [llms.txt](/llms.txt).

# Route
URL: /developers/docs/router-api/route
LLM index: /llms.txt
Description: POST /api/v1/router — analyze a request and return the model that should handle it, with fallbacks.
Related: router-api/completions, router-api/feedback, papers-api/authentication

# Route a request

```http
POST /api/v1/router
```

Returns a routing decision. Nothing is executed — you call the returned model yourself.

## Authentication

Same as every other endpoint: `x-api-key: sxv_…` or `Authorization: Bearer sxv_…`.
See [Authentication](/developers/docs/papers-api/authentication).

## Request body

| Field | Type | Required | Description |
|---|---|---|---|
| `messages` | array | one of | OpenAI-style messages. The last user turn is what gets classified. |
| `prompt` | string | one of | A single prompt, if you don't have a message array. |
| `preset` | string | No | `quality`, `balanced` (default), or `cheap`. |
| `models` | string[] | No | Restrict the pool. Exact ids or wildcards: `anthropic/*`, `openai/gpt-5*`. |
| `requires_tools` | boolean | No | Set when you'll pass tools — models without tool-calling are excluded. |
| `has_image` | boolean | No | Set when the request includes an image, so vision-incapable models are excluded. |
| `has_pdf` | boolean | No | Set when the request includes a PDF. |

## Response

| Field | Description |
|---|---|
| `decision_id` | Pass to [`/feedback`](/developers/docs/router-api/feedback) to score this decision. |
| `model` | The model to use. |
| `fallbacks` | Next-best models, ranked. Retry down this list on failure. |
| `task` | Predicted task type, one of 14 labels. |
| `difficulty` | 0–1. How demanding this request is within its task type. |
| `preset` | The preset the decision was made under — echoes your request, or `balanced`. |
| `estimated_cost_usd` | Estimated cost of this one request on the chosen model. |
| `candidates_considered` | How many models survived the constraint filter. |
| `routing_latency_ms` | Time spent deciding. |
| `degraded` | `true` when constraints left no candidates and a safe default was used. |

## Profiles set the policy; requests narrow it

Each API key routes under a **routing profile** you configure in the
[developer dashboard](/developers/dashboard/router) — a saved policy carrying an
allowed-model list, a default preset and an optional per-request cost ceiling.

A `models` list on the request is applied **on top of** that profile, so it can only
narrow what the profile already permits. A request cannot reach a model its key's
profile excludes. Likewise `preset` on the request overrides the profile's default
for that call only.

If you configure your own AI Gateway key in the dashboard, routing bills to that key
and our plan tiers stop restricting the pool — you're paying the provider directly.

## Restricting the pool

Route only across models you already have keys for:

```json title="request.json"
{
  "prompt": "Summarize this abstract in two sentences",
  "preset": "cheap",
  "models": ["anthropic/*", "openai/gpt-5*"]
}
```

If no model matches your patterns, the response comes back with `degraded: true` and a
safe default — the endpoint never fails just because routing couldn't find a match.

## Errors

| Status | Meaning |
|---|---|
| `400` | No `messages` or `prompt`, malformed JSON, or an unknown `preset`. |
| `401` | Missing, malformed, or revoked API key. |
| `429` | Rate limit for your plan exceeded. |

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
