Presets API
Create, list, update, and delete reusable preset configurations.
A preset stores a default model, system prompt, sampling parameters and provider routing rules. Use it in any inference request as model: "@preset/<slug>".
Use a Management key (ak_…) carrying read:presets (read routes) or write:presets (write routes), or a signed-in dashboard session. An LLM key (sk-ar-…) is not accepted. See Management API Keys.
Request
POST /api/v1/presets creates a preset in the authenticated workspace:
| Field | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Unique identifier. Lowercase alphanumeric and hyphens (/^[a-z0-9][a-z0-9-]*$/). Unique per workspace. |
name | string | Yes | Display name. Must not be empty. |
description | string | null | No | Optional description. |
config | object | Yes | Preset configuration. See PresetConfig fields. |
Other routes
| Method & path | Purpose |
|---|---|
GET /api/v1/presets | List all presets in the workspace, newest first. |
GET /api/v1/presets/{slug} | Return a single preset by slug (404 if none). |
PATCH /api/v1/presets/{slug} | Partial update — only included fields change. |
DELETE /api/v1/presets/{slug} | Delete a preset by slug (404 if none). |
PATCH update behavior: name is updated if provided and non-empty; description is tri-state (omit to keep, null to clear, string to set); config is shallow-merged so existing keys not in the patch are preserved.
PresetConfig fields
All fields are optional. A request can override these defaults.
| Field | Type | Description |
|---|---|---|
model | string | Default model (e.g. "z-ai/glm-4.7-flash") |
models | string[] | Fallback model list, tried in order if the primary is unavailable. |
system | string | System prompt, prepended as a {role: "system"} message when the request has none. |
temperature | number | Sampling temperature (0–2) |
max_tokens | number | Maximum tokens in the response |
max_completion_tokens | number | Maximum completion tokens (newer OpenAI parameter) |
top_p | number | Nucleus sampling threshold |
top_k | number | Top-K sampling |
frequency_penalty | number | Frequency penalty (-2 to 2) |
presence_penalty | number | Presence penalty (-2 to 2) |
repetition_penalty | number | Repetition penalty |
stop | string | string[] | Stop sequences |
seed | number | Reproducibility seed |
response_format | object | Response format (e.g. { "type": "json_object" }) |
tools | array | Tool definitions |
tool_choice | string | object | Tool selection strategy |
provider | object | Provider routing rules (sort, only, ignore, allow_fallbacks, etc.) |
reasoning | object | Reasoning config (effort, max_tokens, exclude) |
stream_options | object | Streaming options (e.g. { "include_usage": true }) |
Reasoning on anyrouter/* routes
The built-in anyrouter/auto, anyrouter/free, anyrouter/cowork, anyrouter/hermes and anyrouter/latest ids are routing presets, not fixed models, and have no synthetic reasoning level list. The rules below cover explicit request controls on them; a custom preset's stored reasoning object is not guaranteed to be merged by every endpoint.
- Chat requests use flat
reasoning_effort. Responses uses nestedreasoning.effort, withreasoning.enabled: falseto disable. For flat Chat and converted Messages,noneis a disable sentinel, not an effort tier. - Messages requests use
thinking.type(enabled/disabled); native Anthropic routes get the body unchanged. Converted to a non-native upstream,enabledmaps to flathighanddisabledtonone;thinking.budget_tokensis not carried over. - On flat
reasoning_effortpaths (including converted Messages), before each upstream attempt AnyRouter clamps the effort to the selected model's declared levels (a route-specific override wins), preferring the nearest lower level and falling back to the model default for an unknown tier. An omitted effort stays omitted. A branch's levels never leak into the next fallback branch.noneis never clamped. - If a resolved branch declares no effort enum, the caller's flat value is forwarded unchanged. For a selected route, its per-upstream
supported_parametersis the authority. - Preset-level
require_paramsis a hard candidate constraint on paths that support preset candidate selection. Preset, key and request provider lists are unioned at the preference layer, but provider/key requirements are not a hard filter on every dispatch. Built-in virtual resolution uses tool-related entries (and request tools) to require tool-capable members; other parameters are not capability guarantees. provider.require_parameters: trueis a separate strict model-level check over the request body and has no effect when the model declares nosupported_parameters. Body-inferred parameters such astools,tool_choiceandresponse_formatuse the softer reorder/strip path. With no declared support list, support is treated as unknown and permissive.- Routing floors merge as follows:
min_contexttakes the higher value, keyignoreis unioned, key and requestonlylists intersect. Top-levelrequire_paramsis the legacy alias forprovider.require_params;min_contextis also accepted at the top level. - A fallback chain may try a different model after an upstream failure; clamping is recalculated for that attempt.
Interleaved thinking is a provider beta request (anthropic-beta: interleaved-thinking-2025-05-14), not a preset or model guarantee. These rules do not promise toggle or token-budget support on every provider.
Response
GET /api/v1/presets returns a list envelope. A preset record:
{
"id": "preset_abc123",
"object": "preset",
"slug": "code-reviewer",
"name": "Code Reviewer",
"description": "Strict senior-engineer review focused on bugs, security, and clarity.",
"config": {
"model": "anthropic/claude-sonnet-4",
"system": "You are a senior code reviewer...",
"temperature": 0.2,
"max_tokens": 4096
},
"created_at": "2026-03-01T12:00:00.000Z",
"updated_at": "2026-03-01T12:00:00.000Z"
}DELETE /api/v1/presets/{slug} returns:
{
"deleted": true,
"slug": "code-reviewer"
}Examples
curl -X POST https://anyrouter.dev/api/v1/presets \
-H "Authorization: Bearer ak_your-management-key" \
-H "Content-Type: application/json" \
-d '{
"slug": "code-reviewer",
"name": "Code Reviewer",
"description": "Strict senior-engineer review focused on bugs, security, and clarity.",
"config": {
"model": "anthropic/claude-sonnet-4",
"system": "You are a senior code reviewer. Focus on bugs, security issues, and clarity.",
"temperature": 0.2,
"max_tokens": 4096
}
}'import httpx
httpx.post(
"https://anyrouter.dev/api/v1/presets",
headers={"Authorization": "Bearer ak_your-management-key"},
json={
"slug": "code-reviewer",
"name": "Code Reviewer",
"config": {
"model": "anthropic/claude-sonnet-4",
"system": "You are a senior code reviewer.",
"temperature": 0.2,
"max_tokens": 4096,
},
},
)await fetch("https://anyrouter.dev/api/v1/presets", {
method: "POST",
headers: {
Authorization: "Bearer ak_your-management-key",
"Content-Type": "application/json",
},
body: JSON.stringify({
slug: "code-reviewer",
name: "Code Reviewer",
config: {
model: "anthropic/claude-sonnet-4",
system: "You are a senior code reviewer.",
temperature: 0.2,
max_tokens: 4096,
},
}),
})Then set model to @preset/code-reviewer in any inference request.
Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_slug | Slug doesn't match the required pattern. |
| 400 | name_required | Name is empty or missing. |
| 400 | config_required | Config is missing or not an object. |
| 401 | — | Missing or invalid credential. |
| 403 | — | Key lacks the required read:presets / write:presets scope. |
| 409 | duplicate_slug | A preset with this slug already exists in the workspace. |
AnyRouter routes requests to third-party models. Models and outputs are provided as is, with no warranty; you use them at your own risk. Disclaimer