> ## Documentation Index
> Fetch the complete documentation index at: https://developers.meshapi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Service Tiers

> Trade latency for a lower token price with service_tier: flex on OpenAI models — which models serve it, what it costs, and how the refusals behave.

`service_tier` is an optional field on `POST /v1/chat/completions` and
`POST /v1/responses`. It selects the capacity pool the provider serves your request
from.

| Value       | What it does                                                                                           |
| ----------- | ------------------------------------------------------------------------------------------------------ |
| `"auto"`    | Inert. Forwarded unchanged — no change in price, latency or behaviour.                                 |
| `"default"` | Inert. Same as `"auto"`.                                                                               |
| `"flex"`    | Serves the request from OpenAI's discounted, slower capacity pool and bills it at OpenAI's flex rates. |

Omitting the field is the same as sending `"default"`.

<Warning>
  Those three are the **only** accepted values. `"priority"`, `"fast"` and `"scale"`
  are OpenAI's *more expensive* tiers and are not supported — they are rejected with
  `422` before the request reaches a provider:

  ```json theme={null}
  {
    "error": {
      "code": "validation_error",
      "message": "Request validation failed.",
      "details": [
        {
          "type": "literal_error",
          "loc": ["body", "service_tier"],
          "msg": "Input should be 'auto', 'default' or 'flex'",
          "input": "priority",
          "ctx": { "expected": "'auto', 'default' or 'flex'" }
        }
      ]
    },
    "request_id": "req_01JQ..."
  }
  ```
</Warning>

***

## Which models serve flex

Flex is an OpenAI feature. It is refused on every other provider, whatever model
you name.

Within OpenAI, only the models OpenAI publishes a complete flex rate card for can
serve it. That set changes as OpenAI's pricing moves, so read it from
`GET /v1/models` rather than hardcoding a list:

* `pricing.flex_input_usd_per_1m` — **this is the signal to branch on.** A flex rate
  is published only for a model whose provider can actually serve the tier, so its
  presence is the closest thing to a yes.
* `supports_flex` — the model's own declaration, and weaker than it looks. It does
  not account for which upstream serves the model, so a row reached through a
  provider with no flex tier still reports `true`.

```bash theme={null}
curl -s https://api.meshapi.ai/v1/models \
  -H "Authorization: Bearer <YOUR_RSK_KEY>" \
  | jq -r '.[] | select(.pricing.flex_input_usd_per_1m != null) | .id'
```

<Note>
  Neither field is a guarantee, for two reasons. `GET /v1/models` publishes a model's
  **default** pricing row, while the tier is checked against the row for the provider
  your request actually resolves to — so a key with its own provider credential, a key
  pinned to a `fixed_provider`, or a brand routing rule can land on a row with no flex
  tier. And a model can acquire a rate that flex does not price after its flex prices
  were published. Treat a published flex rate as "expected to work" and handle the
  `400` below.
</Note>

## What it costs

Flex tokens bill at OpenAI's published flex rates, materially below the standard
rates. The rates are transcribed from OpenAI's card per model rather than derived
from a discount, so there is no ratio to apply — the per-model `pricing.flex_*`
values in `GET /v1/models` are the contract.

Prompt caching still applies on a flex request and bills at the model's flex cache
rates. A flex request is **never** billed at a standard rate: if any rate the model
carries has no flex counterpart, the request is refused rather than priced off the
standard card.

Flex is not the same product as the [Batch API](/docs/capabilities/batch-api), which
is asynchronous and priced off its own rate card.

## Sending a flex request

```bash theme={null}
curl https://api.meshapi.ai/v1/chat/completions \
  -H "Authorization: Bearer <YOUR_RSK_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5-mini",
    "messages": [{ "role": "user", "content": "Summarise this changelog." }],
    "service_tier": "flex"
  }'
```

The same field works identically on `POST /v1/responses`.

## A model that cannot serve flex is refused

A flex request for a model that cannot serve the tier is rejected with `400`
`model_capability_not_supported` before anything is sent upstream. It is **never**
silently downgraded to the standard tier and billed at the standard price.

Two messages, two causes. The provider your request resolved to has no flex tier, or
the model publishes no flex input/output rate for the context length it would use:

```json theme={null}
{
  "error": {
    "code": "model_capability_not_supported",
    "message": "Model 'openai/gpt-4o-mini' is not available on the 'flex' service tier from the provider resolved for this request. Omit service_tier, or use a model that publishes flex pricing."
  },
  "request_id": "req_01JQ..."
}
```

Or the headline rates are there but something else on the card is not — a cache,
reasoning or audio rate the model charges that flex publishes no counterpart for.
This one can appear on a model that served flex yesterday, so handle it rather than
treating a published flex rate as permanent:

```json theme={null}
{
  "error": {
    "code": "model_capability_not_supported",
    "message": "Model 'openai/gpt-5-mini' is not priced for the flex service tier. Retry without `service_tier`."
  },
  "request_id": "req_01JQ..."
}
```

Both remedies are the same: drop `service_tier`, or pick a model that publishes a
flex rate.

## Knowing which tier actually served

A request can end up on the standard tier even though you asked for flex. If
[retry and fallback](/docs/platform/retry-and-fallback) moves the request to a
different provider or model that cannot serve flex, the tier is dropped for that
attempt and the request is served at the standard tier — and billed at that
target's standard rate, not at the flex rate you asked for.

Two ways to see what happened:

| Surface                               | When to use it                                                                                                                                                         |
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `X-Mesh-Service-Tier` response header | Non-streaming responses. Present only when flex served; absent means standard.                                                                                         |
| The request's usage record            | **Streaming responses**, where the headers are already sent before the attempt finishes, so there is no header to read. `service_tier` on the record is the authority. |

## Caching is per tier

The [gateway response cache](/docs/capabilities/caching) keys on the service tier, so
a flex request never replays a response that was served at the standard tier, and
vice versa. Two otherwise-identical requests on different tiers are two cache
entries.

## Flex is slower by design

That is the trade you are making. Raise your client's timeout before you use it —
OpenAI recommends allowing up to 15 minutes for a flex request.

<Warning>
  The per-request `timeout` field is capped at **600 seconds**, on every tier. A flex
  request that needs longer than that fails with `504 gateway_timeout`, which is
  expected under load — retry it, or send the request without `service_tier`.
</Warning>

## When OpenAI's flex capacity is full

Flex runs on spare capacity, so it can be unavailable when the standard tier is
fine. OpenAI does not charge for a request refused this way, and neither do we:

```json theme={null}
{
  "error": {
    "code": "upstream_error",
    "message": "Service tier is at capacity. Please try again later.",
    "provider_code": "provider_overloaded",
    "provider_error": {
      "provider": "openai",
      "status": 429,
      "message": "Service tier is at capacity. Please try again later."
    }
  },
  "request_id": "req_01JQ..."
}
```

It is served as `503` with a `Retry-After` header. Mesh treats it as a capacity
condition rather than a rate limit, so the request is retryable and eligible for
fallback to another model. Two remedies:

* Retry with exponential backoff, honouring `Retry-After`.
* Retry without `service_tier` (or with `"auto"`) to take standard capacity at the
  standard price.

See the [Error Reference](/docs/reference/errors) for the full error contract.

## Where flex is not available

These are deliberate, not gaps:

| Surface                                                           | Why                                                                                                                                                                                               |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`/v1/batches`](/docs/capabilities/batch-api)                     | Batch is already a discounted asynchronous product with its own rate card. A `service_tier` on a batch line is **not** read by Mesh — it is neither validated nor priced, so it buys you nothing. |
| [Video generation](/docs/capabilities/video-generation)           | Video requests have a `service_tier` field of their own. It is an unrelated BytePlus parameter and has nothing to do with OpenAI's tiers.                                                         |
| `"background": true` on `/v1/responses`                           | A background job settles outside the request, where the flex rate card cannot be applied. Combining the two is refused with `400`.                                                                |
| [Realtime WebSocket endpoints](/docs/capabilities/realtime-audio) | No tier selection.                                                                                                                                                                                |

The background refusal looks like this:

```json theme={null}
{
  "error": {
    "code": "model_capability_not_supported",
    "message": "background=true cannot be served on the 'flex' service tier. Omit service_tier, or run the request without background."
  },
  "request_id": "req_01JQ..."
}
```

## Tracking flex spend

`service_tier` is recorded on every usage record and is filterable in usage
analytics, so flex spend can be separated from standard spend without tagging
requests yourself. See the [Usage API](/docs/reference/usage-api).
