# Reranking

> Score documents against a query and return them in order.

Section: Core API. Canonical page: https://routehook.ai/docs/rerank

`POST /v1/rerank` takes a query and a list of documents and returns them scored for relevance, highest first. It is the second pass of a retrieval pipeline: an embedding search is fast and approximate over the whole corpus, and a rerank is slow and accurate over the handful of candidates that search returned.

> **Warning: This route needs a rerank model in the catalogue**
>
> Reranking is offered by Cohere, Jina and Voyage. None ships with a credential by default, so until an operator adds one the route answers `409 model_unavailable`: not `404`, because the surface exists and only its models are missing. The route is complete: all three vendors expose `POST /rerank` with this exact body, so configuring one is the whole of the work.

## Where it fits

The usual shape is: embed the query, search a vector store, take the top fifty, rerank them, keep the top five. The first pass optimises for recall over millions of documents; the second optimises for precision over fifty. Doing only the first gives you results that are topically close but often not answers; doing only the second is too slow to run over a corpus.

## A request

**cURL**

```bash
curl https://api.routehook.ai/v1/rerank \
  -H "Authorization: Bearer $ROUTEHOOK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "YOUR_MODEL_ID",
    "query": "how do credit holds work",
    "documents": [
      "A hold reserves the ceiling before the call is made.",
      "Invoices are issued on the first of the month.",
      "The reservation is released when the request fails."
    ],
    "top_n": 2
  }'
```

**JavaScript**

```javascript
const response = await fetch("https://api.routehook.ai/v1/rerank", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ROUTEHOOK_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "YOUR_MODEL_ID",
    query: "how do credit holds work",
    documents: candidates,
    top_n: 5,
  }),
});

const { results } = await response.json();

// index points back into `candidates`, not into `results`.
const ranked = results.map((r) => candidates[r.index]);
```

## POST /v1/rerank

Score a set of documents against a query and return them in relevance order.

Status: Available. Authentication: any live API key on the account.

> **Note: index points at what you sent**
>
> Each result carries the position of the document in **your** `documents` array, not its position in the reordered response. That is what lets you map a ranking back onto your own records without matching on text, and it is why dropping `top_n` results still leaves the surviving ones addressable.

## What it costs

Billed on the query plus the documents you send. There is no completion, so there is no output axis. Sending fifty candidates costs fifty candidates' worth whether you keep five of them or all of them, so trim the candidate list before the call rather than with `top_n` after it.
