- Native SDK
- OpenAI SDK
- Anthropic SDK
- Vercel AI SDK
Prerequisites
A Concentrate AI account with an active API key
sk-cn-v1-.Quick Start for Claude Code users
If you use 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:
/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:Step 2: Update Your Client
The two big changes are collapsing the per-SDK base URL ontohttps://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.
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.Request-body field mapping
Request-body field mapping
| 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 |
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 (cost / latency / performance) |
Request header mapping
Request header mapping
| 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 |
SDK / TypeScript option equivalents
SDK / TypeScript option equivalents
| 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 |
Response header mapping
Response header mapping
| 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 for 429 semantics |
Step 4: Decompose Your Routing Policy
Merge bundles routing into named routing policies (referenced byrouting_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.
Routing strategy mapping
Routing strategy mapping
| 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" |
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.
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 |
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 (cost / latency / performance) |
provider/model-id pairs, call GET /v1/models or browse the Model Fortress.
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) | Not applicable. Concentrate owns provider credentials at no per-token BYOK fee |
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 |
| 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; per-key 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 nativemerge-gateway-sdk, you were already on a Responses-style API. Concentrate’s native Responses API 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.
Why migrate to Concentrate
How it works
How it works
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 |
merge-gateway-sdk is Responses-style (client.responses.create(...)). Its closest one-to-one target is Concentrate’s Responses API, reachable from the standard OpenAI SDK or any HTTP client.Team-scale spend management
Team-scale spend management
project_id tagging to maintain.Feature-aware resiliency
Feature-aware resiliency
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 tojson_objector 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.
Strategy-driven auto routing
Strategy-driven auto routing
model: "auto" accepts an explicit optimization target via routing.model.sort: cost, latency, or performance (default). See Auto Routing. This maps cleanly onto Merge’s intelligent routing axes (cost / performance / intelligence).Native Responses and Messages APIs
Native Responses and Messages APIs
Managed provider credentials by default
Managed provider credentials by default
Troubleshooting
Model not found
Model not found
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 for the authoritative list.Invalid API key error
Invalid API key error
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 and confirm there are no extra spaces or quotes.Requests succeed but nothing shows up in the Concentrate dashboard
Requests succeed but nothing shows up in the Concentrate dashboard
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.My project scoping stopped working
My project scoping stopped working
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.My routing policy stopped applying
My routing policy stopped applying
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. Tag-based routing has no direct equivalent, so handle it with per-condition keys in application code.Connection errors
Connection errors
https://api.concentrate.ai/v1 (no /api segment, no per-SDK suffix like /openai or /anthropic). Test the connection manually: