DEV Community

Cover image for Migrate from OpenAI & Claude API to Amazon Bedrock (2026 Guide)
Rahul Pandya
Rahul Pandya

Posted on

Migrate from OpenAI & Claude API to Amazon Bedrock (2026 Guide)

Introduction

If your app calls the OpenAI API or the Claude API directly, you've probably heard this question at work: "Can we run this through AWS instead?"

It usually comes from security or from finance. Security wants IAM instead of API keys sitting in environment variables. Finance wants one bill, and wants AI spend to count toward the AWS commitment they already signed.

In 2026 this is much easier than it used to be. OpenAI models (GPT-5.5, GPT-5.6 and GPT-6 Astra) are generally available on Amazon Bedrock. Claude models run on Bedrock through the same Messages API you already use with Anthropic. For many apps, the code change is only a few lines.

But "a few lines" hides the details that break production: model IDs, regions, endpoints, authentication, and features that don't exist on Bedrock yet. This guide covers both migrations, OpenAI API to Amazon Bedrock and Claude API to Amazon Bedrock, including the parts that tripped me up.

Why move to Amazon Bedrock (and when not to)

You don't need to migrate just because you can. These are the real reasons teams do it:

  • IAM instead of shared API keys. Access is controlled with IAM roles and policies, like the rest of your AWS resources.
  • Private networking. Calls can go through VPC and PrivateLink, so traffic stays on the AWS network.
  • Audit logs. Calls are logged in CloudTrail, so "who used which model, and when?" has an answer.
  • One bill. AI spend appears on your AWS bill and can count toward your existing AWS commitments.
  • Data protection. Your prompts and responses are not used to train models and are not shared with the model providers.
  • Same price for GPT-5.5. AWS says Bedrock matches OpenAI's own per-token rates, with no extra fee.

And the honest reasons to wait:

  • Some features of the direct APIs are not available on Bedrock yet. The Claude section lists them.
  • Region availability is limited, especially for OpenAI models.
  • New features usually reach the direct APIs first.

For a solo side project, the direct API is probably fine. For a company already running on AWS, Bedrock makes a lot of sense.

The confusing part: bedrock-runtime vs bedrock-mantle

This is what I wish someone had explained to me first. Amazon Bedrock now has two inference endpoints, and which one you use changes your code.

bedrock-runtime bedrock-mantle
Host bedrock-runtime.{region}.amazonaws.com bedrock-mantle.{region}.api.aws
APIs InvokeModel, Converse, plus OpenAI-compatible and Messages API paths OpenAI Responses API, OpenAI Chat Completions API, Anthropic Messages API
Best for Existing Bedrock apps, Guardrails, Knowledge Bases, Agents Moving code from the OpenAI or Anthropic SDKs with minimal changes

bedrock-mantle is Bedrock's newer inference engine. It speaks the same "language" as OpenAI's and Anthropic's own APIs, which is why migrating is so easy now. You mostly change three things: the base URL, the credentials, and the model ID.

flowchart LR
    A[Your app] --> R[bedrock-runtime]
    A --> M[bedrock-mantle]
    R --> R1[InvokeModel / Converse]
    R --> R2[Guardrails / Knowledge Bases]
    M --> M1[OpenAI Responses API]
    M --> M2[Anthropic Messages API]

One warning: Agents, Knowledge Bases, Guardrails and fine-tuning are managed from the classic Bedrock console, on the bedrock-runtime side. If your app depends on them, check the docs before choosing mantle.

Before you start

You need four things:

  1. An AWS account with Bedrock model access for the models you plan to use.
  2. The right region. Not every model is in every region, so check the model card first.
  3. A way to authenticate. Either normal AWS credentials (IAM role, SSO and so on) or a Bedrock API key.
  4. Up-to-date SDKs:
pip install -U openai "anthropic[bedrock]" aws-bedrock-token-generator
Enter fullscreen mode Exit fullscreen mode

AWS also launched a new Bedrock console built for the mantle endpoint. It compares up to three models side by side, groups work into projects, and generates code snippets already filled in with your region, model ID and endpoint. Open it before writing any code.

Part 1: Migrating from the OpenAI API to Amazon Bedrock

Step 1: Pick your model and region

OpenAI model IDs on Bedrock carry an openai. prefix. At the time of writing, these are the main ones:

Model Bedrock model ID Good for
GPT-6 Astra openai.gpt-6-astra The most capable model; on mantle, us-west-2 (Oregon) only
GPT-5.6 Sol openai.gpt-5.6-sol Hard reasoning and complex coding
GPT-5.6 Terra openai.gpt-5.6-terra Balanced, everyday production work
GPT-5.6 Luna openai.gpt-5.6-luna Fast, low-cost, high-volume tasks
GPT-5.5 openai.gpt-5.5 The first GA model, launched in US East (Ohio)
GPT-5.4 openai.gpt-5.4 Strong price-performance

Region warning: OpenAI models on Bedrock are mostly in US regions right now. If you're in India like me, or anywhere with data residency rules, check the model card before promising anything to your team. This limits you more than anything else in the migration.

Step 2: Create a Bedrock API key

The OpenAI SDK expects a bearer token, so the simplest path is a Bedrock API key. For testing, create one in the Bedrock console. For production, don't use long-term keys; Step 4 shows how to generate short-term tokens instead.

Step 3: Change your code

A typical call to the OpenAI API looks like this:

# Before: direct OpenAI API
from openai import OpenAI

client = OpenAI()  # reads OPENAI_API_KEY

response = client.responses.create(
    model="gpt-5.5",
    input="Explain what an AWS NAT Gateway costs in simple words.",
)

print(response.output_text)
Enter fullscreen mode Exit fullscreen mode

The same call through Amazon Bedrock:

# After: Amazon Bedrock
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://bedrock-mantle.us-east-2.api.aws/openai/v1",
    api_key=os.environ["BEDROCK_API_KEY"],
)

response = client.responses.create(
    model="openai.gpt-5.5",
    input="Explain what an AWS NAT Gateway costs in simple words.",
)

print(response.output_text)
Enter fullscreen mode Exit fullscreen mode

Three things changed:

  1. base_url points to the Bedrock mantle endpoint, with the region inside the URL.
  2. api_key is your Bedrock API key, not your OpenAI key.
  3. model gets the openai. prefix.

You can even switch without touching the client code, using environment variables:

export OPENAI_BASE_URL="https://bedrock-mantle.us-east-2.api.aws/openai/v1"
export OPENAI_API_KEY="<your-bedrock-api-key>"
Enter fullscreen mode Exit fullscreen mode

Step 4: Use short-term tokens in production

A long-term API key is the same problem you were trying to escape. In production, generate a short-lived token from your IAM role instead:

from aws_bedrock_token_generator import provide_token
from openai import OpenAI

region = "us-east-2"
token = provide_token(region=region)  # uses your normal AWS credential chain

client = OpenAI(
    base_url=f"https://bedrock-mantle.{region}.api.aws/openai/v1",
    api_key=token,
)
Enter fullscreen mode Exit fullscreen mode

Short-term tokens last 12 hours at most. In a long-running service, refresh the token before it expires instead of creating it once at startup.

OpenAI gotchas to watch for

  • The Responses API is the safe choice. GPT-5.5 and GPT-5.4 launched on Bedrock with Responses API support only. Some newer models also support Chat Completions, but check the model card. If your code uses chat.completions.create, test it before assuming it works.
  • The endpoint and model ID must match. On bedrock-mantle you use the plain ID (openai.gpt-6-astra). On bedrock-runtime, some models need an inference profile ID such as us.openai.gpt-6-astra or global.openai.gpt-6-astra. Mixing them up produces confusing errors.
  • Global inference can process data in other regions. If you have residency requirements, use in-region or geographic (us.) routing, not global..
  • Reasoning effort changes latency a lot. AWS recommends setting reasoning effort explicitly rather than relying on defaults.

Part 2: Migrating from the Claude API to Amazon Bedrock

The Claude migration is the easier of the two. Claude on Bedrock uses the same Messages API request format as Anthropic's own API, and Anthropic's SDK has a dedicated Bedrock client.

Step 1: Pick your model

Claude model IDs on Bedrock carry an anthropic. prefix:

Model Bedrock model ID
Claude Opus 5.5 anthropic.claude-opus-5-5
Claude Sonnet 5 anthropic.claude-sonnet-5
Claude Fable 5.1 anthropic.claude-fable-5-1
Claude Haiku 4.5 anthropic.claude-haiku-4-5

Some models are open to every Bedrock customer, while others have their own access requirements. Check model access in your console.

Step 2: Change your code

A typical call to the Claude API:

# Before: direct Claude API
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_API_KEY

message = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Summarize this CloudWatch alarm for me."}],
)

print(message.content[0].text)
Enter fullscreen mode Exit fullscreen mode

The same call through Amazon Bedrock:

# After: Amazon Bedrock
from anthropic import AnthropicBedrockMantle

client = AnthropicBedrockMantle(aws_region="us-east-1")

message = client.messages.create(
    model="anthropic.claude-sonnet-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Summarize this CloudWatch alarm for me."}],
)

print(next(block.text for block in message.content if block.type == "text"))
Enter fullscreen mode Exit fullscreen mode

The best part: AnthropicBedrockMantle uses the normal AWS credential chain. Environment variables, SSO, assumed roles, ECS task roles and EC2 instance roles all work. You don't need an API key at all.

If you prefer the standard Anthropic client, set base_url to https://bedrock-mantle.{region}.api.aws/anthropic and pass a Bedrock bearer token as api_key. That path supports bearer tokens only, not IAM request signing.

One note: AWS documentation says the Messages API works on both bedrock-mantle and bedrock-runtime, and currently recommends bedrock-runtime for new applications. Check the latest AWS docs to see which fits your setup, especially if you need Guardrails.

Step 3: Understand global vs regional pricing

This choice affects your bill directly:

  • Global endpoint: Bedrock routes each request to any available region. There is no price premium.
  • Regional endpoint: requests stay in the region you choose, for data residency. This costs 10% more than global.

Some regions only offer global routing for Claude. Mumbai (ap-south-1), for example, is listed as global only. If your company needs data processed strictly in India, raise it early.

Claude features not available on Bedrock (yet)

This is where most migrations actually break. Features that run inside the model work: the Messages API, prompt caching, extended thinking, tool use and citations. Features that depend on Anthropic's own infrastructure are missing. According to Anthropic's documentation, these are not supported on Bedrock right now:

  • Structured outputs
  • The Files API, and URL sources for images and documents
  • Server-side tools (web search, web fetch, code execution)
  • The Message Batches API
  • The MCP connector and Agent Skills
  • Claude Managed Agents

Before migrating, search your codebase for these. If you run nightly jobs on the Batches API, or rely on built-in web search, plan a workaround first, such as your own search tool called through tool use.

Security setup that makes the migration worth it

Moving to Bedrock and then sharing one long-term API key everywhere misses the point. This is the minimum I'd set up.

1. A least-privilege IAM policy

Give each app permission to call only the models it needs:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "bedrock-mantle:CreateInference",
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Replace "*" with the ARNs of the models your app actually uses. Check the Bedrock docs for the exact ARN format on your endpoint.

2. Block long-term API keys

Attach a policy that denies bedrock:CallWithBearerToken unless the token is short-term, using the bedrock:BearerTokenType condition key. This stops anyone from creating a long-term key and pasting it into a config file "just for testing".

3. Turn on logging

Claude on Bedrock sends logs to both CloudWatch and CloudTrail. Keep at least 30 days of logs. The first time your bill spikes, you'll be glad you did.

4. Track cost per project

On the mantle endpoint you can group requests into projects; for Claude calls, that's the anthropic-workspace header. You get per-project cost tracking, access control and usage insights. If you've read my FinOps agent post, you know how much I care about knowing where every dollar goes.

Common errors and how to fix them

Error Likely cause Fix
404 or "model not found" Model ID doesn't match the endpoint, such as a us. prefix on mantle for Claude Use the plain model ID on mantle
Works in one region, fails in another The region is part of the URL, and the model isn't in the new region Change the base URL and confirm the model's regions
Requests fail after a few hours Short-term token expired Refresh the token before it expires
Timeouts on long responses (bedrock-runtime with boto3) AWS SDK clients time out after 1 minute by default Raise read_timeout in your botocore config
Access denied Model access not enabled, or IAM policy missing the model Enable access and update the policy

Migration checklist

Before you switch production traffic:

[ ] The model is available in your target region
[ ] Codebase searched for unsupported features (Batches, Files API, server tools, structured outputs)
[ ] Model IDs updated with the openai. or anthropic. prefix
[ ] Short-term tokens or IAM roles in place, with no long-term keys
[ ] Least-privilege IAM policy attached
[ ] CloudTrail and CloudWatch logging turned on
[ ] Global vs regional routing decided (cost vs data residency)
[ ] Same test prompts run on the old and new setup, and outputs compared
[ ] Rollback plan ready: keep the old API key working for a week or two

So, should you migrate?

Your situation My take
Already on AWS, and security or compliance matters Yes, migrate
You want AI spend on your AWS bill Yes
You depend on Batches, the Files API or built-in web search Wait, or plan workarounds first
You need OpenAI models outside US regions Check availability first
Solo project with no AWS infrastructure The direct API is fine

What surprised me most was how small the code change is now. The real work isn't the code; it's checking regions, features and IAM. Get those right, and the migration itself takes an afternoon.


Have you moved to Bedrock, or are you stuck on something? Tell me in the comments. I read every one, and if enough people hit the same problem, I'll write a follow-up.

If this helped, you might also like my ECS vs EKS comparison and my AWS FinOps agent build.

Sources

Top comments (0)