> This page is for Gateway.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.merge.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.merge.dev/_mcp/server.

# API details

> Base URL, authentication, endpoints, pagination, shared request fields and headers, OpenAI Responses clients, and per-call cost for the Gateway API.

This page covers what every Gateway endpoint shares. The endpoint reference in this tab has the full schemas.

## Base URL and authentication

```text
https://api-gateway.merge.dev/v1
```

Send a Gateway API key from the [API keys](https://gateway.merge.dev/api-keys) page as a bearer token:

```http
Authorization: Bearer mg_...
```

The [Management API](/merge-gateway/management-api) administers keys, projects, routing policies, and usage with a separate `mgmt_` key on the same host. There's no rotate endpoint: create a new key, then delete or disable the old one.

## Endpoints

| Endpoint                                                                                                                              | Purpose                                                                                                                                              |
| ------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /v1/models`, `GET /v1/models/{model_id}`                                                                                         | The model catalog, filterable by `provider`, `vendor`, and `zero_data_retention`. Pass `?model=provider/model` to retrieve one model.                |
| `GET /v1/models/discounted`                                                                                                           | Models with a current discount                                                                                                                       |
| `GET /v1/vendors`, `GET /v1/vendors/{vendor_id}`                                                                                      | Execution vendors and the models they serve, filterable by `zero_data_retention`                                                                     |
| `POST /v1/responses`                                                                                                                  | Gateway's native Responses API                                                                                                                       |
| `GET /v1/responses/{response_id}`, `DELETE /v1/responses/{response_id}`                                                               | Read or delete a response stored with `store: true`. Stored responses expire an hour after last use, and `previous_response_id` resumes one.         |
| `POST /v1/chat/completions`                                                                                                           | OpenAI Chat Completions shape, also served at `/v1/openai/chat/completions`                                                                          |
| `POST /v1/messages`, `POST /v1/messages/count_tokens`                                                                                 | Anthropic Messages shape, also served at `/v1/anthropic/v1/messages`                                                                                 |
| `POST /v1/embeddings`                                                                                                                 | Embeddings, priced on input tokens                                                                                                                   |
| `POST /v1/decisions`                                                                                                                  | Typed answers from a [decision model](/merge-gateway/capabilities/decisions)                                                                         |
| `POST /v1/images/generations`, `POST /v1/images/edits`                                                                                | [Image generation](/merge-gateway/capabilities/multimodal/image-generation) and [editing](/merge-gateway/capabilities/multimodal/image-editing)      |
| `POST /v1/audio/speech`, `POST /v1/audio/transcriptions`                                                                              | [Speech synthesis](/merge-gateway/capabilities/multimodal/text-to-speech) and [transcription](/merge-gateway/capabilities/multimodal/speech-to-text) |
| `POST /v1/videos`, `GET /v1/videos`, `GET /v1/videos/{video_id}`, `DELETE /v1/videos/{video_id}`, `GET /v1/videos/{video_id}/content` | Async [video generation](/merge-gateway/capabilities/multimodal/video-generation)                                                                    |
| `/v1/batches`                                                                                                                         | [Batch inference](/merge-gateway/capabilities/batch-inference) at the `batch` tier                                                                   |
| `GET /v1/tags`                                                                                                                        | The tag key-value pairs available to your organization                                                                                               |
| `GET /v1/routing/policies`, `GET /v1/routing/strategies`                                                                              | Your routing policies and the available strategies                                                                                                   |

SDK-compatible surfaces under `/v1/openai`, `/v1/anthropic`, `/v1/ai-sdk`, and `/v1/langchain` need only a base URL change in an existing client ([Get started](/merge-gateway/get-started)).

> **\`/v1/responses\` is Gateway's native API, not OpenAI's Responses API**
>
> The native endpoint streams `response.stream` and `response.done` snapshots; OpenAI's streams `response.created` through `response.completed`. Point OpenAI Responses clients, including the OpenAI SDK's `client.responses.*` and Codex, at `/v1/openai/responses` ([details](#openai-responses-api-clients)).

## Models API shape

`GET /v1/models` returns canonical model identity at the top level and per-vendor execution details under `vendors`:

```json
{
  "model": "openai/gpt-5.4",
  "provider": "openai",
  "display_name": "GPT-5.4",
  "aliases": [],
  "vendors": {
    "openai": {
      "launch_date": "2026-03-05",
      "context_window": 1050000,
      "max_output_tokens": 128000,
      "availability_status": "available",
      "zero_data_retention": true,
      "capabilities": {
        "input": ["text", "image", "document"],
        "output": ["text", "tool_use"],
        "supports_tool_calling": true,
        "supports_structured_outputs": true,
        "supports_reasoning": true,
        "reasoning": { "effort_values": ["none", "low", "medium", "high", "xhigh"] },
        "streaming": true
      },
      "service_tiers": ["standard", "flex", "priority", "batch"],
      "pricing": {
        "currency": "USD",
        "input_per_million": 2.5,
        "output_per_million": 15,
        "cache_read_per_million": 0.25,
        "flex": { "input_per_million": 1.25, "output_per_million": 7.5 },
        "priority": { "input_per_million": 5, "output_per_million": 30 },
        "batch": { "input_per_million": 1.25, "output_per_million": 7.5 }
      },
      "batch_endpoints": ["/v1/chat/completions", "/v1/embeddings", "/v1/responses"]
    }
  },
  "availability_status": "available",
  "access_required": false,
  "access_reason": null
}
```

Models that need [provider access](/merge-gateway/model-access/vendor-access) enabled are still listed, with `access_required: true` and `access_reason: "vendor_access_required"`.

The listing shows only what the caller can route to, applying your organization's vendor and region controls, blocklist, and BYOK-only setting, the key's project and `allowed_models`, zero data retention (non-ZDR vendors and models without a ZDR route are omitted), and a customer's controls when the request carries a [customer API key](/merge-gateway/embedded-routing-stack/customer-api-keys) or `X-Merge-Customer`. An exhausted customer budget doesn't change it.

`GET /v1/vendors` returns execution hosts, such as `bedrock` ("Amazon Bedrock"), each with `models`, `supports_zdr`, `supports_byok`, and `availability_status` (`active`, `degraded`, or `unavailable`).

## Pagination

`GET /v1/models` and `GET /v1/vendors` return `{"object": "list", "data": [...], "has_more", "next_cursor"}`. `limit` defaults to 50 and caps at 500 (larger returns `422`). The catalog grows, so page with `cursor`: pass the previous `next_cursor` while `has_more` is `true`, repeating any filters. Pages never overlap, but an unknown or stale cursor restarts at the first page, so stop if you see a model ID twice.

**`cURL`**

```bash title="cURL"
curl "https://api-gateway.merge.dev/v1/models?limit=500" \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY"

# Next page: pass the previous response's next_cursor
curl "https://api-gateway.merge.dev/v1/models?limit=500&cursor=mistral/magistral-medium-2509-thinking" \
  -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY"
```

**`Python`**

```python title="Python"
import os
import requests

headers = {"Authorization": f"Bearer {os.environ['MERGE_GATEWAY_API_KEY']}"}
models, seen, cursor = [], set(), None
while True:
    params = {"limit": 500, **({"cursor": cursor} if cursor else {})}
    page = requests.get("https://api-gateway.merge.dev/v1/models", headers=headers, params=params).json()
    new = [m for m in page["data"] if m["model"] not in seen]
    if not new:
        break
    models.extend(new)
    seen.update(m["model"] for m in new)
    if not page["has_more"]:
        break
    cursor = page["next_cursor"]
print(len(models))
```

The Management API paginates separately, up to 100 per page: `GET /v1/keys` uses `offset` and `limit`, and `GET /v1/projects` uses `cursor` and `limit`.

## Shared request fields

All work on `POST /v1/responses`; `customer`, `routing_policy_id`, `priority_order`, and the two metadata flags also work on every SDK-compatible surface.

| Field                         | Description                                                                                                                                                                                                                                                                                                                                                  |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `service_tier`                | `standard` (default), `flex`, `priority`, or `ultrafast` (direct OpenAI routes). `fast` means `priority`, and `default`, `auto`, `unspecified`, and `standard_only` mean `standard`. A tier the route doesn't price returns `400 unsupported_params`. `batch` applies only to `/v1/batches`. See [Service tiers](/merge-gateway/capabilities/service-tiers). |
| `service_tier_fallback`       | `true` retries once at `standard` when the vendor throttles the tier with a `429` or `503`. On streams, only before the first token. Defaults to `false`.                                                                                                                                                                                                    |
| `customer`                    | [Embedded Routing Stack](/merge-gateway/embedded-routing-stack/overview) customer UUID. Its routing policies, vendor keys, budget, and usage apply                                                                                                                                                                                                           |
| `routing_policy_id`           | A routing policy UUID to use for this request                                                                                                                                                                                                                                                                                                                |
| `priority_order`              | An inline priority list of up to 10 models, each a model ID or `{model, priority, vendors}`. It can't be combined with `routing_policy_id`, `vendor`, or `vendors`. See [Sending a priority list with the request](/merge-gateway/routing/using-policies#sending-a-priority-list-with-the-request).                                                          |
| `include_routing_metadata`    | Adds a `routing` object with the policy, vendor, and cost decisions                                                                                                                                                                                                                                                                                          |
| `include_guardrails_metadata` | Adds a `guardrails` object with the [prompt injection](/merge-gateway/security/prompt-injection-protection) and [DLP](/merge-gateway/security/data-loss-prevention) outcome, including on a blocked `422`. It never contains prompt text.                                                                                                                    |
| `logprobs`, `top_logprobs`    | Token log probabilities in OpenAI's shape. A route that refuses them is served without them.                                                                                                                                                                                                                                                                 |
| `parallel_tool_calls`         | `false` limits the model to one tool call per turn                                                                                                                                                                                                                                                                                                           |

**Sampling on fixed-sampling models.** Gateway strips sampling fields a model would reject, so it runs at its own defaults and `temperature: 0` isn't deterministic.

| Models                                    | Dropped                                     |
| ----------------------------------------- | ------------------------------------------- |
| Newest Claude models                      | `temperature`, `top_p`, and `top_k`, always |
| OpenAI GPT-5.4 and later reasoning models | `temperature` and `top_p` unless `1`        |
| Kimi K2.5 and K3 on `moonshot`            | `temperature` unless `1`                    |

When a vendor rejects stop sequences, `stop` is removed and the request retried. `top_k` is honored only on the Anthropic surface.

## Headers

| Header                                                                               | Direction | Meaning                                                                                                                                                                                                                                                                                                               |
| ------------------------------------------------------------------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-merge-vendor`, `x-merge-model`                                                    | Response  | The vendor and canonical model that served a non-streaming request                                                                                                                                                                                                                                                    |
| `x-merge-routing-policy-id`                                                          | Response  | The policy that resolved, on non-streaming requests. On streams, read `routing` from the terminal frame.                                                                                                                                                                                                              |
| `X-Request-ID`                                                                       | Response  | Gateway's request ID, for support                                                                                                                                                                                                                                                                                     |
| `X-Merge-Customer`, `X-Merge-Routing-Policy-Id`                                      | Request   | Header forms of `customer` and `routing_policy_id`. A header that conflicts with the body or a customer API key returns `400 customer_mismatch` or `routing_policy_mismatch`, and a non-UUID returns `400 invalid_customer` or `invalid_routing_policy_id`. The routing policy header applies to chat endpoints only. |
| `include-routing-metadata`, `X-Merge-Include-Routing`, `include-guardrails-metadata` | Request   | Turn metadata on (value `true`). Headers only turn it on, never off. Underscore spellings also work, but nginx drops them by default.                                                                                                                                                                                 |
| `X-Merge-Wire-Format`                                                                | Request   | `openai` or `native` on `POST /v1/responses`. See below.                                                                                                                                                                                                                                                              |

`X-Customer-ID` is a free-form tracing tag and doesn't scope the request.

## OpenAI Responses API clients

OpenAI's Responses API is at `POST /v1/openai/responses`. For clients that reach native `POST /v1/responses` by mistake:

* **Codex** requests (an `originator` header starting with `codex`) get the OpenAI shape automatically
* **`X-Merge-Wire-Format: openai`** returns the OpenAI shape for any caller. Any other value pins the native shape, overriding Codex detection.
* **OpenAI-only fields** with a native equivalent are translated: `instructions` becomes a leading system message, `reasoning.effort` and `reasoning.summary` set reasoning, `text.format` becomes `response_format`, and `max_output_tokens` is an alias of `max_tokens`. A native field wins over its OpenAI counterpart.
* **Other OpenAI-only fields** (`background`, `include`, `max_tool_calls`, `metadata`, `prompt`, `prompt_cache_key`, `stream_options`, `truncation`) are ignored and listed in an `openai_fields_ignored` [warning](/merge-gateway/warnings)

An unknown `reasoning.effort` or a malformed `text.format` returns `400`.

## OpenAI hosted tools on `POST /v1/openai/responses`

OpenAI's hosted tools run only for an `openai/` model on the direct `openai` vendor:

| Tool                                                    | Behavior                                                                                                                                                                                                                                        |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `web_search`, `web_search_preview`                      | Streaming or not. Elsewhere removed with an `openai_web_search_dropped` warning; use `{"type": "merge:web_search"}` for [search on any model](/merge-gateway/capabilities/web-search).                                                          |
| `image_generation`                                      | Removed elsewhere with an `openai_image_generation_dropped` warning                                                                                                                                                                             |
| `tool_search`                                           | Server execution runs on OpenAI, and its items round-trip on the next turn. A request that can't reach OpenAI returns `400 openai_tool_search_requires_openai`. With `"execution": "client"`, the protocol Codex uses, it works on every model. |
| `code_interpreter`, `file_search`, `mcp`, `local_shell` | Never run. `/v1/openai/responses` removes them with a `tools_dropped` warning, and native `/v1/responses` returns `400 unsupported_tool_type`.                                                                                                  |

Anthropic's tool search tools pass through on `/v1/messages`, including Bedrock-hosted Claude.

## Per-call cost

`usage.cost` is the call's USD cost at the pricing of the route and tier that served it, including any model discount or committed-spend contract and OpenAI hosted image generation. It's on `/v1/responses`, embeddings, and the OpenAI, AI SDK, and LangChain surfaces (not Anthropic), and arrives on a stream's terminal frame.

```json
{
  "model": "openai/gpt-5.4",
  "vendor": "openai",
  "service_tier": "flex",
  "usage": { "input_tokens": 812, "output_tokens": 180, "total_tokens": 992, "cost": 0.002365 }
}
```

The top-level `service_tier` is the tier that served and billed the request, so a `flex` request that fell back to `standard` reports and costs `standard`.

| Detail                  | Behavior                                                                                                                                                                                                                                   |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Unpriced route          | `cost` is `null`, never `0`                                                                                                                                                                                                                |
| `routing.cost_usd`      | The same figure, returned with `include_routing_metadata`                                                                                                                                                                                  |
| `routing.merge_fee_usd` | Merge's fee at your plan rate, or `0` when no markup applies, returned with `include_routing_metadata`. On BYOK it's computed on the model's list price, not on `cost_usd`. `null` when `cost_usd` is `null`.                              |
| Server tools            | Web search and other server-tool charges aren't in `cost` or `merge_fee_usd`                                                                                                                                                               |
| Invoice                 | The invoice is the authority. It applies your plan rate, prices BYOK requests at list price, and adds server-tool charges. **Logs** shows both halves per request. See [Cost governance](/merge-gateway/cost/cost-governance-and-savings). |

## Next steps

#### [Get started](/merge-gateway/get-started)

Send your first request through Gateway

#### [Errors](/merge-gateway/errors)

Every error code grouped by HTTP status

#### [Management API](/merge-gateway/management-api)

Manage keys, projects, routing policies, and usage