# Fallbacks and routing

> Fallback models, and how Clonvo chooses between your keys and credits.

Clonvo can retry a request on another model, or with other credentials, when the first attempt fails for a reason that’s worth retrying.

> **Note: Available from Pay as you go up**
> 
> On the [Free plan](https://clonvo.com/docs/plans.md), requests can’t include `models` or `provider`. A request with either fails with `402` and the code `plan_feature_unavailable`. Buy credits of any amount to move to Pay as you go.

## Fallback models

Add a `models` array. Clonvo tries `model` first, then each entry in `models` in order, and returns the first successful response.

```python
completion = client.chat.completions.create(
    model="anthropic/claude-sonnet-5-5",
    messages=[{"role": "user", "content": "Summarise this ticket…"}],
    extra_body={"models": ["openai/gpt-6.1-sol", "google/gemini-3.8-flash"]},
)
print(completion.model)  # the model that answered
```

```js
const completion = await client.chat.completions.create({
  model: "anthropic/claude-sonnet-5-5",
  messages: [{ role: "user", content: "Summarise this ticket…" }],
  // @ts-expect-error Clonvo extension
  models: ["openai/gpt-6.1-sol", "google/gemini-3.8-flash"],
});
```

The response’s `model` and `provider` fields name the model that answered, and you’re billed at that model’s price. `models` can list up to 5 fallback models, and every id in it must exist: an unknown id fails the whole request with `400`.

### When Clonvo moves on

| What happened | Falls back? |
| --- | --- |
| Rate limited (`429`) | Yes |
| Server error (`5xx`), overloaded, timeout, provider unreachable | Yes |
| The provider rejected the credentials (`401`, `402` or `403` from the provider) | Yes, to the next credentials, then the next model (see below) |
| The model can’t take this request before it’s sent: switched off, retired, missing a capability the request needs (tools, images, audio, files), excluded by your privacy settings, a free model over its limit, or no credits to pay for it | Yes, the model is skipped |
| Invalid request (`400`) from the provider, such as an unsupported parameter or a prompt longer than the model’s context | No. The error is returned straight away. |

If every attempt fails, you get the error from the last attempt that reached a provider. If no attempt reached a provider, you get the most actionable reason a model was skipped (a `402` beats a `429`, which beats a `403`, `503` or `404`), for example `402 insufficient_credits` or `403 training_providers_not_allowed`.

To use only one model, leave `models` out. Clonvo can still try your own key and then credits for that model; use [`provider.order`](#choosing-per-request) to limit that. `provider.allow_fallbacks` doesn’t turn off `models`: it only applies to `provider.order`.

### Streaming

Fallbacks happen before the first chunk is sent. Once a stream has started, a provider failure ends the stream with an [error chunk](https://clonvo.com/docs/streaming.md#errors).

## Credentials: your keys first, then credits

For each model, Clonvo picks credentials in this order:

1.  **Your provider keys**, if your organization has added any for that model’s provider ([Bring your own keys](https://clonvo.com/docs/byok.md)). With several keys for the same provider, Clonvo tries them oldest first; it doesn’t rotate between them. Disabled keys are skipped.
2.  **Clonvo credits**, using Clonvo’s own provider account.

If your key fails with a rate limit, server error, timeout or authentication error, Clonvo tries your next key for that provider, then the same model on credits, then the next fallback model. A rejected key is marked with the error under **Provider keys** in the dashboard.

### “Always use this key”

Turn on **Always use this key** for a provider key and Clonvo never uses credits for that provider’s models. If your keys for that provider fail, the request moves to the next fallback model (with that model’s own credentials) or returns the error. Use it when every request for that provider must go through your own account, for example for data-processing terms or committed spend.

### Choosing per request

`provider.order` lets one request prefer or require your own keys or Clonvo credits. It accepts `"byok"` and `"credits"`; other entries are ignored.

| Request | Credentials used, per model |
| --- | --- |
| No `provider.order` | Your keys, then credits. |
| `"order": ["credits"]` | Credits, then your keys. |
| `"order": ["credits"], "allow_fallbacks": false` | Credits only. |
| `"order": ["byok"], "allow_fallbacks": false` | Your keys only. If you have none for the provider, the model is skipped. |

**Always use this key** still applies: with it on, credits are never used for that provider, whatever `provider.order` says. If your `provider.order` settings leave no usable credential (for example a strict `["byok"]` with no key for that provider, or a strict `["credits"]` while **Always use this key** is on), the request fails with `400 no_allowed_credentials` and the message names the setting to change.

```json
{
  "model": "anthropic/claude-sonnet-5-5",
  "messages": [{ "role": "user", "content": "…" }],
  "provider": { "order": ["byok"], "allow_fallbacks": false }
}
```

## Data collection

`provider.data_collection: "deny"` excludes endpoints that may store or train on prompts for that request, even if your organization has free models on. Today this only affects [free models](https://clonvo.com/docs/free-models.md): they’re skipped, or rejected with `404` and the code `no_endpoints_for_data_policy` when nothing else is left.

```json
{
  "model": "anthropic/claude-sonnet-5-5",
  "messages": [{ "role": "user", "content": "…" }],
  "models": ["openai/gpt-6.1-sol"],
  "provider": { "data_collection": "deny" }
}
```

## What you’re charged

Only the attempt that produced the response is charged. Failed attempts are never charged, even if the provider processed part of the request, and a request where every attempt failed is recorded in your activity with a charge of `0`. A stream that fails partway is charged for the tokens it produced (see [Streaming](https://clonvo.com/docs/streaming.md#errors)).