# Routing and fallbacks (/docs/concepts/routing)



`POST /v1/call/{provider}/{endpoint}` runs one endpoint and never routes. `POST /v1/run/{capability}`
plans a list of endpoints that serve the capability and tries them in turn.

## The plan [#the-plan]

1. **Candidates.** Every live endpoint for the capability. Endpoints whose circuit breaker is open,
   whose required inputs you did not send, or that your filters exclude drop out.
2. **Order.** Your `provider.order` or `sort` when given; otherwise the capability's declared
   route, if it has one. With nothing to decide the order, GridRouter load-balances: vendors with recent
   errors go last and the rest are drawn with weight 1/price².
3. **Walk.** Each attempt is quoted, run and settled on its own. The run stops at the first
   **hit** (or the first successful response with `"stop_when": "success"`), and falls through
   on misses, vendor errors and vendors you have not added a key for.

A run stops immediately on account errors, because a fallback would fail the same way:
`insufficient_balance`, `budget_blocked`, `account_frozen`, `scope_denied` and
`max_cost_exceeded`. When no vendor could run because none has your key, the error is one
`vendor_key_required` naming all of them.

Every attempt is in the result's `attempts`, with its outcome (`hit`, `miss`, `failed`,
`skipped`), cost, latency and error code.

## Provider preferences [#provider-preferences]

Send them as `provider` in the run body, or save them in a [preset](/docs/api/calls/presets_create).

| Field                                | Effect                                                                                                                                  |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `order`                              | Try these first, in this order. Vendor slugs (`hunter`) or endpoint ids (`hunter/email.find`); at most 20                               |
| `allow_fallbacks`                    | Default `true`. With `false`, only the vendors in `order` are tried                                                                     |
| `only` / `ignore`                    | Keep only, or drop, these vendors or endpoints                                                                                          |
| `sort`                               | `price`, `reliability`, `latency`, `throughput` or `quality`                                                                            |
| `max_cost_micro` / `max_price_micro` | Skip endpoints whose quote (or worst-case price) is above this. The lower of the two wins                                               |
| `preferred_max_latency_ms`           | Endpoints with a median latency above this go after the ones under it                                                                   |
| `data_policy.storage`                | `any` (default), `reviewed` (drop vendors whose data terms are not reviewed yet) or `storable` (only vendors whose results may be kept) |
| `data_policy.zdr`                    | `true` stops GridRouter from storing this call's request and response bodies                                                            |
| `require_verified`                   | Only vendors GridRouter has verified                                                                                                    |

```json
{
  "input": { "first_name": "Ada", "last_name": "Lovelace", "domain": "example.com" },
  "provider": { "order": ["prospeo", "hunter"], "allow_fallbacks": false },
  "fields": ["email", "confidence"],
  "stop_when": "hit"
}
```

`fields` (at most 50) trims the result to the normalized output fields you name. `preset: "@slug"`
applies a saved preset; anything in the request body overrides it.

## Cost caps [#cost-caps]

The per-request cap is `max_cost_micro` in the body or `X-Grid-Max-Cost` in USD as a header. An
attempt whose quote exceeds what is left is skipped, and a single `call` over the cap fails with
`402 max_cost_exceeded` before anything runs. `POST /v1/quote/{provider}/{endpoint}` prices a call
without making it.

Failed attempts and misses on per-success endpoints are never charged. At launch every call runs on
your own vendor keys and costs `0`.

