Skip to content

Making requests

Read this guide to construct a request by hand, or to understand what your SDK does on your behalf.

  • An access key id and secret access key

A request is a POST to the service endpoint with a form-encoded body:

POST / HTTP/1.1
Host: ec2.hel1.shelfcloud.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8
X-Amz-Date: 20260903T142207Z
Authorization: AWS4-HMAC-SHA256
Credential=AKIA.../20260903/hel1/ec2/aws4_request,
SignedHeaders=content-type;host;x-amz-date,
Signature=...
Action=DescribeInstances&Version=2016-11-15

GET with a query string is also accepted, and is what presigned requests use.

The Credential parameter is the access key id, a slash, then the credential scope:

AKIAIOSFODNN7EXAMPLE/20260903/hel1/ec2/aws4_request

The access key id is sent in the clear and is not part of the credential scope. The scope is the four trailing elements.

The hashed payload is always the final line of the canonical request, including for requests with no body, which sign the hash of the empty string.

SignedHeaders must contain host, x-amz-date, and every x-amz-* header present on the request, plus content-type when a body is sent. Headers not listed in SignedHeaders are ignored by the server rather than acted on.

PROPOSED: 15 minutes. A request whose X-Amz-Date is outside that window is rejected with RequestExpired and HTTP 400.

Our server time is in the Date header of every response, including error responses, so that a client can detect its own skew. The AWS SDKs correct their clocks automatically from this, and only when the status and error code match what they expect — which is why the status codes on the error page are not negotiable.

Retry on:

  • HTTP 500, 502, 503, 504
  • RequestLimitExceeded
  • InternalError

Retry with exponential backoff and jitter.

A resource that has just been created may not be visible to an immediately following call. DescribeInstances may not return an instance that RunInstances has just returned an id for, and a security group referenced seconds after creation may return InvalidGroup.NotFound.

This is inherited from Amazon EC2 and existing tooling already accounts for it: the Terraform AWS provider retries NotFound errors on recently created resources for exactly this reason.

Therefore, and against the general rule that a 4xx is not retryable, do retry a NotFound error for a resource you created in the last few seconds.

PROPOSED: a created resource is visible to all readers within 10 seconds.

RunInstances accepts a ClientToken. A repeated request with the same token returns the original result rather than launching a second instance. If the token is reused with different parameters, the request is refused with IdempotentParameterMismatch.

Actions that do not accept a ClientToken in the Amazon EC2 model do not accept one here either. The SDKs validate parameters against their own model before sending, so a token added to an action AWS does not model would be rejected by the client, before it ever reached us.

For those actions, retry safety comes from the action’s own semantics: CreateTags sets tags to a value and repeating it is harmless; DeleteVolume on an already-deleted volume returns InvalidVolume.NotFound, which the caller treats as success.

See Pagination.