Develop / Reference
Rerank
Orders documents by their relevance to a search query and inspects query, instruction and documents with Noirdoc Shield before forwarding when Shield is active.
/v1/rerank - Family
- rerank
- Shield
- yes
- Streaming
- no
- Format
- JSON
- Billing
- tokens (input) or per request
A reranker rates how well each document matches a search query. In a RAG pipeline, you use it after the vector search: the search returns candidates, the reranker reorders them, and only the best go to the language model.
Request
The body follows the widely used rerank format (POST /v1/rerank). model is required and must be a model of the rerank family from GET /v1/models. The gateway answers a chat or embedding model on this endpoint with 400 wrong_endpoint_for_model, and likewise a rerank model on another endpoint.
| Field | Required | Content |
|---|---|---|
model | yes | model ID of the rerank family |
query | yes | search query as a non-empty string |
documents | yes | list of 1 to 1,000 strings |
instruction | no | optional task instruction string (inspected when Shield is active and forwarded to the provider) |
top_n | no | whole number from 1: the result contains only the best top_n documents. If not given, it rates all of them. |
return_documents | no | true: each result also contains the text of the document. The gateway forwards the field unchanged. |
The endpoint accepts only text. The gateway rejects images or content parts (content arrays) in query or documents, even if the model at the provider could process images. It answers violations of the rules in the table with 400 invalid_rerank_request before forwarding the request.
curl https://api.noirdoc.de/v1/rerank \
-H "Authorization: Bearer $NOIRDOC_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3-VL-Reranker-8B",
"query": "How long is the notice period?",
"documents": [
"The contract ends at the end of the quarter.",
"The notice period is three months.",
"The rent is due on the first of the month."
],
"top_n": 2,
"return_documents": true
}'import os
import httpx
key = os.environ["NOIRDOC_API_KEY"]
response = httpx.post(
"https://api.noirdoc.de/v1/rerank",
headers={"Authorization": f"Bearer {key}"},
json={
"model": "Qwen/Qwen3-VL-Reranker-8B",
"query": "How long is the notice period?",
"documents": [
"The contract ends at the end of the quarter.",
"The notice period is three months.",
"The rent is due on the first of the month.",
],
"top_n": 2,
"return_documents": True,
},
)
response.raise_for_status()
for result in response.json()["results"]:
print(result["index"], result["relevance_score"])Response
The gateway returns the provider’s response in a uniform shape, whichever provider delivered it:
| Field | Content |
|---|---|
results | list of the rated documents in the provider’s order, usually by descending relevance |
results[].index | position of the document in your documents list, starting at 0 |
results[].relevance_score | relevance of the document to query. The model sets the scale; compare values only within one response. |
results[].document | object {"text": …} with the text of the document. With return_documents: true, it is included; whether it appears without this option depends on the provider. |
usage | token usage, if the provider reports it. If it is missing, the gateway estimates the input tokens for billing itself. |
If a provider delivers the document as a plain string, the gateway converts it into an object with the field text. It passes objects on unchanged. It reports provider errors in the uniform error object, see Error codes.
{
"results": [
{
"index": 1,
"relevance_score": 0.94,
"document": {
"text": "The notice period is three months."
}
},
{
"index": 0,
"relevance_score": 0.31,
"document": {
"text": "The contract ends at the end of the quarter."
}
}
],
"usage": { "total_tokens": 48 }
}Prompt tags for Qwen3 rerankers
Some rerankers expect their inputs in a fixed prompt format. Qwen3 reranker models deliver the best results if query contains a task description and the search query with the tags <Instruct>: and <Query>:, and each document starts with <Document>:.
The gateway does not set these tags itself. It forwards query and documents as you send them. The model’s documentation states whether a model needs tags. Call models that expect no tags with the plain text.
instruct = (
"Find contract clauses that answer the question."
)
question = "How long is the notice period?"
docs = [
"The contract ends at the end of the quarter.",
"The notice period is three months.",
]
payload = {
"model": "<qwen3-reranker-model>",
"query": f"<Instruct>: {instruct}\n<Query>: {question}",
"documents": [f"<Document>: {d}" for d in docs],
}What Noirdoc changes
| Area | Behaviour |
|---|---|
| Model | The gateway resolves the model ID through the catalogue and sends the provider its own model name. |
| Provider | The X-Noirdoc-Provider header in the response names the provider. See Providers & routing. |
| Response | results[].document is always an object with text, see Response. If Shield redacted documents, text carries the redacted version when return_documents: true. |
| Noirdoc Shield | When Shield is active (default_on, enforced, key or request-tag shield_mode: on, or X-Noirdoc-Shield: on), Shield inspects query, instruction and documents[] before forwarding. The response carries X-Noirdoc-Shield: redacted=<n> and X-Noirdoc-Masked: true; on a block match, the gateway rejects the request with 403 shield_violation (see Inspected fields). |
| Streaming | None. The gateway answers "stream": true with 400 streaming_not_supported_for_endpoint. |
| Billing | Depending on the model, by input tokens (per1MTokens) or per request (perRequest), plus Noirdoc Shield when inspection is active (Billing). With tokens, the gateway bills the usage from usage; if the provider reports none, it estimates the input tokens from query and documents. With perRequest, each successful request costs the price from price_input, regardless of the number of documents. Models & pricing lists the prices. |
| Headers | The gateway removes your key, X-Noirdoc-Shield and X-Noirdoc-Mask before forwarding the request. |
Only pre-existing organisations still on legacy masking until 30.11.2026 receive 403 masking_not_supported_for_endpoint on /v1/rerank under enforced or X-Noirdoc-Mask: on — unless they opt into Noirdoc Shield via X-Noirdoc-Shield: on or by switching under Models → Shield.
Sub-routes
None. The gateway answers other paths under /v1/rerank/ with 404 unsupported_endpoint. The endpoint accepts only POST; the gateway answers other methods with 405 method_not_allowed.
Errors on this endpoint
| Status | Code | Meaning |
|---|---|---|
| 400 | model_required | The request names no model (model in the body, or in the form field for /v1/audio/transcriptions). |
| 400 | wrong_endpoint_for_model | The model belongs to a different endpoint family or API format than the endpoint called. |
| 400 | streaming_not_supported_for_endpoint | The request asks for streaming, but the endpoint does not support it. |
| 400 | invalid_request_body | The body is not a JSON object or not encoded in UTF-8. |
| 400 | invalid_rerank_request | query is not a non-empty string, documents is not a list of 1 to 1,000 strings or top_n is not an integer of at least 1; message names the field. |
| 402 | insufficient_credit | The organisation's credit is used up or lower than the estimated maximum cost of the request (including Noirdoc Shield, also on BYOK routes when Shield is active). |
| 402 | key_budget_exhausted | This key's budget is used up for the current period or does not cover the estimated cost of the request. |
| 403 | model_not_allowed_for_key | The model is not one of this key's allowed models. |
| 403 | provider_not_allowed_for_tenant | The organisation counts as bound by professional secrecy (§ 203 StGB); this excludes every provider that offers this model. |
| 403 | provider_not_allowed_for_key | The key's restrictions (providers, data residency, CLOUD Act, § 203) exclude every provider of this model. |
| 403 | starter_model_not_allowed | The organisation is still using only its starter credit, and the model or its managed provider is not included in starter credit. |
| 403 | shield_violation | Noirdoc Shield blocked the request before forwarding to the provider because an active protection filter configured with block matched; message names the triggered rule (secrets, pii, ner, injection or custom). |
| 403 | masking_not_supported_for_endpoint | The endpoint supports neither Noirdoc Shield nor legacy masking, yet the policy is enforced or the request sends X-Noirdoc-Mask: on (and on /v1/images/generations also X-Noirdoc-Shield: on). During the legacy masking transition until 30.11.2026, this also affects /v1/embeddings and /v1/rerank on pre-existing organisations that have not switched to Shield yet. |
| 403 | model_not_billable | The model has no complete price on record, so it cannot be used with credit. |
| 404 | model_not_available | The model ID is not available to the organisation. |
| 405 | method_not_allowed | The endpoint accepts only POST. |
| 413 | shield_input_too_large | The text to inspect in this request exceeds the Shield service limit of 4 MiB of encoded text in a single call. |
| 422 | shield_config_invalid | The organisation's stored Shield configuration is invalid (for example enforced without any active protection filter, or a pattern that fails compilation); the gateway did not forward the request. |
| 502 | provider_unreachable | The gateway could not connect to the provider, or the connection dropped. |
| 503 | shield_unavailable | The Noirdoc Shield inspection service is temporarily unreachable; the gateway never forwards a request that requires inspection uninspected (fail-closed). The response contains Retry-After with 5 seconds. |
| 504 | provider_timeout | The provider did not answer within the gateway's timeout. The response contains Retry-After with 10 seconds. |