AWS Signature Version 4 (SigV4) is the request-signing scheme used across AWS: your client derives a signing key from your credentials plus the date, the region, and a service name, then signs each request with it. If any ingredient on your side differs from what the server expects, the signatures don't match and the request is rejected. For Claude Platform on AWS — the Anthropic-operated service that lives inside AWS — the service name is aws-external-anthropic, and it appears in three places you will touch: the SigV4 signing string, the IAM action namespace (aws-external-anthropic:CreateInference and friends), and the endpoint hostname itself, aws-external-anthropic.{region}.api.aws.
Why not a Bedrock name?
Because it is not Bedrock. Amazon Bedrock is AWS-operated, with its own endpoints and its own IAM namespace (bedrock:InvokeModel). Claude Platform on AWS is a different arrangement: Anthropic operates the service and the models run on Anthropic-managed infrastructure, while AWS provides the authentication layer, IAM-based access control, and Marketplace billing. The aws-external-anthropic name says exactly that — an external partner service authenticated through AWS's front door. Signing a request to it with bedrock as the service name (a natural reflex for teams migrating) produces a signature the gateway will never accept.
Setting it correctly
In cURL, the service name rides in the --aws-sigv4 flag:
curl "https://aws-external-anthropic.us-east-1.api.aws/v1/messages" \
--aws-sigv4 "aws:amz:us-east-1:aws-external-anthropic" \
--user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \
-H "anthropic-workspace-id: $ANTHROPIC_AWS_WORKSPACE_ID" \
-H "content-type: application/json" \
-d '{"model": "claude-sonnet-5", "max_tokens": 256,
"messages": [{"role": "user", "content": "Hello"}]}'
Two alignment rules hide in there. The region in the --aws-sigv4 string must match the region in the endpoint URL — a mismatch in either the region or the service name is rejected. And every request needs the anthropic-workspace-id header, since workspaces are the platform's isolation boundary. If you use temporary credentials (an assumed role, SSO, or STS), you must also send the x-amz-security-token header.
With the official SDK, all of this disappears. The AnthropicAWS client signs with the right service name, builds the regional base URL, attaches the workspace header, and handles the security token automatically — it reads AWS_REGION and ANTHROPIC_AWS_WORKSPACE_ID from the environment and raises if either is missing rather than guessing:
from anthropic import AnthropicAWS
client = AnthropicAWS() # needs AWS_REGION + ANTHROPIC_AWS_WORKSPACE_ID
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=256,
messages=[{"role": "user", "content": "Hello"}],
)
The misleading error
Here is the part that costs teams an afternoon: a service-name or region mismatch does not say "wrong service name." It produces a generic signature-rejection error — the same class of error you would get from a clock skew, a bad secret key, or a malformed canonical request. SigV4 verification can only report that the computed signature didn't match; it cannot tell you which ingredient was wrong. So when a hand-rolled integration fails signature validation against this endpoint, check the boring things in this order: service name is exactly aws-external-anthropic, the signing region equals the endpoint region, credentials are current (and the security token is present for temporary credentials). Only then suspect anything exotic.
AnthropicAWS and let the SDK own the signing details — it also walks the full AWS default credential chain, from env vars through SSO profiles to EC2 instance roles.Where to go next
The same string is the IAM namespace, so policy work continues in the IAM actions reference. Signature errors' close cousin — the once-per-account STS prerequisite — has its own article, and SigV4 under the hood goes deeper on the signing math.