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

# Merge

> Migrate from Merge Gateway to Concentrate AI: what changes, what carries over, and what does not.

<Tabs>
  <Tab title="Native SDK">
    <CodeGroup>
      ```python Python theme={null}
      # Before
      from merge_gateway import MergeGateway
      import os

      client = MergeGateway(api_key=os.environ["MERGE_GATEWAY_API_KEY"])

      response = client.responses.create(
          model="openai/gpt-4o",
          input=[{"type": "message", "role": "user", "content": "Say hello in one word"}],
          project_id="summarizer",
      )

      # After
      from openai import OpenAI
      import os

      client = OpenAI(
          base_url="https://api.concentrate.ai/v1",
          api_key=os.environ["CONCENTRATE_API_KEY"],
      )

      response = client.responses.create(
          model="openai/gpt-4o",
          input=[{"type": "message", "role": "user", "content": "Say hello in one word"}],
      )
      ```

      ```javascript JavaScript theme={null}
      // Before
      import { MergeGateway } from "merge-gateway-sdk";

      const client = new MergeGateway({ apiKey: process.env.MERGE_GATEWAY_API_KEY });

      const response = await client.responses.create({
        model: "openai/gpt-4o",
        input: [{ type: "message", role: "user", content: "Say hello in one word" }],
        project_id: "summarizer",
      });

      // After
      import OpenAI from "openai";

      const client = new OpenAI({
        baseURL: "https://api.concentrate.ai/v1",
        apiKey: process.env.CONCENTRATE_API_KEY,
      });

      const response = await client.responses.create({
        model: "openai/gpt-4o",
        input: [{ type: "message", role: "user", content: "Say hello in one word" }],
      });
      ```

      ```bash cURL theme={null}
      # Before
      curl https://api-gateway.merge.dev/v1/responses \
        -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{ "model": "openai/gpt-4o", "input": [...], "project_id": "summarizer" }'

      # After
      curl https://api.concentrate.ai/v1/responses \
        -H "Authorization: Bearer $CONCENTRATE_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{ "model": "openai/gpt-4o", "input": [...] }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="OpenAI SDK">
    <CodeGroup>
      ```python Python (OpenAI SDK) theme={null}
      # Before
      from openai import OpenAI
      import os

      client = OpenAI(
          base_url="https://api-gateway.merge.dev/v1/openai",
          api_key=os.environ["MERGE_GATEWAY_API_KEY"],
      )

      # After
      from openai import OpenAI
      import os

      client = OpenAI(
          base_url="https://api.concentrate.ai/v1",
          api_key=os.environ["CONCENTRATE_API_KEY"],
      )
      ```

      ```javascript JavaScript (OpenAI SDK) theme={null}
      // Before
      import OpenAI from "openai";

      const client = new OpenAI({
        baseURL: "https://api-gateway.merge.dev/v1/openai",
        apiKey: process.env.MERGE_GATEWAY_API_KEY,
      });

      // After
      const client = new OpenAI({
        baseURL: "https://api.concentrate.ai/v1",
        apiKey: process.env.CONCENTRATE_API_KEY,
      });
      ```

      ```bash cURL theme={null}
      # Before
      curl https://api-gateway.merge.dev/v1/openai/chat/completions \
        -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{ "model": "gpt-4o", "messages": [...] }'

      # After
      curl https://api.concentrate.ai/v1/chat/completions \
        -H "Authorization: Bearer $CONCENTRATE_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{ "model": "gpt-4o", "messages": [...] }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Anthropic SDK">
    <CodeGroup>
      ```python Python theme={null}
      # Before
      from anthropic import Anthropic
      import os

      client = Anthropic(
          base_url="https://api-gateway.merge.dev/v1/anthropic",
          api_key=os.environ["MERGE_GATEWAY_API_KEY"],
      )

      # After
      from openai import OpenAI
      import os

      client = OpenAI(
          base_url="https://api.concentrate.ai/v1",
          api_key=os.environ["CONCENTRATE_API_KEY"],
      )
      ```

      ```javascript JavaScript theme={null}
      // Before
      import Anthropic from "@anthropic-ai/sdk";

      const client = new Anthropic({
        baseURL: "https://api-gateway.merge.dev/v1/anthropic",
        apiKey: process.env.MERGE_GATEWAY_API_KEY,
      });

      // After
      import OpenAI from "openai";

      const client = new OpenAI({
        baseURL: "https://api.concentrate.ai/v1",
        apiKey: process.env.CONCENTRATE_API_KEY,
      });
      ```

      ```bash cURL theme={null}
      # Before
      curl https://api-gateway.merge.dev/v1/anthropic/v1/messages \
        -H "Authorization: Bearer $MERGE_GATEWAY_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{ "model": "claude-sonnet-4-20250514", "messages": [...] }'

      # After (Anthropic-compatible Messages API)
      curl https://api.concentrate.ai/v1/messages \
        -H "Authorization: Bearer $CONCENTRATE_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{ "model": "anthropic/claude-opus-4-6", "messages": [...] }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Vercel AI SDK">
    <CodeGroup>
      ```javascript JavaScript (provider) theme={null}
      // Before
      import { createMergeGateway } from "merge-gateway-ai-sdk-provider";
      import { generateText } from "ai";

      const gateway = createMergeGateway({ apiKey: process.env.MERGE_GATEWAY_API_KEY });

      const { text } = await generateText({
        model: gateway("openai/gpt-4o"),
        prompt: "Say hello in one word",
      });

      // After
      import { createOpenAI } from "@ai-sdk/openai";
      import { generateText } from "ai";

      const gateway = createOpenAI({
        baseURL: "https://api.concentrate.ai/v1",
        apiKey: process.env.CONCENTRATE_API_KEY,
      });

      const { text } = await generateText({
        model: gateway("openai/gpt-4o"),
        prompt: "Say hello in one word",
      });
      ```

      ```javascript JavaScript (URL shim) theme={null}
      // Before
      import { createOpenAI } from "@ai-sdk/openai";

      const gateway = createOpenAI({
        baseURL: "https://api-gateway.merge.dev/v1/ai-sdk",
        apiKey: process.env.MERGE_GATEWAY_API_KEY,
      });

      // After
      const gateway = createOpenAI({
        baseURL: "https://api.concentrate.ai/v1",
        apiKey: process.env.CONCENTRATE_API_KEY,
      });
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Prerequisites

<Steps>
  <Step title="A Concentrate AI account with an active API key">
    Sign up or log in at [concentrate.ai](https://concentrate.ai) and create an API key. Your key should start with `sk-cn-v1-`.
  </Step>

  <Step title="An existing Merge Gateway integration">
    This guide assumes you are calling Merge Gateway from the `merge-gateway-sdk`, the OpenAI SDK, the Anthropic SDK, the Vercel AI SDK provider, `fetch`, `requests`, or another HTTP client.
  </Step>
</Steps>

## Quick Start for Claude Code users

If you use [Claude Code](https://claude.com/claude-code), you can install a skill that walks through this migration interactively. It searches your project for Merge Gateway usage, collapses the per-SDK base URLs, strips Merge-specific fields and headers, decomposes routing policies, maps model slugs, and generates a verification script. Drop the skill into your `~/.claude/skills/` directory:

```bash theme={null}
mkdir -p ~/.claude/skills/migrate-merge && \
  curl -fsSL https://concentrate.ai/scripts/migrate-merge.md \
  -o ~/.claude/skills/migrate-merge/SKILL.md
```

Then start a Claude Code session in your project and ask it to "migrate from Merge Gateway to Concentrate" or run `/migrate-merge`. Claude will load the skill and run the steps.

## Step 1: Update Your Environment Variables

Replace your Merge key (and any BYOK provider keys) with a single Concentrate key:

```bash theme={null}
# Before
export MERGE_GATEWAY_API_KEY="mg_..."
export BASE_URL="https://api-gateway.merge.dev/v1/openai"

# After
export CONCENTRATE_API_KEY="sk-cn-v1-..."
export BASE_URL="https://api.concentrate.ai/v1"
```

<Warning>
  If you ran Merge in BYOK mode, you no longer need `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, AWS credentials, or any other upstream provider key in your environment — Concentrate manages provider credentials by default, and if you want to keep using your own keys, store them once in the dashboard with [BYOK](/docs/api-reference/endpoint/byok).
</Warning>

## Step 2: Update Your Client

The two big changes are collapsing the per-SDK base URL onto `https://api.concentrate.ai/v1` and dropping Merge-specific fields and headers. If you were using the native `merge-gateway-sdk`, swap to the OpenAI SDK pointed at Concentrate. Concentrate does not ship a dedicated SDK because the OpenAI-compatible shape covers every endpoint.

<CodeGroup>
  ```python Python (OpenAI SDK) theme={null}
  # Before (native merge-gateway-sdk)
  from merge_gateway import MergeGateway

  client = MergeGateway(api_key=os.environ["MERGE_GATEWAY_API_KEY"])

  # After (Concentrate)
  from openai import OpenAI
  import os

  client = OpenAI(
      base_url="https://api.concentrate.ai/v1",
      api_key=os.environ["CONCENTRATE_API_KEY"],
  )

  response = client.chat.completions.create(
      model="anthropic/claude-opus-4-6",
      messages=[{"role": "user", "content": "Say hello in one word"}],
  )
  print(response.choices[0].message.content)
  ```

  ```javascript JavaScript (OpenAI SDK) theme={null}
  // Before (native merge-gateway-sdk)
  import { MergeGateway } from "merge-gateway-sdk";

  const client = new MergeGateway({ apiKey: process.env.MERGE_GATEWAY_API_KEY });

  // After (Concentrate)
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.concentrate.ai/v1",
    apiKey: process.env.CONCENTRATE_API_KEY,
  });

  const response = await client.chat.completions.create({
    model: "anthropic/claude-opus-4-6",
    messages: [{ role: "user", content: "Say hello in one word" }],
  });
  console.log(response.choices[0].message.content);
  ```

  ```bash cURL theme={null}
  curl https://api.concentrate.ai/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $CONCENTRATE_API_KEY" \
    -d '{
      "model": "anthropic/claude-opus-4-6",
      "messages": [{"role": "user", "content": "Say hello in one word"}]
    }'
  ```
</CodeGroup>

## Step 3: Remove Merge-Specific Fields and Headers

None of Merge Gateway's custom request fields or headers carry over to Concentrate, so they should come out. They're dead weight in your client config and mislead future readers. Expand the tables below for the full mapping if any of these are in your code.

<AccordionGroup>
  <Accordion title="Request-body field mapping" icon="arrow-right-arrow-left">
    | Merge field                                                | Concentrate replacement                                                                                                                                                |
    | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `project_id`                                               | Drop. Issue per-project keys (or per-team / per-org keys); analytics roll up by whichever key, team, or org the request was made with. No per-request scoping field    |
    | `tags`                                                     | Drop. Use the key/team/org hierarchy for attribution. No per-request tagging                                                                                           |
    | `routing_policy_id`                                        | Drop. Express routing as `routing.model.fallbacks` / `routing.provider.fallbacks` body params, or `model: "auto"`. See [Step 4](#step-4-decompose-your-routing-policy) |
    | `vendor`, `vendors` (vendor routing / ordered vendor list) | Drop. Pin via the model slug (`provider/model-id`), or order providers with `routing.provider.fallbacks`                                                               |
    | `include_routing_metadata`                                 | Drop. The resolved provider is recorded per request in the dashboard                                                                                                   |
    | `model: "default_routing"`                                 | `model: "auto"` with explicit [`routing.model.sort`](/docs/api-reference/endpoint/auto-routing) (`cost` / `latency` / `performance`)                                        |
  </Accordion>

  <Accordion title="Request header mapping" icon="arrow-right-arrow-left">
    <Warning>
      Merge supports two transports each for project scoping and tags. **Project scoping:** a `project_id` request-body field (canonical, used by both the Responses API schema and the Continue.dev guide, the latter via `requestOptions.extraBodyProperties`) and an `X-Project-Id` header. **Tags:** a `tags` request-body field (Responses API schema) and an `X-Merge-Tags` header. There is no deprecation notice for the header forms in the Merge changelog. **Search your code for all four forms.** None carries over to Concentrate.
    </Warning>

    | Merge header                   | Concentrate replacement                                             |
    | ------------------------------ | ------------------------------------------------------------------- |
    | `Authorization: Bearer mg_...` | Standard `Authorization: Bearer sk-cn-v1-...`                       |
    | `X-Project-Id`                 | Drop. Per-key / team / org scoping replaces per-request project IDs |
    | `X-Merge-Tags`                 | Drop. No per-request tags; attribution comes from the key/team/org  |
  </Accordion>

  <Accordion title="SDK / TypeScript option equivalents" icon="code">
    | Merge option                                                                 | Concentrate replacement                                                                                        |
    | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
    | `merge-gateway-sdk` (`MergeGateway`)                                         | OpenAI SDK pointed at `https://api.concentrate.ai/v1`                                                          |
    | `merge-gateway-ai-sdk-provider` (`createMergeGateway`)                       | `@ai-sdk/openai` `createOpenAI` with `baseURL` set to Concentrate                                              |
    | `providerOptions.mergeGateway` (tags, vendor routing, routing metadata)      | Drop. Vendor routing → model slug (`provider/model-id`) or `routing.*`; tags / metadata → key/team/org rollups |
    | `requestOptions.extraBodyProperties` (used to send `project_id` in the body) | Drop. No per-request project field                                                                             |
    | `extra_headers={"X-Project-Id": ...}` (Python)                               | Drop. Per-key / team / org scoping                                                                             |
  </Accordion>

  <Accordion title="Response header mapping" icon="arrow-left">
    | Merge response header                        | Concentrate equivalent                                                                           |
    | -------------------------------------------- | ------------------------------------------------------------------------------------------------ |
    | Merge request / trace id                     | `X-Request-Id` (Concentrate returns its own per-request id, surfaced in dashboard logs)          |
    | Resolved-provider / routing-decision headers | No header. The resolved provider is recorded per request in the dashboard                        |
    | Rate-limit headers                           | Standard `X-RateLimit-*` headers. See [Errors](/docs/api-reference/endpoint/errors) for 429 semantics |
  </Accordion>
</AccordionGroup>

## Step 4: Decompose Your Routing Policy

Merge bundles routing into named **routing policies** (referenced by `routing_policy_id`, or handed off via `model: "default_routing"`). Concentrate has no routing-policy primitive. Each behavior is either on by default or expressed as a body param on the request. Expand the table below for the full mapping.

<Accordion title="Routing strategy mapping" icon="arrow-right-arrow-left">
  | Merge routing strategy                                            | Concentrate equivalent                                             |
  | ----------------------------------------------------------------- | ------------------------------------------------------------------ |
  | **Single** (`type: "fallback"`, one target)                       | Pin the model: `model: "provider/model-id"`                        |
  | **Priority** (`type: "fallback"`, ordered targets)                | `routing.model.fallbacks` / `routing.provider.fallbacks` (ordered) |
  | **Least Latency**                                                 | `model: "auto"` with `routing.model.sort: "latency"`               |
  | **Lowest Cost**                                                   | `model: "auto"` with `routing.model.sort: "cost"`                  |
  | **Cost Optimized** (`type: "intelligent"`, `axis: "cost"`)        | `model: "auto"` with `routing.model.sort: "cost"`                  |
  | **Balanced** (`type: "intelligent"`, `axis: "performance"`)       | `model: "auto"` with `routing.model.sort: "performance"` (default) |
  | **Quality First** (`type: "intelligent"`, `axis: "intelligence"`) | `model: "auto"` with `routing.model.sort: "performance"`           |
</Accordion>

<Warning>
  Merge's **tag-based routing** (rules with operators `eq`, `gt`, `in`, `contains`, `starts_with`, `exists` and AND/OR logic that steer a request by its tags) has no direct equivalent. Concentrate's conditional routing conditions on **request capabilities** (feature support, ZDR flag, per-feature uptime, cache affinity), not on **request attributes** like tags. If your policy routes on tags, the migration path is to issue separate keys per condition and pick the key in application code.
</Warning>

## Step 5: Update Model Identifiers

Concentrate accepts model strings in two forms:

* **Bare slug**, e.g. `gpt-4o`, `claude-haiku-4-5`, `auto`. Routing picks a provider.
* **`provider/model-id`**, e.g. `bedrock/claude-haiku-4-5`, `openai/gpt-4o`. Pins the request to a specific provider.

Merge already uses provider-prefixed slugs in its native SDK (`openai/gpt-4o`, `anthropic/claude-sonnet-4-20250514`), so most strings carry over directly. The SDK shims (OpenAI, Anthropic) used bare slugs, which work as-is too.

One thing to know about the slashed form: **the prefix is the provider that serves the request, not the model's author.** For most popular names the two are the same string (`openai`, `anthropic`, `mistral`, `cohere`). They diverge whenever a model is hosted by something other than its author:

| Author                                 | Provider serving the request | Concentrate slug              |
| -------------------------------------- | ---------------------------- | ----------------------------- |
| Anthropic (`claude-haiku-4-5`)         | Anthropic                    | `anthropic/claude-haiku-4-5`  |
| Anthropic (same model, different host) | AWS Bedrock                  | `bedrock/claude-haiku-4-5`    |
| Anthropic (same model, different host) | Azure                        | `azure/claude-haiku-4-5`      |
| Google (`gemini-3.5-flash`)            | Google AI Studio             | `ai-studio/gemini-3.5-flash`  |
| Meta (`llama-3-8b-instruct`)           | AWS Bedrock                  | `bedrock/llama-3-8b-instruct` |

Bare slugs work in all of these cases. Use them when you don't care which provider serves the request. Use the `provider/` prefix when you specifically want to pin to one host (for ZDR compliance, contractual reasons, or latency in a specific region).

The only universally required slug change is auto-routing:

| Merge Gateway                                | Concentrate AI                                                                                                                  |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `model: "default_routing"` (or omit `model`) | `model: "auto"` with explicit [`routing.model.sort`](/docs/api-reference/endpoint/auto-routing) (`cost` / `latency` / `performance`) |

For the authoritative list of supported `provider/model-id` pairs, call [`GET /v1/models`](/docs/api-reference/endpoint/list-models) or browse the [Model Fortress](https://concentrate.ai/models).

## Step 6: Map Projects, Budgets, and Compression

Merge's project, budget, and compression features map onto Concentrate's key hierarchy and built-in routing rather than per-request configuration.

| Merge Gateway concept                                                                                                              | Concentrate equivalent                                                                                                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Project** (slug-based org unit with its own budget, routing policy, and compression)                                             | **Team** or a dedicated **key** within an organization. Spend, routing, and limits attach to the key/team                                                           |
| **Budget: Soft Limit** (alerts only; thresholds 50 / 80 / 90%)                                                                     | Spend alerts on the key/team                                                                                                                                        |
| **Budget: Hard Limit** (HTTP 402 block)                                                                                            | Per-key spend limits; requests are rejected once the cap is hit                                                                                                     |
| **Budget periods** (daily / weekly / monthly / quarterly / yearly)                                                                 | Per-key spend limits in the dashboard                                                                                                                               |
| **Context compression** (Context Window Only / Cost Optimization / Disabled; lossless JSON minification + middle-message trimming) | No gateway-side compression. Manage context in application code, or rely on auto-routing to pick a model with sufficient context                                    |
| **BYOK** (\$0.05 / M tokens)                                                                                                       | Free. Store your keys once in the dashboard ([BYOK](/docs/api-reference/endpoint/byok)) and routing uses them automatically — Concentrate never charges for BYOK traffic |

## Step 7: Reconnect Observability

Concentrate's dashboard covers the major surfaces you used in the Merge Gateway dashboard (`gateway.merge.dev`).

| Merge Gateway surface                                    | Concentrate equivalent                                                                                                                             |
| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| Request logs (every routing decision, cost, outcome)     | Per-request logs at [concentrate.ai](https://concentrate.ai)                                                                                       |
| Project-scoped spend                                     | Org / team / developer / key spend rollups                                                                                                         |
| Tag breakdowns                                           | Per-key / team / org rollups. No per-request tag dimension                                                                                         |
| Routing decision history                                 | Resolved provider recorded per request in the dashboard                                                                                            |
| Budgets & spend caps                                     | Per-key rate and spend limits                                                                                                                      |
| Audit trail / roles & permissions                        | Organization and team members + audit logs in the dashboard                                                                                        |
| Security (blocklist, geo routing, prompt injection, DLP) | [Guardrails & Redaction](/docs/api-reference/endpoint/guardrails-redaction); per-key [Zero Data Retention](/docs/api-reference/endpoint/zero-data-retention) |

### Exporting your Merge history

Merge Gateway's dashboards do not import into Concentrate, and the reverse is also true. Historical request logs stay where they were created. If your migration is driven by compliance or audit requirements, export your history from the Merge Gateway dashboard before deprovisioning.

## Step 8 (Optional): Adopt the Responses API

If you used Merge's native `merge-gateway-sdk`, you were already on a Responses-style API. Concentrate's native [Responses API](/docs/api-reference/endpoint/create-response) is the direct successor: it supports streaming, tool calling, structured output, multi-modal input, and web search through a single normalized shape across every provider, and `previous_response_id` links related requests into a server-managed conversation tree.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.concentrate.ai/v1/responses \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $CONCENTRATE_API_KEY" \
    -d '{
      "model": "anthropic/claude-opus-4-6",
      "input": "What is the capital of France?"
    }'
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.post(
      "https://api.concentrate.ai/v1/responses",
      headers={
          "Authorization": f"Bearer {os.environ['CONCENTRATE_API_KEY']}",
          "Content-Type": "application/json",
      },
      json={
          "model": "anthropic/claude-opus-4-6",
          "input": "What is the capital of France?",
      },
  )
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.concentrate.ai/v1/responses", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.CONCENTRATE_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "anthropic/claude-opus-4-6",
      input: "What is the capital of France?",
    }),
  });
  console.log(await response.json());
  ```
</CodeGroup>

## Why migrate to Concentrate

<AccordionGroup>
  <Accordion title="How it works" icon="circle-info">
    Merge Gateway exposes one native endpoint plus four SDK-compatibility shims, each on its own base URL. Migrating collapses all five onto Concentrate's single base URL `https://api.concentrate.ai/v1`.

    | Merge integration        | Merge base URL                               |
    | ------------------------ | -------------------------------------------- |
    | Native Merge Gateway SDK | `https://api-gateway.merge.dev/v1`           |
    | OpenAI SDK               | `https://api-gateway.merge.dev/v1/openai`    |
    | Anthropic SDK            | `https://api-gateway.merge.dev/v1/anthropic` |
    | Vercel AI SDK            | `https://api-gateway.merge.dev/v1/ai-sdk`    |
    | LangChain                | `https://api-gateway.merge.dev/v1/openai`    |

    The native `merge-gateway-sdk` is Responses-style (`client.responses.create(...)`). Its closest one-to-one target is Concentrate's [Responses API](/docs/api-reference/endpoint/create-response), reachable from the standard OpenAI SDK or any HTTP client.
  </Accordion>

  <Accordion title="Team-scale spend management" icon="building">
    Concentrate organizes billing around an **organization → team → developer → key** hierarchy. Set budgets at any level and roll spend up into a single dashboard. Per-team budgets and per-developer attribution come from the key itself, so there's no per-request `project_id` tagging to maintain.
  </Accordion>

  <Accordion title="Feature-aware resiliency" icon="shield-check">
    Beyond ordered model and provider fallbacks (`routing.model.fallbacks`, `routing.provider.fallbacks`), Concentrate's routing layer ships:

    * **Uptime gate.** Providers whose per-feature success rate drops below 90% are skipped.
    * **Feature degradation.** If no provider supports the full requested feature set (e.g. `json_schema`), the request is downgraded to `json_object` or text instead of failing.
    * **Cache-affinity routing.** When multiple providers can serve a request, the one where your actor already has cached tokens is preferred.

    All on by default. No routing policy to author, name, or version.
  </Accordion>

  <Accordion title="Strategy-driven auto routing" icon="route">
    `model: "auto"` accepts an explicit optimization target via `routing.model.sort`: `cost`, `latency`, or `performance` (default). See [Auto Routing](/docs/api-reference/endpoint/auto-routing). This maps cleanly onto Merge's `intelligent` routing axes (`cost` / `performance` / `intelligence`).
  </Accordion>

  <Accordion title="Native Responses and Messages APIs" icon="code">
    Like Merge Gateway's native SDK, Concentrate exposes a first-class [Responses API](/docs/api-reference/endpoint/create-response). Alongside it you also get OpenAI Chat Completions compatibility and an Anthropic-compatible [Messages API](/docs/api-reference/endpoint/create-message).
  </Accordion>

  <Accordion title="Managed provider credentials by default" icon="key">
    Concentrate manages provider credentials by default — point at a model and Concentrate owns the upstream credentials. And if you want to keep using the provider keys you carried for Merge's BYOK mode, [BYOK](/docs/api-reference/endpoint/byok) is completely free — unlike Merge's \$0.05 / M tokens.
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Model not found" icon="circle-question">
    Bare slugs (`gpt-4o`, `claude-haiku-4-5`) and `provider/model-id` slugs both work. If you're using a `provider/` prefix and getting a miss, double-check the prefix is a provider (e.g. `bedrock`, `azure`, `ai-studio`) and not just the author (e.g. `meta`, `google`). Call [`GET /v1/models`](/docs/api-reference/endpoint/list-models) for the authoritative list.
  </Accordion>

  <Accordion title="Invalid API key error" icon="triangle-exclamation">
    Concentrate keys start with `sk-cn-v1-`. If you are still sending a Merge `mg_...` key as the `Authorization` bearer, you will see a 401. Verify the value in your [dashboard](https://concentrate.ai) and confirm there are no extra spaces or quotes.
  </Accordion>

  <Accordion title="Requests succeed but nothing shows up in the Concentrate dashboard" icon="chart-line">
    Confirm the base URL is `https://api.concentrate.ai/v1`, not `api-gateway.merge.dev`. If the SDK is still pointed at Merge it is logging against your Merge Gateway dashboard, not Concentrate.
  </Accordion>

  <Accordion title="My project scoping stopped working" icon="folder">
    Concentrate has no `project_id` body field or `X-Project-Id` header. Per-project spend and analytics come from issuing a separate key (or team) per project; rollups happen automatically by key/team/org. Drop both the `project_id` body field and the `X-Project-Id` header.
  </Accordion>

  <Accordion title="My routing policy stopped applying" icon="route">
    `routing_policy_id` and `model: "default_routing"` are no-ops on Concentrate. Express fallbacks via `routing.model.fallbacks` / `routing.provider.fallbacks` body params, or use `model: "auto"` with a [routing strategy](/docs/api-reference/endpoint/auto-routing). Tag-based routing has no direct equivalent, so handle it with per-condition keys in application code.
  </Accordion>

  <Accordion title="Connection errors" icon="wifi">
    Confirm the base URL is `https://api.concentrate.ai/v1` (no `/api` segment, no per-SDK suffix like `/openai` or `/anthropic`). Test the connection manually:

    ```bash theme={null}
    curl https://api.concentrate.ai/v1/responses/health
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/docs/api-reference/introduction">
    Explore the full API capabilities
  </Card>

  <Card title="Available Models" icon="layer-group" href="/docs/api-reference/endpoint/list-models">
    Browse all supported models
  </Card>

  <Card title="Auto Routing" icon="route" href="/docs/api-reference/endpoint/auto-routing">
    Optimize model selection automatically
  </Card>

  <Card title="Get Support" icon="life-ring" href="mailto:support@concentrate.ai">
    Contact our support team
  </Card>
</CardGroup>

## Feedback

If you hit anything that didn't translate cleanly (especially around projects, routing policies, tag-based routing, context compression, or per-request scoping), email [support@concentrate.ai](mailto:support@concentrate.ai). The capability gaps called out above are tracked, and migration friction reports directly shape what we ship next.
