Docs · Guides
Combos and fallback
A combo is a named, ordered list of models. When the first one cannot answer, the gateway tries the next, so that one provider's outage or rate limit does not stop your work. It is a fallback chain: one answer comes from one model.
Manage combos#
All of these take your API key and only reach your own combos. Another person's combo is a 404.
GET/api/v1/combos#
{
"data": [
{
"id": 1,
"user_id": 42,
"name": "daily driver",
"mode": "fallback",
"targets": [
{ "server_key": "anthropic", "model": "claude-sonnet-4-6" },
{ "server_key": "openai", "model": "gpt-4o" }
],
"judge": null,
"is_active": true,
"created_at": "2026-10-10T17:00:00.000000Z",
"updated_at": "2026-10-10T17:00:00.000000Z"
}
]
}POST/api/v1/combos#
Creates a combo and answers 201 with {"data": {…}}.
| Field | Notes |
|---|---|
name | required, up to 64 characters, unique among your combos |
targets | required, 1 to 4 items, in priority order |
targets[].server_key | the provider or server, for example anthropic: the part after the @ of a model id |
targets[].model | the model name, without the @server part |
You can have 5 combos. The 6th is refused with 422.
Only the shape is checked when you save. A target that does not exist, or that has no key behind it, is accepted and then skipped when the combo runs, so test a combo after you create it.
PUT/api/v1/combos/{id}#
Replaces name and targets. It answers 200 with the combo.
DELETE/api/v1/combos/{id}#
Answers 200 with {"status": "deleted"}.
Use a combo#
curl -sN "$SHVIA_URL/api/v1/chat" \
-H "Authorization: Bearer $SHVIA_API_KEY" -H "Content-Type: application/json" \
-d '{ "message": "Summarize the plan in 3 bullets.", "combo_id": 1 }'The combo replaces the choice of model. An unknown combo_id, or one that belongs to someone else, is ignored, and the normal model choice applies. Your default model is added at the end of every combo as a last resort, so a combo whose targets cannot be reached usually answers from your default model instead of failing. The stream carries an error event with codigo combo_sem_modelo only when not even that can be resolved.
How the chain runs#
- A combo tries its targets in order, from the first, on every turn. The gateway moves to the next one only if the failure is one that another model can fix and no text has been sent yet. Once the first token has streamed, that reply is the answer, even if it breaks later.
- A failure that another model can fix is, for example, a quota or rate limit at the provider, an overloaded provider, a credential that is refused, an unknown model, a server that is offline, or an empty answer. A request that the provider rejects as invalid, or one that is too long for the model's context, does not move on: another model would get the same request.
- A target whose context window cannot hold your prompt, or that cannot see images when the turn has one, is skipped when another target remains.
- A combo does not keep a prompt on the operator's servers. If the first target is on the operator's own servers and it fails, the next target can be a cloud provider, and the conversation goes to it, with personal data in the text masked. For a guarantee that a prompt never leaves the operator's servers, keep every target of the combo on them.
- If any target of the combo is in the cloud, the gateway leaves knowledge-base context and memory out of the prompt for every target of that combo, the first one included, because a fallback could carry them there. Everything else in the turn can reach a cloud target once the chain gets there: the earlier turns of the conversation, your attachments and images (resized to fit the cloud limits), and the persona and the project instructions and files of your account, unless you turned on LGPD protection in your account settings.
Which model answered#
The stream's first model event names the first target. When another model takes over, a second model event follows with target_source set to combo_fallback and the new name. It arrives after the text of the answer has already streamed, just before usage and done, so a screen that labels the answer from the first event shows the wrong model while it streams. Read the last model event, or usage.model.
Notes#
modeisfallback. The API does not let you set another mode or a judge, even thoughGETreturns the fields.is_activeis accepted and returned, and it has no effect today.