Concepts / Routing

# Routing & fallback

How a request becomes an endpoint choice — and how that choice is evidenced back to you.

## Evaluation order

Hard constraints eliminate candidates. Preferences rank what survives. Fallback walks the ranked list and never crosses a constraint. The constraints are your organization's policy — [/console/routing](https://yelno.ai/console/routing), `PUT /api/v1/organizations/{id}/policy` — and a request may tighten them in a `yelno` object, never loosen them.

```
// organization policy — GET /api/v1/organizations/{id}/policy
{
  "require_zdr": true,                            // hard: zero retention, no training
  "max_retention_days": 0,                        // hard
  "allowed_regions": ["eu-west", "eu-central"],   // hard
  "blocked_providers": ["google"],                // hard
  "allow_byok": true,
  "version": 3                                    // send it back on PUT: optimistic concurrency
}

// per request, optional — may only make the policy stricter
"yelno": { "max_price_nanos": 20000000, "allowed_regions": ["eu-central"] }

// ranking of what survives: provider_order → parameter fidelity → credential preference
//                            → circuit state → health → estimated cost → p50 latency
```

## Route evidence

Every response carries a `yelno` object: the plan fingerprint with the catalog, price-book and policy versions it was computed against, the endpoint that served you, and every planned attempt with its credential source and state. Money is integer nanos — `customer_nanos: 4440000` is $0.00444.

```
"yelno": {
  "request_id": "req_01J9F3KJ2MQ8ZV5T7XB0N4A6WD",
  "model": "mistral/mistral-large-2",
  "endpoint_id": "ep_01J8ZC7Q4RT2M9XKV6B3H5N0PA",
  "provider": "mistral", "credential_source": "platform",
  "route_plan": { "fingerprint": "3f9c1e7a4b2d8c05…", "catalog_version": "catalog@2026-09-01T14:32:08+00:00",
                  "price_book_version": "price@7", "policy_version": "policy@3" },
  "attempts": [
    { "sequence": 1, "attempt_id": "att_01J9F3KJ2N…", "endpoint_id": "ep_01J8ZC7Q4R…", "provider": "mistral",
      "region": "eu-west", "credential_source": "platform", "state": "provider_completed" },
    { "sequence": 2, "attempt_id": "att_01J9F3KJ2P…", "endpoint_id": "ep_01J8ZD1W6K…", "provider": "mistral",
      "region": "eu-west", "credential_source": "platform", "state": "planned" }
  ],
  "usage": { "units": { "input_uncached": 1200, "output": 340 },
             "source": "provider_final", "status": "provider_final" },
  "cost": { "state": "final", "currency": "USD", "customer_nanos": 4440000, "reconciliation_required": false },
  "client_disconnected": false, "generation_may_have_continued": false,
  "request_state": "provider_completed", "compat_mode": "permissive", "warnings": []
}
```

When nothing is eligible you get `422 capability_unsupported` with `code: "no_eligible_route"`; the message names the constraints that eliminated every candidate, and `GET /api/v1/catalog/resolve?model=…` lists each endpoint with its reason — not a silent relaxation of your policy.

Source: https://yelno.ai/docs/routing
