Skip to main content
# Before
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.portkey.ai/v1",
    api_key=os.environ["OPENAI_API_KEY"],
    default_headers={
        "x-portkey-api-key": os.environ["PORTKEY_API_KEY"],
        "x-portkey-provider": "openai",
    },
)

# After
from openai import OpenAI
import os

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

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 Portkey integration

This guide assumes you are calling Portkey from the OpenAI SDK, the portkey-ai SDK, fetch, requests, or another HTTP client (in BYOK or Config-driven mode).

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 Portkey usage, strips x-portkey-* headers, decomposes Configs, maps model slugs, and generates a verification script. Drop the skill into your ~/.claude/skills/ directory:
mkdir -p ~/.claude/skills/migrate-portkey && \
  curl -fsSL https://concentrate.ai/scripts/migrate-portkey.md \
  -o ~/.claude/skills/migrate-portkey/SKILL.md
Then start a Claude Code session in your project and ask it to “migrate from Portkey to Concentrate” or run /migrate-portkey. Claude will load the skill and run the steps.

Step 1: Update Your Environment Variables

Replace your Portkey key and any upstream provider keys with a single Concentrate key:
# Before (BYOK mode)
export PORTKEY_API_KEY="pk-..."
export OPENAI_API_KEY="sk-..."
export BASE_URL="https://api.portkey.ai/v1"

# After
export CONCENTRATE_API_KEY="sk-cn-v1-..."
export BASE_URL="https://api.concentrate.ai/v1"
You no longer need OPENAI_API_KEY, ANTHROPIC_API_KEY, AWS credentials, Azure deployment IDs, or any other upstream provider key. Concentrate owns those credentials. Comment them out (don’t delete) until you’ve verified the migration end-to-end, then remove them.

Step 2: Update Your Client

The two big changes are the base URL and stripping every x-portkey-* header. If you were using the portkey-ai SDK, swap to the OpenAI SDK pointed at Concentrate. Concentrate does not ship a dedicated SDK because the OpenAI-compatible shape covers every endpoint.
# Before (Portkey with portkey-ai SDK)
from portkey_ai import Portkey

client = Portkey(
    api_key=os.environ["PORTKEY_API_KEY"],
    virtual_key="openai-prod",
    trace_id="req_42",
    metadata={"_user": "user_42", "feature": "summarizer"},
)

# 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)

Step 3: Remove x-portkey-* Headers

None of Portkey’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.
Portkey headerConcentrate replacement
x-portkey-api-keyStandard Authorization: Bearer sk-cn-v1-...
x-portkey-provider, x-portkey-virtual-keyDrop. Provider is encoded in the model slug (provider/model-id); credentials are managed by Concentrate
x-portkey-configDrop. See Step 4 for per-feature mapping
x-portkey-trace-idOptional X-Request-Id for correlation. Concentrate returns its own request id on the response
x-portkey-metadataDrop. Use per-user, per-team, or per-org keys; analytics roll up by key automatically
x-portkey-cache-force-refreshNo equivalent. Caching is provider-native, not gateway-stored
x-portkey-cache-namespaceprompt_cache_key body param
x-portkey-request-timeoutSet via your HTTP client (e.g. OpenAI SDK timeout)
x-portkey-forward-headers, x-portkey-sensitive-headersNot applicable. No BYOK passthrough
x-portkey-custom-hostNot supported. Self-hosted models stay on direct calls
x-portkey-azure-*Drop. Request azure/<model-id>
x-portkey-vertex-*Drop. Request ai-studio/<model-id> or the appropriate Vertex-backed slug
x-portkey-aws-*Drop. Request bedrock/<model-id>
If your code uses the portkey-ai SDK, the snake_case (Python) or camelCase (Node) parameters map to the same headers above:
portkey-ai parameterHeader it setsConcentrate replacement
api_key / apiKeyx-portkey-api-keyOpenAI SDK api_key / apiKey with your sk-cn-v1- key
virtual_key / virtualKeyx-portkey-virtual-keyDrop. Managed credentials
configx-portkey-configDrop. Express settings as body params
providerx-portkey-providerDrop. Model slug carries this
trace_id / traceIDx-portkey-trace-idDrop or send X-Request-Id
metadatax-portkey-metadataDrop. Use per-key/team/org rollups
cache_force_refresh / cacheForceRefreshx-portkey-cache-force-refreshDrop
cache_namespace / cacheNamespacex-portkey-cache-namespaceprompt_cache_key body param
custom_host / customHostx-portkey-custom-hostNot supported
forward_headers / forwardHeadersx-portkey-forward-headersNot supported
Portkey echoes a handful of headers back on every response. If your code reads or logs them, here’s the mapping:
Portkey response headerConcentrate equivalent
x-portkey-trace-idX-Request-Id (surfaced in dashboard logs)
x-portkey-cache-statusRead usage.prompt_tokens_details.cached_tokens in the response body (where supported)
x-portkey-provider, x-portkey-last-used-option-indexNo header. Resolved provider is recorded per request in the dashboard
Rate-limit headersStandard X-RateLimit-* headers. See Errors for 429 semantics

Step 4: Decompose Your Portkey Config

Portkey’s x-portkey-config bundles caching, fallbacks, load balancing, retries, conditional routing, and timeouts into a single saved or inline object. Concentrate does not have a Config 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.
Portkey config keyConcentrate equivalent
strategy: { mode: "fallback" } + targetsrouting.model.fallbacks or routing.provider.fallbacks, or model: "auto"
strategy: { mode: "loadbalance" } + weighted targetsmodel: "auto" with routing.model.sort across eligible providers
strategy: { mode: "conditional" } (route by metadata)Capability-driven only. Issue different keys per condition and pick in application code
cache: { mode: "simple" | "semantic", max_age }Provider-native prompt caching. No semantic cache
retry: { attempts, on_status_codes }Automatic failover on any provider error across your fallback chain
request_timeoutSet via your HTTP client
override_paramsPass directly in the request body
virtual_key inside a targetDrop. Managed credentials
custom_host inside a targetNot supported
guardrailsGuardrails & Redaction
Concentrate has conditional routing, but it conditions on request capabilities (feature support, ZDR flag, per-feature uptime, cache affinity), not on request attributes (metadata, headers, user cohorts). If your Portkey Config routes on _environment, _user, or custom metadata, the migration path is to issue separate keys per condition and pick the key in application code.

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.
If you were on Portkey with model strings like gpt-4o or claude-sonnet-4-6 and provider selection via x-portkey-provider or a Virtual Key, drop the header and let the model slug carry provider intent. Most Portkey model strings work as-is once you remove the provider header. One thing to know about the slashed form: the prefix is the provider that serves the request, not the model’s author. Portkey customers steering through x-portkey-provider: bedrock (or a Bedrock Virtual Key) with model: "claude-sonnet-4-6" should switch to model: "bedrock/claude-haiku-4-5" (or whichever slug GET /v1/models returns). For most popular names the two are the same string (openai, anthropic, mistral), but 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:
PortkeyConcentrate AI
model: "auto" inside a Config strategymodel: "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 Portkey.
Portkey dashboard surfaceConcentrate equivalent
Logs (full request/response)Per-request logs at concentrate.ai
Traces (trace_id-grouped)previous_response_id on the Responses API links related requests into a stateful tree
Metadata filters (_user, _environment, custom keys)Per-user / team / organization keys. Analytics roll up by whichever key, team, or org the request was made with
Feedback API (thumbs up/down)No equivalent today
Analytics (cost, latency, tokens, cache hit rate)Org / team / developer / key spend and latency rollups
Rate Limits / Usage Limits PoliciesPer-key rate and spend limits in the dashboard
Audit LogsAvailable in the dashboard
Log ExportsAvailable via the dashboard

Exporting your Portkey history

Portkey’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, Portkey exposes Log Exports via their Admin API; pull your history out before deprovisioning your Portkey workspace.

Step 7: Migrate Admin and Governance Surface

Portkey’s Admin API (Workspaces, Virtual Keys, Configs, Prompts, Policies, SCIM mappings) maps roughly to Concentrate’s organization/team/key hierarchy plus dashboard-managed settings rather than a separate API surface.
Portkey Admin conceptConcentrate equivalent
WorkspaceTeam (within an organization)
Virtual Key / Provider IntegrationNot exposed. Managed credentials
ConfigBody params per request
API KeyAPI Key (per developer, per team, or per org)
Rate Limits / Usage Limits PolicyPer-key rate and spend limits
User / User Invite / Workspace MemberOrganization and team members in the dashboard
SCIM Workspace MappingsAvailable for enterprise plans. Contact support@concentrate.ai
Audit LogsAvailable in the dashboard
Prompts / Partials / Labels / CollectionsNo equivalent today
GuardrailsGuardrails & Redaction
Secret ReferencesNot applicable. Concentrate owns provider credentials

Step 8 (Optional): Adopt the Responses API

For new code, we recommend the native Responses API. 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 replaces Portkey’s trace_id-grouped sessions with 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

Portkey offers two integration shapes. The migration path differs for each:
  • BYOK mode. Point the OpenAI SDK at https://api.portkey.ai/v1, set x-portkey-api-key, and pass your own provider key via Authorization (with x-portkey-provider: openai) or a stored Virtual Key (x-portkey-virtual-key, or x-portkey-provider: @provider-slug). Migrating here gets you off provider keys entirely.
  • Config-driven mode. Use x-portkey-config to reference a saved or inline JSON config covering caching, fallbacks, load balancing, retries, and timeouts. Decompose the Config: most settings become Concentrate body params or are handled automatically. See Step 4.
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 metadata tagging 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 Config object to author or version.
model: "auto" accepts an explicit optimization target via routing.model.sort: cost, latency, or performance (default). See Auto Routing.
Alongside OpenAI Chat Completions, Concentrate exposes a first-class Responses API and an Anthropic-compatible Messages API.
Concentrate is BYOK-free. There are no Virtual Keys, Provider Integrations, or Model Catalog to configure. Point at a model and Concentrate owns the upstream credentials. Any OPENAI_API_KEY, ANTHROPIC_API_KEY, AWS keys, or Azure deployment IDs you carried alongside Portkey can be retired after migrating.

Troubleshooting

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 for the authoritative list.
Concentrate keys start with sk-cn-v1-. If you are still sending a Portkey x-portkey-api-key value (or an upstream provider key from BYOK mode) 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 api.portkey.ai. If the SDK is still pointed at Portkey it is logging against your Portkey workspace, not Concentrate.
Concentrate does not accept arbitrary per-request metadata. Reserved Portkey keys like _user, _environment, and _organisation map to the key/team/org hierarchy. Issue a separate key per user or environment and analytics roll up automatically. Custom metadata keys have no equivalent today.
x-portkey-config is a no-op on Concentrate. Express fallbacks via routing.model.fallbacks / routing.provider.fallbacks body params, or use model: "auto" with a routing strategy. Conditional routing by metadata has no direct equivalent. Handle in application code.
Concentrate uses provider-native prompt caching, currently supported on Anthropic and AWS Bedrock. There is no semantic cache and no gateway-stored cache, so Portkey’s simple and semantic cache modes do not carry over. Caches are seeded per API key by default; pass prompt_cache_key in the request body if you want to set the seed explicitly (the analog of x-portkey-cache-namespace).
Confirm the base URL is https://api.concentrate.ai/v1 (no /api segment, no per-provider subdomain). 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 Configs, Prompt templates, conditional routing, custom hosts, or per-request metadata), email support@concentrate.ai. The capability gaps called out above are tracked, and migration friction reports directly shape what we ship next.