Skip to main content
// Before
import { generateText } from "ai";

const { text } = await generateText({
  model: "anthropic/claude-opus-4.7",
  prompt: "Say hello in one word",
});
// Auth read from AI_GATEWAY_API_KEY (or VERCEL_OIDC_TOKEN) in the environment

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

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

const { text } = await generateText({
  model: concentrate("anthropic/claude-opus-4-6"),
  prompt: "Say hello in one word",
});

Prerequisites

1

A Concentrate AI account with an active API key

Sign up or log in at concentrate.ai and create an API key. Your key should start with sk-cn-v1-.
2

An existing Vercel AI Gateway integration

This guide assumes you are calling AI Gateway from the AI SDK (@ai-sdk/gateway), the OpenAI SDK (Chat Completions or Responses), the Anthropic SDK, fetch, requests, or another HTTP client.

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 AI Gateway usage, collapses the per-surface base URLs (including the Anthropic-base-URL trap), strips Vercel-specific headers, decomposes providerOptions.gateway, maps model slugs, and generates a verification script. Drop the skill into your ~/.claude/skills/ directory:
mkdir -p ~/.claude/skills/migrate-vercel && \
  curl -fsSL https://concentrate.ai/scripts/migrate-vercel.md \
  -o ~/.claude/skills/migrate-vercel/SKILL.md
Then start a Claude Code session in your project and ask it to “migrate from Vercel AI Gateway to Concentrate” or run /migrate-vercel. Claude will load the skill and run the steps.
If you were running Claude Code itself through AI Gateway (via ANTHROPIC_BASE_URL=https://ai-gateway.vercel.sh), point it at Concentrate instead. See the Claude Code integration guide.

Step 1: Update Your Environment Variables

Replace your AI Gateway key (and any BYOK provider keys) with a single Concentrate key:
# Before
export AI_GATEWAY_API_KEY="vck_..."
export BASE_URL="https://ai-gateway.vercel.sh/v1"

# After
export CONCENTRATE_API_KEY="sk-cn-v1-..."
export BASE_URL="https://api.concentrate.ai/v1"
If you authenticated with a Vercel OIDC token (VERCEL_OIDC_TOKEN, auto-provisioned on Vercel deployments and valid for ~12 hours), that mechanism does not carry over. Concentrate keys never expire unless revoked, so the process.env.AI_GATEWAY_API_KEY || process.env.VERCEL_OIDC_TOKEN fallback pattern collapses to a single CONCENTRATE_API_KEY. If you ran any BYOK credentials, you no longer need OPENAI_API_KEY, ANTHROPIC_API_KEY, AWS credentials, or any other upstream provider key.

Step 2: Update Your Client

The two big changes are collapsing the base URL onto https://api.concentrate.ai/v1 and dropping Vercel-specific headers and providerOptions.gateway fields. If you used the native @ai-sdk/gateway provider, swap to @ai-sdk/openai pointed at Concentrate. Concentrate does not ship a dedicated SDK because the OpenAI-compatible shape covers every endpoint.
Anthropic base-URL difference. Vercel’s Anthropic surface uses https://ai-gateway.vercel.sh with no /v1; the OpenAI surfaces use …/v1. Concentrate uses the same https://api.concentrate.ai/v1 base for every surface, so if you were special-casing the Anthropic base URL, remove that branch.
# Before
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://ai-gateway.vercel.sh/v1",
    api_key=os.environ["AI_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"],
)

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)

Step 3: Remove Vercel-Specific Headers

None of AI Gateway’s custom 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.
Vercel headerConcentrate replacement
Authorization: Bearer vck_...Standard Authorization: Bearer sk-cn-v1-...
x-api-key (Anthropic surface only)Standard Authorization: Bearer sk-cn-v1-.... Concentrate’s Messages API also accepts x-api-key for Anthropic-SDK compatibility
http-referer (app attribution)Drop. No per-request app attribution; analytics roll up by key/team/org
x-title (app attribution)Drop. No per-request app attribution
Auto-injected o11y headers (VERCEL_DEPLOYMENT_ID, VERCEL_PROJECT_ID via the AI SDK)Drop. Concentrate records its own per-request telemetry in the dashboard
Vercel response surfaceConcentrate equivalent
providerMetadata.gateway (routing info, cost, service tier in the response body)No body field. The resolved provider and cost are recorded per request in the dashboard
Request / trace idX-Request-Id (Concentrate returns its own per-request id, surfaced in dashboard logs)
Rate-limit headersStandard X-RateLimit-* headers. See Errors for 429 semantics

Step 4: Decompose Your providerOptions.gateway

AI Gateway layers routing, fallback, caching, and compliance controls onto the standard request body under providerOptions.gateway (and a few top-level fields). A naïve “just change the base URL” migration silently drops these. Concentrate has no providerOptions.gateway 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.
Vercel optionConcentrate equivalent
order: [...] (ordered provider fallback)routing.provider.fallbacks (ordered)
only: [...] (allowed provider set)Pin via the model slug (provider/model-id), or constrain with routing.provider.fallbacks
sort: 'cost'model: "auto" with routing.model.sort: "cost"
sort: 'ttft' (time to first token)model: "auto" with routing.model.sort: "latency"
sort: 'tps' (throughput)model: "auto" with routing.model.sort: "performance"
models: [...] (model-level fallback chain)routing.model.fallbacks (ordered)
byok: { provider: [{...}] } (request-scoped BYOK)Drop. Concentrate owns provider credentials at no per-token BYOK fee
providerTimeouts: {...} (per-provider failover timeouts)Automatic failover on any provider error across your fallback chain, plus the 90% per-feature uptime gate
caching: 'auto' (auto cache breakpoints)Provider-native prompt caching on Anthropic + AWS Bedrock. Manual cache_control: { type: 'ephemeral' } is honored too
zeroDataRetention: trueKey-level Zero Data Retention, not a request param
disallowPromptTraining: trueCovered by ZDR-certified provider routing. Configure at the key level
serviceTier: 'flex' | 'priority'No equivalent today. Concentrate routes for uptime and latency automatically
reasoning: { effort, max_tokens, ... }Pass reasoning controls in the standard request body. The Responses API normalizes reasoning across providers
Concentrate has conditional routing, but it conditions on request capabilities (feature support, ZDR flag, per-feature uptime, cache affinity), not on a per-request provider allow-list or sort key handed in the body. If your code relied on only/order/sort to steer specific requests, express the durable cases as routing.* body params or pin the model slug.

Step 5: Update Model Identifiers

Concentrate accepts model strings in two forms:
  • Bare slug, e.g. gpt-5.5, claude-haiku-4-5, auto. Routing picks a provider.
  • provider/model-id, e.g. bedrock/claude-haiku-4-5, openai/gpt-5.5. Pins the request to a specific provider.
Vercel always uses the provider/model form (e.g. anthropic/claude-opus-4.7, openai/gpt-5.5, xai/grok-4.3), so most strings carry over directly once you reconcile version suffixes against GET /v1/models. 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:
AuthorProvider serving the requestConcentrate slug
Anthropic (claude-haiku-4-5)Anthropicanthropic/claude-haiku-4-5
Anthropic (same model, different host)AWS Bedrockbedrock/claude-haiku-4-5
Anthropic (same model, different host)Azureazure/claude-haiku-4-5
Google (gemini-3.5-flash)Google AI Studioai-studio/gemini-3.5-flash
Meta (llama-3-8b-instruct)AWS Bedrockbedrock/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:
Vercel AI GatewayConcentrate AI
sort: 'cost' | 'ttft' | 'tps' in providerOptions.gatewaymodel: "auto" with explicit routing.model.sort (cost / latency / performance)
For the authoritative list of supported provider/model-id pairs, call GET /v1/models or browse the Model Fortress.

Step 6: Reconnect Observability

Concentrate’s dashboard covers the major surfaces you used in the AI Gateway dashboard.
Vercel AI Gateway surfaceConcentrate equivalent
Request logs (every routing decision, cost, outcome)Per-request logs at concentrate.ai
Spend monitoring / budgetsOrg / team / developer / key spend rollups and per-key spend limits
App attribution (http-referer / x-title)No per-request attribution. Roll up by key/team/org
Routing metadata (providerMetadata.gateway)Resolved provider recorded per request in the dashboard
Observability traces (Vercel Observability → AI)Per-request logs; previous_response_id on the Responses API links related requests into a stateful tree
BYOK ($0 markup)Not applicable. Concentrate owns provider credentials at no per-token BYOK fee

Exporting your AI Gateway history

Vercel’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 Vercel dashboard before deprovisioning.

Step 7 (Optional): Adopt the Responses API

If you used Vercel’s OpenAI Responses surface (or the native AI SDK), 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.
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?"
  }'

Why migrate to Concentrate

AI Gateway exposes three request schemas across two base URLs, plus a native AI SDK provider. Migrating collapses all of them onto Concentrate’s single base URL https://api.concentrate.ai/v1.
Vercel surfaceVercel base URL
OpenAI Chat Completionshttps://ai-gateway.vercel.sh/v1
OpenAI Responseshttps://ai-gateway.vercel.sh/v1
Anthropic Messageshttps://ai-gateway.vercel.sh (no /v1)
Native AI SDK (@ai-sdk/gateway)resolved automatically from a plain string model id
Concentrate’s Responses API is the closest one-to-one target for Vercel’s Responses surface and the native AI SDK, reachable from the standard OpenAI SDK or any HTTP client.
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 http-referer / x-title attribution to maintain.
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 providerOptions.gateway block to author per request.
model: "auto" accepts an explicit optimization target via routing.model.sort: cost, latency, or performance (default). See Auto Routing. This maps cleanly onto Vercel’s sort metrics (cost / ttft / tps).
Like AI Gateway’s Responses and Anthropic surfaces, Concentrate exposes a first-class Responses API and an Anthropic-compatible Messages API, both on the same …/v1 base, with no per-surface base-URL difference.
Concentrate is BYOK-free. Point at a model and Concentrate owns the upstream credentials. Any provider keys you carried for AI Gateway’s BYOK mode can be retired after migrating, and like Vercel, there’s no per-token markup.

Troubleshooting

Bare slugs (gpt-5.5, 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), and reconcile the version suffix against GET /v1/models.
Concentrate keys start with sk-cn-v1-. If you are still sending a Vercel vck_... key (or a VERCEL_OIDC_TOKEN) as the Authorization bearer, you will see a 401. Verify the value in your dashboard and confirm there are no extra spaces or quotes.
Confirm the base URL is https://api.concentrate.ai/v1, not ai-gateway.vercel.sh. If the SDK is still pointed at Vercel it is logging against your AI Gateway dashboard, not Concentrate.
Vercel’s Anthropic surface uses https://ai-gateway.vercel.sh with no /v1; Concentrate uses https://api.concentrate.ai/v1 for every surface. If you copied the Vercel Anthropic base URL verbatim, you dropped the /v1 segment. Set the base URL to https://api.concentrate.ai/v1.
providerOptions.gateway (order, only, sort, models, providerTimeouts) has no effect on Concentrate. Express fallbacks via routing.model.fallbacks / routing.provider.fallbacks body params, or use model: "auto" with a routing strategy.
Concentrate uses provider-native prompt caching, currently supported on Anthropic and AWS Bedrock. There is no gateway-stored cache, so Vercel’s caching: 'auto' auto-breakpoints become provider-native caching. Caches are seeded per API key by default; pass prompt_cache_key in the request body if you want to set the seed explicitly.
Confirm the base URL is https://api.concentrate.ai/v1 (no per-surface variant like the /v1-less Anthropic base). Test the connection manually:
curl https://api.concentrate.ai/v1/responses/health

Next Steps

API Reference

Explore the full API capabilities

Available Models

Browse all supported models

Auto Routing

Optimize model selection automatically

Get Support

Contact our support team

Feedback

If you hit anything that didn’t translate cleanly (especially around providerOptions.gateway, BYOK, service tiers, app attribution, or the Anthropic base-URL difference), email support@concentrate.ai. The capability gaps called out above are tracked, and migration friction reports directly shape what we ship next.