all docs
/ integrations

AWS Bedrock integration

Call AWS Bedrock through the ACE gateway: endpoint, zero-trust credential headers, stored-key alternative and runnable examples.

Send AWS Bedrock traffic to https://engine.acefleet.dev/bedrock/converse with your ACE developer key in Authorization: Bearer ace_dev_... and the provider credential on the zero-trust headers below. The request body is the vendor's own, relayed as written, and the vendor's answer comes back verbatim.

The same headers also serve:

  • https://engine.acefleet.dev/bedrock/converse-stream
  • https://engine.acefleet.dev/bedrock/model/{modelId}/converse
  • https://engine.acefleet.dev/bedrock/model/{modelId}/converse-stream
  • https://engine.acefleet.dev/v1/chat/completions
  • https://engine.acefleet.dev/anthropic/v1/messages

Zero-trust headers

Header Required What it carries
x-ace-bedrock-api-key situational An Amazon Bedrock API key (long-term ABSK… or short-term). Use this OR the access-key pair below, never both — a key beside a pair, or half a pair, is a 400 naming both headers. ACE sends it upstream as Authorization: Bearer and signs nothing, so no AWS secret or STS token leaves your side. Not read off Authorization, which carries your ACE key.
x-ace-bedrock-key situational AWS access key id, half of the SigV4 pair — the alternative to x-ace-bedrock-api-key; one of the two is required. ACE computes the SigV4 signature per request — there is no local AWS CLI, profile or assumed role involved.
x-ace-aws-secret-access-key situational AWS secret access key, the other half of the pair. Bedrock is signed rather than forwarded on this path, so unlike every other provider here the credential is a pair, not a single token — unless you send the API key instead.
x-ace-aws-region yes Region the model is served from. With the pair it is part of the SigV4 scope (defaults to us-east-1 when absent); with an API key it is required — a short-term key is bound to the region it was minted in, and a missing region is a 400, never a defaulted host.
x-ace-aws-session-token situational Only for temporary STS credentials with the pair. Omit it for a long-lived key pair or an API key.
x-ace-provider situational Pin the channel to bedrock on /v1/chat/completions (an OpenAI body translated to Converse) or /anthropic/v1/messages (a Messages body sent to InvokeModel as Anthropic's Bedrock SDK sends it); the /bedrock/… paths imply it.

Stored key instead

A stored bedrock vendor key replaces the credential headers; region is stored with it. POST /api/v1/vendor_key/create with provider: bedrock takes the packed access-key pair as api_key by default, or an Amazon Bedrock API key when the body says credential_kind: "api_key"; a pair stored before that field existed is unchanged. A pass-through pair beats a stored API key, as a pass-through key beats a stored one everywhere else. An AWS SDK or the AI SDK's Bedrock provider pointed at /bedrock builds /model/{modelId}/converse[-stream] with the id percent-encoded in the path (ARNs included); the gateway serves that path and lifts modelId into the body, so the SDK needs only a base URL and these headers — see the Vercel AI SDK quickstart.

Example request

curl -X POST https://engine.acefleet.dev/bedrock/converse \
  -H "Authorization: Bearer ace_dev_<your-dev-key>" \
  -H "x-ace-bedrock-api-key: ABSK..." \
  -H "x-ace-aws-region: us-east-1" \
  -H "Content-Type: application/json" \
  -d '{ "modelId": "anthropic.claude-3-5-sonnet-20241022-v2:0",
        "messages": [{ "role": "user", "content": [{ "text": "ping" }] }] }'

# The SigV4 pair instead (never both), at the path an AWS SDK builds:
curl -X POST https://engine.acefleet.dev/bedrock/model/anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse \
  -H "Authorization: Bearer ace_dev_<your-dev-key>" \
  -H "x-ace-bedrock-key: AKIAIOSFODNN7EXAMPLE" \
  -H "x-ace-aws-secret-access-key: wJalrXUtnFEMI/K7MDENG/..." \
  -H "x-ace-aws-region: us-east-1" \
  -H "Content-Type: application/json" \
  -d '{ "messages": [{ "role": "user", "content": [{ "text": "ping" }] }] }'

Quickstarts

AWS Bedrock proxy (cURL)

# An Amazon Bedrock API key: sent upstream as a bearer, nothing signed, no AWS secret
# leaves your side. The region is required with it.
curl -X POST https://engine.acefleet.dev/bedrock/converse \
  -H "Authorization: Bearer ace_dev_<your-dev-key>" \
  -H "x-ace-bedrock-api-key: ABSK..." \
  -H "x-ace-aws-region: us-east-1" \
  -H "Content-Type: application/json" \
  -d '{
    "modelId": "anthropic.claude-3-5-sonnet-20241022-v2:0",
    "messages": [
      { "role": "user", "content": [{ "text": "Optimize GPU allocations." }] }
    ]
  }'

# The SigV4 pair instead (never both): ACE signs the request for the AWS host.
# modelId may also travel in the path, as an AWS SDK sends it (percent-encoded).
curl -X POST https://engine.acefleet.dev/bedrock/model/anthropic.claude-3-5-sonnet-20241022-v2%3A0/converse \
  -H "Authorization: Bearer ace_dev_<your-dev-key>" \
  -H "x-ace-bedrock-key: AKIAIOSFODNN7EXAMPLE" \
  -H "x-ace-aws-secret-access-key: wJalrXUtnFEMI/K7MDENG/..." \
  -H "x-ace-aws-region: us-east-1" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      { "role": "user", "content": [{ "text": "Optimize GPU allocations." }] }
    ]
  }'

Vercel AI SDK: Bedrock (@ai-sdk/amazon-bedrock)

baseURL is the gateway's /bedrock prefix and nothing else changes: the provider builds {baseURL}/model/{modelId}/converse[-stream] with the id percent-encoded in the path (: as %3A; an inference-profile ARN with / as %2F), and the gateway serves exactly that path, lifting modelId from it into the body. No request-rewriting fetch. The upstream credential is one of two on the zero-trust headers, never both: an Amazon Bedrock API key on x-ace-bedrock-api-key, which ACE sends upstream as a bearer with nothing signed, or the access-key pair on x-ace-bedrock-key + x-ace-aws-secret-access-key, which ACE SigV4-signs for the real AWS host. x-ace-aws-region names the region either way (required with the key). The ACE dev key rides on Authorization: Bearer — the provider's apiKey option sends it there and signs nothing — or on x-api-key, which the surface promotes to the bearer when none is present. That second shape is for a client that SigV4-signs against the gateway's host (accessKeyId / secretAccessKey set instead of apiKey): ACE never reads a credential out of a SigV4 Authorization and never forwards it — that signature was computed over the gateway's host and is useless upstream — so the ACE identity has to travel on x-api-key and the AWS credential on the x-ace-* headers. The streaming reply is AWS's binary event-stream framing, which is what a Converse client parses; Accept: application/x-ndjson asks for newline-delimited JSON instead.

import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';

const bedrock = createAmazonBedrock({
  baseURL: 'https://engine.acefleet.dev/bedrock',                 // the SDK builds /model/{modelId}/converse[-stream]
  apiKey: 'ace_dev_<your-dev-key>',                 // Authorization: Bearer — your ACE identity
  headers: {
    'x-ace-bedrock-api-key': 'ABSK...',       // zero-trust: sent upstream as a bearer, nothing signed
    'x-ace-aws-region': 'us-east-1',          // required with an API key
  },
});
// model: bedrock('anthropic.claude-3-5-sonnet-20241022-v2:0')
//
// With the SigV4 pair instead: drop apiKey and x-ace-bedrock-api-key, set
//   'x-api-key': 'ace_dev_<your-dev-key>',
//   'x-ace-bedrock-key': 'AKIAIOSFODNN7EXAMPLE',
//   'x-ace-aws-secret-access-key': 'wJalrXUtnFEMI/K7MDENG/...',
// in headers; the client-side signature the SDK adds is ignored and ACE signs for AWS itself.