diff --git a/docs.json b/docs.json
index 13b371e9..4caf1e4e 100644
--- a/docs.json
+++ b/docs.json
@@ -416,6 +416,15 @@
"integrations/llms/bedrock/bedrock-knowledgebase"
]
},
+ {
+ "group": "Claude Platform on AWS",
+ "pages": [
+ "integrations/llms/claude-platform-aws/claude-platform-aws",
+ "integrations/llms/claude-platform-aws/setup-assumed-role",
+ "integrations/llms/claude-platform-aws/files",
+ "integrations/llms/claude-platform-aws/batches"
+ ]
+ },
"integrations/llms/bedrock-mantle",
"integrations/llms/aws-sagemaker",
"integrations/llms/ollama",
diff --git a/integrations/llms/claude-platform-aws/batches.mdx b/integrations/llms/claude-platform-aws/batches.mdx
new file mode 100644
index 00000000..588dac24
--- /dev/null
+++ b/integrations/llms/claude-platform-aws/batches.mdx
@@ -0,0 +1,479 @@
+---
+title: Batches
+description: Run asynchronous batch jobs on Claude Platform on AWS through Portkey's unified /v1/batches API
+---
+
+
+Self-hosted deployments require **Enterprise Gateway v2.6.1+**.
+
+
+Portkey exposes Anthropic's [Message Batches API](https://docs.anthropic.com/en/docs/build-with-claude/batch-processing) for Claude Platform on AWS through the unified OpenAI-compatible `/v1/batches` endpoints. All five batch operations -- create, retrieve, cancel, list, and get output -- are supported, enabling large asynchronous Claude jobs at 50% lower cost.
+
+Use batches for offline workloads like nightly evals, bulk summarization, or dataset grading.
+
+## Supported Endpoints
+
+| Gateway Endpoint | Anthropic Upstream | Operation |
+| ---------------------------------------- | -------------------------------------------------- | ---------------- |
+| `POST /v1/batches` | `POST /v1/messages/batches` | Create a batch |
+| `GET /v1/batches/{batch_id}` | `GET /v1/messages/batches/{batch_id}` | Retrieve a batch |
+| `POST /v1/batches/{batch_id}/cancel` | `POST /v1/messages/batches/{batch_id}/cancel` | Cancel a batch |
+| `GET /v1/batches` | `GET /v1/messages/batches` | List batches |
+| `GET /v1/batches/{batch_id}/output` | Streams from `results_url` | Get batch output |
+
+## Request Format
+
+
+Unlike OpenAI's file-based batches, Anthropic batch creation uses an inline `requests[]` array -- there is no `input_file_id`. Each item carries a `custom_id` and a `params` object containing the standard Messages API payload.
+
+
+```json
+{
+ "requests": [
+ {
+ "custom_id": "req-1",
+ "params": {
+ "model": "claude-sonnet-4-6",
+ "max_tokens": 1024,
+ "messages": [
+ { "role": "user", "content": "Hello" }
+ ]
+ }
+ }
+ ]
+}
+```
+
+## Create a Batch
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+batch = portkey.post(
+ "/batches",
+ requests=[
+ {
+ "custom_id": "req-1",
+ "params": {
+ "model": "claude-sonnet-4-6",
+ "max_tokens": 1024,
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+ }
+ ]
+)
+
+print(batch)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const batch = await portkey.post('/batches', {
+ requests: [
+ {
+ custom_id: "req-1",
+ params: {
+ model: "claude-sonnet-4-6",
+ max_tokens: 1024,
+ messages: [{ role: "user", content: "Hello" }]
+ }
+ }
+ ]
+});
+
+console.log(batch);
+```
+
+
+```sh
+curl -X POST https://api.portkey.ai/v1/batches \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "requests": [
+ {
+ "custom_id": "req-1",
+ "params": {
+ "model": "claude-sonnet-4-6",
+ "max_tokens": 1024,
+ "messages": [
+ { "role": "user", "content": "Hello" }
+ ]
+ }
+ }
+ ]
+ }'
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+batch = client.post(
+ "/batches",
+ body={
+ "requests": [
+ {
+ "custom_id": "req-1",
+ "params": {
+ "model": "claude-sonnet-4-6",
+ "max_tokens": 1024,
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+ }
+ ]
+ },
+ cast_to=object
+)
+
+print(batch)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const batch = await client.post('/batches', {
+ body: {
+ requests: [
+ {
+ custom_id: "req-1",
+ params: {
+ model: "claude-sonnet-4-6",
+ max_tokens: 1024,
+ messages: [{ role: "user", content: "Hello" }]
+ }
+ }
+ ]
+ }
+});
+
+console.log(batch);
+```
+
+
+
+## Retrieve a Batch
+
+Returns the OpenAI-compatible Batch object. Once processing completes, the response includes `results_url` from Anthropic.
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+batch = portkey.batches.retrieve(batch_id="")
+
+print(batch)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const batch = await portkey.batches.retrieve("");
+
+console.log(batch);
+```
+
+
+```sh
+curl https://api.portkey.ai/v1/batches/ \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider"
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+batch = client.batches.retrieve("")
+
+print(batch)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const batch = await client.batches.retrieve("");
+
+console.log(batch);
+```
+
+
+
+## List Batches
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+batches = portkey.batches.list()
+
+print(batches)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const batches = await portkey.batches.list();
+
+console.log(batches);
+```
+
+
+```sh
+curl https://api.portkey.ai/v1/batches \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider"
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+batches = client.batches.list()
+
+print(batches)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const batches = await client.batches.list();
+
+console.log(batches);
+```
+
+
+
+## Cancel a Batch
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+cancelled = portkey.batches.cancel(batch_id="")
+
+print(cancelled)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const cancelled = await portkey.batches.cancel("");
+
+console.log(cancelled);
+```
+
+
+```sh
+curl -X POST https://api.portkey.ai/v1/batches//cancel \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider"
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+cancelled = client.batches.cancel("")
+
+print(cancelled)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const cancelled = await client.batches.cancel("");
+
+console.log(cancelled);
+```
+
+
+
+## Get Batch Output
+
+
+Before streaming results, Portkey retrieves the batch metadata and verifies that `processing_status === 'ended'`. It then fetches from Anthropic's `results_url`, generating fresh SigV4-signed headers for the output URL. The response body is streamed back as JSONL in Anthropic's native format.
+
+
+
+
+```sh
+curl https://api.portkey.ai/v1/batches//output \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider"
+```
+
+
+
+A typical output line:
+
+```json
+{
+ "custom_id": "req-1",
+ "result": {
+ "type": "succeeded",
+ "message": {
+ "id": "msg_01XYZ...",
+ "type": "message",
+ "role": "assistant",
+ "content": [{ "type": "text", "text": "Hello! How can I help?" }],
+ "model": "claude-sonnet-4-6",
+ "stop_reason": "end_turn",
+ "usage": { "input_tokens": 10, "output_tokens": 12 }
+ }
+ }
+}
+```
+
+## Response Format
+
+`createBatch`, `retrieveBatch`, `cancelBatch`, and `listBatches` return the OpenAI Batch shape so existing OpenAI tooling works unchanged:
+
+- `object: "batch"` and `endpoint: "/v1/batches"` on every batch record
+- `status` values normalized to OpenAI-compatible strings (`validating`, `in_progress`, `finalizing`, `completed`, `failed`, `cancelling`, `cancelled`, `expired`)
+- Timestamps converted from Anthropic's ISO 8601 to Unix epoch seconds
+- Request counts mapped: `succeeded → completed`, `errored → failed`
+- `retrieveBatch` surfaces `results_url` from the Anthropic response when the batch has finished processing
+
+`getBatchOutput` streams the raw Anthropic-native JSONL for full Claude response fidelity (content blocks, tool use, stop reasons, usage).
+
+## See Also
+
+- [Unified Batch Guide](/product/ai-gateway/batches)
+- [Claude Platform on AWS integration overview](/integrations/llms/claude-platform-aws/claude-platform-aws)
+- [Anthropic Message Batches API reference](https://docs.anthropic.com/en/docs/build-with-claude/batch-processing)
diff --git a/integrations/llms/claude-platform-aws/claude-platform-aws.mdx b/integrations/llms/claude-platform-aws/claude-platform-aws.mdx
new file mode 100644
index 00000000..3322ecfc
--- /dev/null
+++ b/integrations/llms/claude-platform-aws/claude-platform-aws.mdx
@@ -0,0 +1,524 @@
+---
+title: "Claude Platform on AWS"
+description: "Integrate Claude models via Claude Platform on AWS with Portkey's AI Gateway"
+---
+
+[Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws) is Anthropic's managed Claude offering delivered through AWS. It uses the same Anthropic Messages API with AWS SigV4 authentication and billing through AWS Marketplace.
+
+Portkey provider slug: `claude-platform-aws`
+
+
+
+ Opus, Sonnet, and Haiku with plain model IDs
+
+
+ Messages, batches, files, token counting
+
+
+ Access Key, Assumed Role, and Service Role
+
+
+
+## Quick Start
+
+
+```python Python icon="python"
+from portkey_ai import Portkey
+
+# 1. Install: pip install portkey-ai
+# 2. Add @claude-platform-aws provider in Model Catalog
+# 3. Use it:
+
+portkey = Portkey(api_key="PORTKEY_API_KEY")
+
+response = portkey.chat.completions.create(
+ model="@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages=[{"role": "user", "content": "What is Portkey's AI Gateway?"}],
+ max_tokens=250
+)
+
+print(response.choices[0].message.content)
+```
+
+```js Javascript icon="square-js"
+import Portkey from 'portkey-ai'
+
+// 1. Install: npm install portkey-ai
+// 2. Add @claude-platform-aws provider in Model Catalog
+// 3. Use it:
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY"
+})
+
+const response = await portkey.chat.completions.create({
+ model: "@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages: [{ role: "user", content: "What is Portkey's AI Gateway?" }],
+ max_tokens: 250
+})
+
+console.log(response.choices[0].message.content)
+```
+
+```python OpenAI Py icon="python"
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL
+
+# 1. Install: pip install openai portkey-ai
+# 2. Add @claude-platform-aws provider in Model Catalog
+# 3. Use it:
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL
+)
+
+response = client.chat.completions.create(
+ model="@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages=[{"role": "user", "content": "What is Portkey's AI Gateway?"}],
+ max_tokens=250
+)
+
+print(response.choices[0].message.content)
+```
+
+```js OpenAI JS icon="square-js"
+import OpenAI from "openai"
+import { PORTKEY_GATEWAY_URL } from "portkey-ai"
+
+// 1. Install: npm install openai portkey-ai
+// 2. Add @claude-platform-aws provider in Model Catalog
+// 3. Use it:
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL
+})
+
+const response = await client.chat.completions.create({
+ model: "@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages: [{ role: "user", content: "What is Portkey's AI Gateway?" }],
+ max_tokens: 250
+})
+
+console.log(response.choices[0].message.content)
+```
+
+```sh cURL icon="square-terminal"
+curl https://api.portkey.ai/v1/chat/completions \
+ -H "Content-Type: application/json" \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -d '{
+ "model": "@claude-platform-aws-provider/claude-sonnet-4-6",
+ "messages": [
+ { "role": "user", "content": "What is Portkey's AI Gateway?" }
+ ],
+ "max_tokens": 250
+ }'
+```
+
+```python Anthropic Py
+import anthropic
+
+# 1. Install: pip install anthropic portkey-ai
+# 2. Add @claude-platform-aws provider in Model Catalog
+# 3. Use it:
+
+client = anthropic.Anthropic(
+ api_key="dummy",
+ default_headers={"x-portkey-api-key": "YOUR_PORTKEY_API_KEY"},
+ base_url="https://api.portkey.ai"
+)
+
+message = client.messages.create(
+ model="@claude-platform-aws-provider/claude-sonnet-4-6",
+ max_tokens=250,
+ messages=[{"role": "user", "content": "What is Portkey's AI Gateway?"}]
+)
+
+print(message.content)
+```
+
+```typescript Anthropic TS
+import Anthropic from '@anthropic-ai/sdk'
+
+// 1. Install: npm install @anthropic-ai/sdk portkey-ai
+// 2. Add @claude-platform-aws provider in Model Catalog
+// 3. Use it:
+
+const anthropic = new Anthropic({
+ apiKey: "YOUR_PORTKEY_API_KEY",
+ baseURL: "https://api.portkey.ai"
+})
+
+const msg = await anthropic.messages.create({
+ model: "@claude-platform-aws-provider/claude-sonnet-4-6",
+ max_tokens: 250,
+ messages: [{ role: "user", content: "What is Portkey's AI Gateway?" }]
+})
+
+console.log(msg)
+```
+
+
+- **`max_tokens` is required** -- always specify this parameter
+- **Model IDs** are identical to the first-party Anthropic API (e.g., `claude-sonnet-4-6`, `claude-opus-4-7`)
+
+## Prerequisites
+
+
+Enable outbound web identity federation on your AWS account before making any requests:
+
+```bash
+aws iam enable-outbound-web-identity-federation
+```
+
+Without this, all requests fail with `"Outbound web identity federation is disabled for your account"`.
+
+
+## Add Provider in Model Catalog
+
+1. Go to [**Model Catalog → Add Provider**](https://app.portkey.ai/model-catalog/providers)
+2. Select **Claude Platform on AWS**
+3. Choose an authentication mode and enter credentials
+
+| Auth Mode | Required Fields |
+|---|---|
+| **AWS Access Key** | `awsAccessKeyId`, `awsSecretAccessKey`, `awsRegion` |
+| **Assumed Role** | `awsRoleArn`, `awsExternalId` (optional), `awsRegion` |
+| **Service Role** (EKS/IRSA) | `awsRegion` |
+
+All auth modes accept an optional **Anthropic Workspace ID** (`anthropicAwsWorkspaceId`). Set this to scope requests to a specific workspace (format: `wrkspc_01AbCdEf23GhIj`).
+
+`awsRegion` determines the endpoint: `aws-external-anthropic.{region}.api.aws`
+
+
+ Step-by-step IAM role and trust policy configuration for assumed role auth
+
+
+## IAM Policy
+
+Claude Platform on AWS uses the `aws-external-anthropic` IAM namespace. Create a permission policy with the actions your workload needs:
+
+
+```json Inference Only
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Action": [
+ "aws-external-anthropic:CreateInference",
+ "aws-external-anthropic:CountTokens"
+ ],
+ "Resource": "arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj"
+ }]
+}
+```
+
+```json Inference + Batch + Files
+{
+ "Version": "2012-10-17",
+ "Statement": [{
+ "Effect": "Allow",
+ "Action": [
+ "aws-external-anthropic:CreateInference",
+ "aws-external-anthropic:CountTokens",
+ "aws-external-anthropic:CreateBatchInference",
+ "aws-external-anthropic:GetBatchInference",
+ "aws-external-anthropic:ListBatchInferences",
+ "aws-external-anthropic:CancelBatchInference",
+ "aws-external-anthropic:DeleteBatchInference",
+ "aws-external-anthropic:CreateFile",
+ "aws-external-anthropic:GetFile",
+ "aws-external-anthropic:ListFiles",
+ "aws-external-anthropic:DeleteFile"
+ ],
+ "Resource": "arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj"
+ }]
+}
+```
+
+
+AWS also provides managed policies for common use cases:
+
+| Managed Policy | Scope |
+|---|---|
+| `AnthropicFullAccess` | All `aws-external-anthropic:*` actions |
+| `AnthropicInferenceAccess` | Inference + read-only + batch |
+| `AnthropicReadOnlyAccess` | `Get*`, `List*`, `CallWithBearerToken` |
+
+## Basic Usage
+
+### Chat Completions
+
+
+```python Python icon="python"
+from portkey_ai import Portkey
+
+portkey = Portkey(api_key="PORTKEY_API_KEY")
+
+response = portkey.chat.completions.create(
+ model="@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages=[
+ {"role": "system", "content": "You are a helpful assistant."},
+ {"role": "user", "content": "Explain quantum computing in simple terms."}
+ ],
+ max_tokens=500
+)
+
+print(response.choices[0].message.content)
+```
+
+```js Javascript icon="square-js"
+import Portkey from 'portkey-ai'
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY"
+})
+
+const response = await portkey.chat.completions.create({
+ model: "@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages: [
+ { role: "system", content: "You are a helpful assistant." },
+ { role: "user", content: "Explain quantum computing in simple terms." }
+ ],
+ max_tokens: 500
+})
+
+console.log(response.choices[0].message.content)
+```
+
+
+### Streaming
+
+
+```python Python icon="python"
+response = portkey.chat.completions.create(
+ model="@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages=[{"role": "user", "content": "Tell me a story"}],
+ max_tokens=500,
+ stream=True
+)
+
+for chunk in response:
+ if chunk.choices[0].delta.content:
+ print(chunk.choices[0].delta.content, end="")
+```
+
+```js Javascript icon="square-js"
+const response = await portkey.chat.completions.create({
+ model: "@claude-platform-aws-provider/claude-sonnet-4-6",
+ messages: [{ role: "user", content: "Tell me a story" }],
+ max_tokens: 500,
+ stream: true
+})
+
+for await (const chunk of response) {
+ if (chunk.choices[0].delta.content) {
+ process.stdout.write(chunk.choices[0].delta.content)
+ }
+}
+```
+
+
+## Using the /messages Route
+
+Use Anthropic's native `/messages` endpoint through Portkey with full gateway features.
+
+### Using Anthropic's Native SDK
+
+
+```python Anthropic Py
+import anthropic
+
+client = anthropic.Anthropic(
+ api_key="dummy",
+ default_headers={"x-portkey-api-key": "YOUR_PORTKEY_API_KEY"},
+ base_url="https://api.portkey.ai"
+)
+
+message = client.messages.create(
+ model="@claude-platform-aws-provider/claude-sonnet-4-6",
+ max_tokens=250,
+ messages=[{"role": "user", "content": "Hello, Claude"}]
+)
+
+print(message.content)
+```
+
+```typescript Anthropic TS
+import Anthropic from '@anthropic-ai/sdk'
+
+const anthropic = new Anthropic({
+ apiKey: "YOUR_PORTKEY_API_KEY",
+ baseURL: "https://api.portkey.ai"
+})
+
+const msg = await anthropic.messages.create({
+ model: "@claude-platform-aws-provider/claude-sonnet-4-6",
+ max_tokens: 1024,
+ messages: [{ role: "user", content: "Hello, Claude" }]
+})
+
+console.log(msg)
+```
+
+
+### Using cURL
+
+```sh cURL icon="square-terminal"
+curl https://api.portkey.ai/v1/messages \
+ -H "Content-Type: application/json" \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: claude-platform-aws" \
+ -d '{
+ "model": "@claude-platform-aws-provider/claude-sonnet-4-6",
+ "max_tokens": 1024,
+ "messages": [
+ { "role": "user", "content": "Hello, Claude" }
+ ]
+ }'
+```
+
+
+All Portkey features (caching, observability, configs) work with the `/messages` route. Add `x-portkey-config`, `x-portkey-provider`, and other Portkey headers as needed.
+
+
+## Extended Thinking
+
+Models like `claude-opus-4-7` and `claude-sonnet-4-6` support [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking). Set `strict_open_ai_compliance=False` to use this feature:
+
+
+```python Python icon="python"
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ strict_open_ai_compliance=False
+)
+
+response = portkey.chat.completions.create(
+ model="@claude-platform-aws-provider/claude-opus-4-7",
+ max_tokens=16000,
+ thinking={"type": "enabled", "budget_tokens": 10000},
+ messages=[{
+ "role": "user",
+ "content": "Solve this step by step: If a train travels 120km in 2 hours, and another travels 200km in 3 hours, which is faster and by how much?"
+ }]
+)
+
+print(response)
+```
+
+```js Javascript icon="square-js"
+import Portkey from 'portkey-ai'
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ strictOpenAiCompliance: false
+})
+
+const response = await portkey.chat.completions.create({
+ model: "@claude-platform-aws-provider/claude-opus-4-7",
+ max_tokens: 16000,
+ thinking: { type: "enabled", budget_tokens: 10000 },
+ messages: [{
+ role: "user",
+ content: "Solve this step by step: If a train travels 120km in 2 hours, and another travels 200km in 3 hours, which is faster and by how much?"
+ }]
+})
+
+console.log(response)
+```
+
+
+
+The thinking response is returned in `response.choices[0].delta.content_blocks`, not `response.choices[0].message.content`.
+
+
+## Supported Models
+
+| Model | Model ID |
+|---|---|
+| Claude Opus 4.7 | `claude-opus-4-7` |
+| Claude Opus 4.6 | `claude-opus-4-6` |
+| Claude Sonnet 4.6 | `claude-sonnet-4-6` |
+| Claude Opus 4.5 | `claude-opus-4-5` |
+| Claude Sonnet 4.5 | `claude-sonnet-4-5` |
+| Claude Haiku 4.5 | `claude-haiku-4-5` |
+
+Model IDs are identical to the first-party Anthropic API -- no Bedrock-style `anthropic.claude-*` prefixes.
+
+Dated aliases (e.g., `claude-sonnet-4-5-20250929`, `claude-opus-4-5-20251101`) are also supported.
+
+## Key Differences from First-Party Anthropic
+
+| Aspect | First-Party Anthropic | Claude Platform on AWS |
+|---|---|---|
+| Base URL | `api.anthropic.com` | `aws-external-anthropic.{region}.api.aws` |
+| Authentication | API key (`x-api-key`) | AWS SigV4 or AWS-managed API key |
+| Billing | Anthropic directly | AWS Marketplace |
+| Required headers | `anthropic-version`, `x-api-key` | `anthropic-version`, `anthropic-workspace-id` + SigV4 |
+| Rate limits | Automatic tier advancement | Contact Anthropic representative |
+| Console access | Direct login | Federated through AWS IAM |
+| OAuth | Supported | Not supported |
+| OpenAI-compatible endpoints | Available | Not available |
+| Webhooks | Available | Not available |
+
+
+Portkey handles all authentication and header translation automatically. From the Portkey SDK, the experience is identical to using first-party Anthropic -- just use a different provider slug.
+
+
+## Making Requests Without Model Catalog
+
+Pass AWS credentials directly via headers:
+
+```sh cURL icon="square-terminal"
+curl https://api.portkey.ai/v1/chat/completions \
+ -H "Content-Type: application/json" \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: claude-platform-aws" \
+ -H "x-portkey-aws-access-key-id: $AWS_ACCESS_KEY_ID" \
+ -H "x-portkey-aws-secret-access-key: $AWS_SECRET_ACCESS_KEY" \
+ -H "x-portkey-aws-region: us-west-2" \
+ -H "x-portkey-anthropic-aws-workspace-id: wrkspc_01AbCdEf23GhIj" \
+ -d '{
+ "model": "claude-sonnet-4-6",
+ "messages": [{ "role": "user", "content": "Hello" }],
+ "max_tokens": 250
+ }'
+```
+
+| Header | Description |
+|---|---|
+| `x-portkey-aws-access-key-id` | AWS access key ID |
+| `x-portkey-aws-secret-access-key` | AWS secret access key |
+| `x-portkey-aws-session-token` | AWS session token (for STS) |
+| `x-portkey-aws-region` | AWS region (e.g., `us-west-2`) |
+| `x-portkey-anthropic-aws-workspace-id` | Anthropic workspace ID (optional) |
+
+## Next Steps
+
+
+
+ Upload, list, retrieve, and delete files
+
+
+ Run large async jobs at 50% lower cost
+
+
+ Step-by-step IAM role and trust policy setup
+
+
+ Shared features: prompt caching, structured outputs, vision
+
+
+
+
+
+ Add gateway configs to your requests
+
+
+ Trace and monitor your requests
+
+
diff --git a/integrations/llms/claude-platform-aws/files.mdx b/integrations/llms/claude-platform-aws/files.mdx
new file mode 100644
index 00000000..d6c02e98
--- /dev/null
+++ b/integrations/llms/claude-platform-aws/files.mdx
@@ -0,0 +1,429 @@
+---
+title: Files
+description: Upload and manage files with Claude Platform on AWS through Portkey
+---
+
+Portkey supports Anthropic's [Files API](https://docs.anthropic.com/en/docs/build-with-claude/files) (beta) for Claude Platform on AWS, enabling file upload, listing, retrieval, and deletion through the gateway. Uploaded files can be referenced in chat completions using `file_id` instead of re-uploading content each request.
+
+
+The Files API is in beta and requires the `files-api-2025-04-14` beta header. Portkey sets this automatically for file endpoints when using the SDK. For cURL requests, include the `anthropic-beta: files-api-2025-04-14` header.
+
+
+## Upload a file
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+file = portkey.files.create(
+ purpose="assistants",
+ file=open("document.pdf", "rb")
+)
+
+print(file.id)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+import fs from 'fs';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const file = await portkey.files.create({
+ purpose: "assistants",
+ file: fs.createReadStream("document.pdf")
+});
+
+console.log(file.id);
+```
+
+
+```sh
+curl -X POST https://api.portkey.ai/v1/files \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider" \
+ -H "anthropic-beta: files-api-2025-04-14" \
+ -F 'file=@"document.pdf"'
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+file = client.files.create(
+ purpose="assistants",
+ file=open("document.pdf", "rb")
+)
+
+print(file.id)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+import fs from 'fs';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const file = await client.files.create({
+ purpose: "assistants",
+ file: fs.createReadStream("document.pdf")
+});
+
+console.log(file.id);
+```
+
+
+
+## Use uploaded files in chat completions
+
+Once a file is uploaded, reference it by `file_id` in chat completions:
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(api_key="PORTKEY_API_KEY")
+
+response = portkey.chat.completions.create(
+ model="@claude-platform-aws-provider/claude-sonnet-4-6",
+ max_tokens=1024,
+ messages=[{
+ "role": "user",
+ "content": [
+ {"type": "text", "text": "Please summarize this document."},
+ {"type": "file", "file": {"file_id": "", "mime_type": "application/pdf"}}
+ ]
+ }]
+)
+
+print(response.choices[0].message.content)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY"
+});
+
+const response = await portkey.chat.completions.create({
+ model: "@claude-platform-aws-provider/claude-sonnet-4-6",
+ max_tokens: 1024,
+ messages: [{
+ role: "user",
+ content: [
+ { type: "text", text: "Please summarize this document." },
+ { type: "file", file: { file_id: "", mime_type: "application/pdf" } }
+ ]
+ }]
+});
+
+console.log(response.choices[0].message.content);
+```
+
+
+```sh
+curl -X POST https://api.portkey.ai/v1/chat/completions \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "anthropic-beta: files-api-2025-04-14" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "model": "@claude-platform-aws-provider/claude-sonnet-4-6",
+ "max_tokens": 1024,
+ "messages": [
+ {
+ "role": "user",
+ "content": [
+ {"type": "text", "text": "Please summarize this document."},
+ {"type": "file", "file": {"file_id": "", "mime_type": "application/pdf"}}
+ ]
+ }
+ ]
+ }'
+```
+
+
+
+
+When using the SDK, the `anthropic-beta` header is set automatically for file endpoints. For chat completions with file references via cURL, include `anthropic-beta: files-api-2025-04-14` in your request headers.
+
+
+## List files
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+files = portkey.files.list()
+
+print(files)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const files = await portkey.files.list();
+
+console.log(files);
+```
+
+
+```sh
+curl https://api.portkey.ai/v1/files \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider" \
+ -H "anthropic-beta: files-api-2025-04-14"
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+files = client.files.list()
+
+print(files)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const files = await client.files.list();
+
+console.log(files);
+```
+
+
+
+## Get file
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+file = portkey.files.retrieve(file_id="")
+
+print(file)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const file = await portkey.files.retrieve("");
+
+console.log(file);
+```
+
+
+```sh
+curl https://api.portkey.ai/v1/files/ \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider" \
+ -H "anthropic-beta: files-api-2025-04-14"
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+file = client.files.retrieve("")
+
+print(file)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const file = await client.files.retrieve("");
+
+console.log(file);
+```
+
+
+
+## Delete file
+
+
+
+```python
+from portkey_ai import Portkey
+
+portkey = Portkey(
+ api_key="PORTKEY_API_KEY",
+ provider="@claude-platform-aws-provider"
+)
+
+response = portkey.files.delete(file_id="")
+
+print(response)
+```
+
+
+```js
+import Portkey from 'portkey-ai';
+
+const portkey = new Portkey({
+ apiKey: "PORTKEY_API_KEY",
+ provider: "@claude-platform-aws-provider"
+});
+
+const response = await portkey.files.delete("");
+
+console.log(response);
+```
+
+
+```sh
+curl -X DELETE https://api.portkey.ai/v1/files/ \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -H "x-portkey-provider: @claude-platform-aws-provider" \
+ -H "anthropic-beta: files-api-2025-04-14"
+```
+
+
+```python
+from openai import OpenAI
+from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders
+
+client = OpenAI(
+ api_key="PORTKEY_API_KEY",
+ base_url=PORTKEY_GATEWAY_URL,
+ default_headers=createHeaders(
+ provider="@claude-platform-aws-provider",
+ api_key="PORTKEY_API_KEY"
+ )
+)
+
+response = client.files.delete("")
+
+print(response)
+```
+
+
+```js
+import OpenAI from 'openai';
+import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai';
+
+const client = new OpenAI({
+ apiKey: "PORTKEY_API_KEY",
+ baseURL: PORTKEY_GATEWAY_URL,
+ defaultHeaders: createHeaders({
+ provider: "@claude-platform-aws-provider",
+ apiKey: "PORTKEY_API_KEY"
+ })
+});
+
+const response = await client.files.delete("");
+
+console.log(response);
+```
+
+
+
+## Supported file types
+
+| Type | MIME types |
+|------|-----------|
+| PDF | `application/pdf` |
+| Images | `image/jpeg`, `image/png`, `image/gif`, `image/webp` |
+
+## See Also
+
+- [Claude Platform on AWS integration overview](/integrations/llms/claude-platform-aws/claude-platform-aws)
+- [Anthropic Files API documentation](https://docs.anthropic.com/en/docs/build-with-claude/files)
diff --git a/integrations/llms/claude-platform-aws/setup-assumed-role.mdx b/integrations/llms/claude-platform-aws/setup-assumed-role.mdx
new file mode 100644
index 00000000..df7b8df5
--- /dev/null
+++ b/integrations/llms/claude-platform-aws/setup-assumed-role.mdx
@@ -0,0 +1,196 @@
+---
+title: "Setup Assumed Role for Claude Platform on AWS"
+description: "Configure AWS IAM assumed role authentication for Claude Platform on AWS on Portkey"
+---
+
+
+ On the Enterprise plan? See the Helm documentation for assumed role setup in self-hosted deployments.
+
+
+## Enable Outbound Web Identity Federation
+
+
+This is a one-time setup step for your AWS account. Without it, all Claude Platform on AWS requests fail with `"Outbound web identity federation is disabled for your account"`.
+
+```bash
+aws iam enable-outbound-web-identity-federation
+```
+
+
+## Select Assumed Role Authentication
+
+Create a new integration on Portkey:
+
+1. Go to [**Model Catalog → Add Provider**](https://app.portkey.ai/model-catalog/providers)
+2. Select **Claude Platform on AWS**
+3. Choose **AWS Assumed Role** as the authentication method
+
+## Create an IAM Permission Policy
+
+Create a permission policy in your AWS account. Claude Platform on AWS uses the `aws-external-anthropic` IAM namespace (not `bedrock`).
+
+### Inference-only policy
+
+For workloads that only need chat completions and token counting:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "ClaudePlatformInference",
+ "Effect": "Allow",
+ "Action": [
+ "aws-external-anthropic:CreateInference",
+ "aws-external-anthropic:CountTokens"
+ ],
+ "Resource": "arn:aws:aws-external-anthropic:*:*:workspace/*"
+ }
+ ]
+}
+```
+
+### Full access policy
+
+For workloads that also need batch processing and file management:
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "ClaudePlatformFullAccess",
+ "Effect": "Allow",
+ "Action": [
+ "aws-external-anthropic:CreateInference",
+ "aws-external-anthropic:CountTokens",
+ "aws-external-anthropic:CreateBatchInference",
+ "aws-external-anthropic:GetBatchInference",
+ "aws-external-anthropic:ListBatchInferences",
+ "aws-external-anthropic:CancelBatchInference",
+ "aws-external-anthropic:DeleteBatchInference",
+ "aws-external-anthropic:CreateFile",
+ "aws-external-anthropic:GetFile",
+ "aws-external-anthropic:ListFiles",
+ "aws-external-anthropic:DeleteFile"
+ ],
+ "Resource": "arn:aws:aws-external-anthropic:*:*:workspace/*"
+ }
+ ]
+}
+```
+
+
+To restrict access to a specific workspace and region, replace the `Resource` with:
+
+```
+arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj
+```
+
+
+Alternatively, attach one of the AWS-managed policies:
+
+| Managed Policy | Scope |
+|---|---|
+| `AnthropicFullAccess` | All `aws-external-anthropic:*` actions |
+| `AnthropicInferenceAccess` | Inference + read-only actions |
+| `AnthropicReadOnlyAccess` | `Get*`, `List*`, `CallWithBearerToken` |
+
+## Create an IAM Role
+
+1. Open the [IAM Console](https://console.aws.amazon.com/iam/) and go to **Roles → Create role**
+2. Choose **AWS account** as the trusted entity type
+3. Optionally set an **external ID** -- copy it for later
+4. Attach the permission policy created above
+5. Name the role (e.g., `portkey-claude-platform-role`) and create it
+
+## Configure the Trust Relationship
+
+Open the role, navigate to the **Trust relationships** tab, and click **Edit trust policy**.
+
+Add Portkey's AWS account as a trusted principal:
+
+```sh Portkey Account ARN
+arn:aws:iam::299329113195:role/portkey-app
+```
+
+
+This ARN is for the [hosted Portkey app](https://app.portkey.ai/). For enterprise self-hosted deployments, refer to the [Helm documentation](https://github.com/Portkey-AI/helm/blob/main/charts/portkey-gateway/docs/Bedrock.md).
+
+
+### Trust policy without external ID
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::299329113195:role/portkey-app"
+ },
+ "Action": "sts:AssumeRole",
+ "Condition": {}
+ }
+ ]
+}
+```
+
+### Trust policy with external ID
+
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::299329113195:role/portkey-app"
+ },
+ "Action": "sts:AssumeRole",
+ "Condition": {
+ "StringEquals": {
+ "sts:ExternalId": ""
+ }
+ }
+ }
+ ]
+}
+```
+
+## Configure the Integration
+
+Back in Portkey, enter the following in the Claude Platform on AWS integration modal:
+
+| Field | Value |
+|---|---|
+| **Role ARN** | The ARN of the role you created (e.g., `arn:aws:iam::123456789012:role/portkey-claude-platform-role`) |
+| **External ID** | The external ID you set (if any) |
+| **AWS Region** | The region for your workspace (e.g., `us-west-2`) |
+| **Anthropic Workspace ID** | Your workspace ID (optional, format: `wrkspc_01AbCdEf23GhIj`) |
+
+Save the integration. Portkey will assume the IAM role and sign requests with SigV4 using the `aws-external-anthropic` service name.
+
+## Verify the Setup
+
+Test the integration with a simple request:
+
+```sh cURL icon="square-terminal"
+curl https://api.portkey.ai/v1/chat/completions \
+ -H "Content-Type: application/json" \
+ -H "x-portkey-api-key: $PORTKEY_API_KEY" \
+ -d '{
+ "model": "@claude-platform-aws-provider/claude-sonnet-4-6",
+ "messages": [{ "role": "user", "content": "Hello" }],
+ "max_tokens": 100
+ }'
+```
+
+## Troubleshooting
+
+| Error | Cause | Fix |
+|---|---|---|
+| `Outbound web identity federation is disabled` | Federation not enabled on the AWS account | Run `aws iam enable-outbound-web-identity-federation` |
+| `Access denied` / `not authorized to perform` | Missing IAM permissions | Verify the permission policy includes the required `aws-external-anthropic:*` actions |
+| `Invalid signature` | Incorrect region or credentials | Confirm the region matches your workspace and the role ARN is correct |
+| `Trust policy error` | Portkey ARN not in trust policy | Add `arn:aws:iam::299329113195:role/portkey-app` as a trusted principal |