

# API Gateway REST APIs
<a name="apigateway-rest-api"></a>

A REST API in API Gateway is a collection of resources and methods that are integrated with backend HTTP endpoints, Lambda functions, or other AWS services. You can use API Gateway features to help you with all aspects of the API lifecycle, from creation through monitoring your production APIs.

API Gateway REST APIs use a request/response model where a client sends a request to a service and the service responds back synchronously. This kind of model is suitable for many different kinds of applications that depend on synchronous communication.

**Topics**
+ [Develop REST APIs in API Gateway](rest-api-develop.md)
+ [Publish REST APIs for customers to invoke](rest-api-publish.md)
+ [Optimize performance of REST APIs](rest-api-optimize.md)
+ [Distribute your REST APIs to clients in API Gateway](rest-api-distribute.md)
+ [Protect your REST APIs in API Gateway](rest-api-protect.md)
+ [Monitor REST APIs in API Gateway](rest-api-monitor.md)

# Develop REST APIs in API Gateway
<a name="rest-api-develop"></a>

 In Amazon API Gateway, you build a REST API as a collection of programmable entities known as API Gateway [resources](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html). For example, you use a [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource to represent an API that can contain a collection of [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) entities. 

Each `Resource` entity can have one or more [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) resources. A `Method` is an incoming request submitted by the client and can contain the following request parameters: a path parameter, a header, or a query string parameter. In addition, depending on the HTTP method, the request can contain a body. Your method defines how the client accesses the exposed `Resource`. To integrate the `Method` with a backend endpoint, also known as the integration endpoint, you create an [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource. This forwards the incoming request to a specified integration endpoint URI. If necessary, you can transform request parameters or the request body to meet the backend requirements, or you can create a proxy integration, where API Gateway sends the entire request in a standardized format to the integration endpoint URI and then directly sends the response to the client.

For responses, you can create a [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) resource to represent a response received by the client and you create an [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) resource to represent the response that is returned by the backend. Use an integration response to transform the backend response data before returning the data to the client or to pass the backend response as-is to the client.

## Example resource for a REST API
<a name="rest-api-develop-example"></a>

The following diagram shows how API Gateway implements this request/response model for an HTTP proxy and an HTTP non-proxy integration for the `GET /pets` resource. The client sends the `x-version:beta` header to API Gateway and API Gateway sends the `204` status code to the client.

In the non-proxy integration, API Gateway performs data transformations to meet the backend requirements, by modifying the integration request and integration response. In a non-proxy integration, you can access the body in the method request but you transform it in the integration request. When the integration endpoint returns a response with a body, you access and transform it in the integration response. You can't modify the body in the method response.

In the proxy integration, the integration endpoint modifies the request and response. API Gateway doesn't modify the integration request or integration response, and sends the incoming request to the backend as-is.

Regardless of the integration type, the client sent a request to API Gateway and API Gateway responded synchronously.

------
#### [ Non-proxy integration ]

![\[Diagram of API Gateway non-proxy integration\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/develop-non-proxy.png)


------
#### [ Proxy integration ]

![\[Diagram of API Gateway proxy integration\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/develop-proxy.png)


------

The following example execution logs show what API Gateway would log in the previous example. For clarity, some values and initial logs have been removed:

------
#### [ Non-proxy integration ]

```
Wed Feb 12 23:56:44 UTC 2025 : Starting execution for request: abcd-1234-5678
Wed Feb 12 23:56:44 UTC 2025 : HTTP Method: GET, Resource Path: /pets
Wed Feb 12 23:56:44 UTC 2025 : Method request path: {}
Wed Feb 12 23:56:44 UTC 2025 : Method request query string: {}
Wed Feb 12 23:56:44 UTC 2025 : Method request headers: {x-version=beta}
Wed Feb 12 23:56:44 UTC 2025 : Method request body before transformations: 
Wed Feb 12 23:56:44 UTC 2025 : Endpoint request URI: http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:56:44 UTC 2025 : Endpoint request headers: {app-version=beta}
Wed Feb 12 23:56:44 UTC 2025 : Endpoint request body after transformations: 
Wed Feb 12 23:56:44 UTC 2025 : Sending request to http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:56:45 UTC 2025 : Received response. Status: 200, Integration latency: 123 ms
Wed Feb 12 23:56:45 UTC 2025 : Endpoint response headers: {Date=Wed, 12 Feb 2025 23:56:45 GMT}
Wed Feb 12 23:56:45 UTC 2025 : Endpoint response body before transformations:
Wed Feb 12 23:56:45 UTC 2025 : Method response body after transformations: (null)
Wed Feb 12 23:56:45 UTC 2025 : Method response headers: {X-Amzn-Trace-Id=Root=1-abcd-12345}
Wed Feb 12 23:56:45 UTC 2025 : Successfully completed execution
Wed Feb 12 23:56:45 UTC 2025 : Method completed with status: 204
```

------
#### [ Proxy integration ]

```
Wed Feb 12 23:59:42 UTC 2025 : Starting execution for request: abcd-1234-5678
Wed Feb 12 23:59:42 UTC 2025 : HTTP Method: GET, Resource Path: /pets
Wed Feb 12 23:59:42 UTC 2025 : Method request path: {}
Wed Feb 12 23:59:42 UTC 2025 : Method request query string: {}
Wed Feb 12 23:59:42 UTC 2025 : Method request headers: {x-version=beta}
Wed Feb 12 23:59:42 UTC 2025 : Method request body before transformations: 
Wed Feb 12 23:59:42 UTC 2025 : Endpoint request URI: http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:59:42 UTC 2025 : Endpoint request headers: { x-version=beta}
Wed Feb 12 23:59:42 UTC 2025 : Endpoint request body after transformations: 
Wed Feb 12 23:59:42 UTC 2025 : Sending request to http://petstore-demo-endpoint.execute-api.com/petstore/pets
Wed Feb 12 23:59:43 UTC 2025 : Received response. Status: 204, Integration latency: 123 ms
Wed Feb 12 23:59:43 UTC 2025 : Endpoint response headers: {Date=Wed, 12 Feb 2025 23:59:43 GMT}
Wed Feb 12 23:59:43 UTC 2025 : Endpoint response body before transformations: 
Wed Feb 12 23:59:43 UTC 2025 : Method response body after transformations:
Wed Feb 12 23:59:43 UTC 2025 : Method response headers: {Date=Wed, 12 Feb 2025 23:59:43 GMT}
Wed Feb 12 23:59:43 UTC 2025 : Successfully completed execution
Wed Feb 12 23:59:43 UTC 2025 : Method completed with status: 204
```

------

To import a similar API and test it in the AWS Management Console, see the [example API](api-gateway-create-api-from-example.md).

## Additional REST API features for development
<a name="rest-api-develop-details"></a>

API Gateway supports additional features for the development of your REST API. For example, to help your customers understand your API, you can provide documentation for the API. To enable this, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource for a supported API entity.

To control how clients call an API, use [IAM permissions](permissions.md), a [Lambda authorizer](apigateway-use-lambda-authorizer.md), or an [Amazon Cognito user pool](apigateway-integrate-with-cognito.md). To meter the use of your API, set up [usage plans](api-gateway-api-usage-plans.md) to throttle API requests. You can enable these when creating or updating your API.

The following diagram shows the features available for REST API development and where in the request/response model these features are configured.

![\[Diagram of API Gateway features\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/develop-features.png)


For an introduction on how to create an API, see [Tutorial: Create a REST API with a Lambda proxy integration](api-gateway-create-api-as-simple-proxy-for-lambda.md). To learn more information about the capabilities of API Gateway that you might use while developing a REST API, see the following topics. These topics contain conceptual information and procedures that you can perform using the API Gateway console, the API Gateway REST API, the AWS CLI, or one of the AWS SDKs.

**Topics**
+ [Example resource for a REST API](#rest-api-develop-example)
+ [Additional REST API features for development](#rest-api-develop-details)
+ [API endpoint types for REST APIs in API Gateway](api-gateway-api-endpoint-types.md)
+ [Security policies for REST APIs in API Gateway](apigateway-security-policies.md)
+ [IP address types for REST APIs in API Gateway](api-gateway-ip-address-type.md)
+ [Methods for REST APIs in API Gateway](how-to-method-settings.md)
+ [Control and manage access to REST APIs in API Gateway](apigateway-control-access-to-api.md)
+ [Integrations for REST APIs in API Gateway](how-to-integration-settings.md)
+ [Request validation for REST APIs in API Gateway](api-gateway-method-request-validation.md)
+ [Data transformations for REST APIs in API Gateway](rest-api-data-transformations.md)
+ [Gateway responses for REST APIs in API Gateway](api-gateway-gatewayResponse-definition.md)
+ [CORS for REST APIs in API Gateway](how-to-cors.md)
+ [Binary media types for REST APIs in API Gateway](api-gateway-payload-encodings.md)
+ [Invoke REST APIs in API Gateway](how-to-call-api.md)
+ [Develop REST APIs using OpenAPI in API Gateway](api-gateway-import-api.md)

# API endpoint types for REST APIs in API Gateway
<a name="api-gateway-api-endpoint-types"></a>

An *[API endpoint](api-gateway-basic-concept.md#apigateway-definition-api-endpoints)* type refers to the hostname of the API. The API endpoint type can be *edge-optimized*, *Regional*, or *private*, depending on where the majority of your API traffic originates from.

## Edge-optimized API endpoints
<a name="api-gateway-api-endpoint-types-edge-optimized"></a>

An *[edge-optimized API endpoint](api-gateway-basic-concept.md#apigateway-definition-edge-optimized-api-endpoint)* typically routes requests to the nearest CloudFront Point of Presence (POP), which could help in cases where your clients are geographically distributed. This is the default endpoint type for API Gateway REST APIs.

Edge-optimized APIs capitalize the names of [HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) (for example, `Cookie`).

CloudFront sorts HTTP cookies in natural order by cookie name before forwarding the request to your origin. For more information about the way CloudFront processes cookies, see [Caching Content Based on Cookies](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Cookies.html).

Any custom domain name that you use for an edge-optimized API applies across all regions.

## Regional API endpoints
<a name="api-gateway-api-endpoint-types-regional"></a>

A *[Regional API endpoint](api-gateway-basic-concept.md#apigateway-definition-regional-api-endpoint)* is intended for clients in the same Region. When a client running on an EC2 instance calls an API in the same Region, or when an API is intended to serve a small number of clients with high demands, a Regional API reduces connection overhead.

For a Regional API, any custom domain name that you use is specific to the Region where the API is deployed. If you deploy a Regional API in multiple Regions, it can have the same custom domain name in all Regions. You can use custom domains together with Amazon Route 53 to perform tasks such as [latency-based routing](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-latency). For more information, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md) and [Set up an edge-optimized custom domain name in API Gateway](how-to-edge-optimized-custom-domain-name.md).

Regional API endpoints pass all header names through as-is.

**Note**  
In cases where API clients are geographically dispersed, it may still make sense to use a Regional API endpoint, together with your own Amazon CloudFront distribution to ensure that API Gateway does not associate the API with service-controlled CloudFront distributions. For more information about this use case, see [How do I set up API Gateway with my own CloudFront distribution?](https://repost.aws/knowledge-center/api-gateway-cloudfront-distribution).

## Private API endpoints
<a name="api-gateway-api-endpoint-types-private"></a>

A *[private API endpoint](api-gateway-basic-concept.md#apigateway-definition-private-api-endpoint)* is an API endpoint that can only be accessed from your Amazon Virtual Private Cloud (VPC) using an interface VPC endpoint, which is an endpoint network interface (ENI) that you create in your VPC. For more information, see [Private REST APIs in API Gateway](apigateway-private-apis.md).

Private API endpoints pass all header names through as-is.

# Change a public or private API endpoint type in API Gateway
<a name="apigateway-api-migration"></a>

Changing an API endpoint type requires you to update the API's configuration. You can change an existing API type using the API Gateway console, the AWS CLI, or an AWS SDK for API Gateway. The endpoint type cannot be changed again until the current change is completed, but your API will be available. 

The following endpoint type changes are supported:
+ From edge-optimized to Regional or private
+ From Regional to edge-optimized or private
+ From private to Regional

You cannot change a private API into an edge-optimized API.

If you are changing a public API from edge-optimized to Regional or vice versa, note that an edge-optimized API may have different behaviors than a Regional API. For example, an edge-optimized API removes the `Content-MD5` header. Any MD5 hash value passed to the backend can be expressed in a request string parameter or a body property. However, the Regional API passes this header through, although it may remap the header name to some other name. Understanding the differences helps you decide how to update an edge-optimized API to a Regional one or from a Regional API to an edge-optimized one. 

**Topics**
+ [Use the API Gateway console to change an API endpoint type](#migrate-api-using-console)
+ [Use the AWS CLI to change an API endpoint type](#migrate-api-using-aws-cli)

## Use the API Gateway console to change an API endpoint type
<a name="migrate-api-using-console"></a>

To change the API endpoint type of your API, perform one of the following sets of steps:

**To convert a public endpoint from Regional or edge-optimized and vice versa**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **API settings**.

1. In the **API details** section, choose **Edit**.

1. For **API endpoint type**, select either **Edge-optimized** or **Regional**.

1. Choose **Save changes**.

1. Redeploy your API so that the changes will take effect.

**To convert a private endpoint to a Regional endpoint**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Edit the resource policy for your API to remove any mention of VPCs or VPC endpoints so that API calls from outside your VPC as well as inside your VPC will succeed.

1. Choose **API settings**.

1. In the **API details** section, choose **Edit**.

1. For **API endpoint type**, select **Regional**.

1. Choose **Save changes**.

1. Remove the resource policy from your API.

1. Redeploy your API so that the changes will take effect.

   Because you're migrating the endpoint type from private to Regional, API Gateway changes the IP address type to IPv4. For more information, see [IP address types for REST APIs in API Gateway](api-gateway-ip-address-type.md).

**To convert a Regional endpoint to a private endpoint**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Create a resource policy that grants access to your VPC or VPC endpoint. For more information, see [Step 3: Set up a resource policy for a private API](apigateway-private-api-create.md#apigateway-private-api-set-up-resource-policy).

1. Choose **API settings**.

1. In the **API details** section, choose **Edit**.

1. For **API endpoint type**, select **Private**.

1. (Optional) For **VPC endpoint IDs**, select the VPC endpoint IDs that you want to associate with your private API. 

1. Choose **Save changes**.

1. Redeploy your API so that the changes will take effect.

   Because you're migrating the endpoint type from Regional to private, API Gateway changes the IP address type to dualstack. For more information, see [IP address types for REST APIs in API Gateway](api-gateway-ip-address-type.md).

## Use the AWS CLI to change an API endpoint type
<a name="migrate-api-using-aws-cli"></a>

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command updates an edge-optimized API to a Regional API: 

```
aws apigateway update-rest-api \
    --rest-api-id a1b2c3 \
    --patch-operations op=replace,path=/endpointConfiguration/types/EDGE,value=REGIONAL
```

The successful response has a status code of `200 OK` and a payload similar to the following:

```
{
    "createdDate": "2017-10-16T04:09:31Z",
    "description": "Your first API with Amazon API Gateway. This is a sample API that integrates via HTTP with our demo Pet Store endpoints",
    "endpointConfiguration": {
        "types": "REGIONAL"
    },
    "id": "a1b2c3",
    "name": "PetStore imported as edge-optimized"
}
```

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command updates a Regional API to an edge-optimized API:

```
aws apigateway update-rest-api \
    --rest-api-id a1b2c3 \
    --patch-operations op=replace,path=/endpointConfiguration/types/REGIONAL,value=EDGE
```

Because [put-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-rest-api.html) is for updating API definitions, it is not applicable to updating an API endpoint type.

# Security policies for REST APIs in API Gateway
<a name="apigateway-security-policies"></a>

A *security policy* is a predefined combination of minimum TLS version and cipher suites offered by API Gateway. When your clients establish a TLS handshake to your API or custom domain name, the security policy enforces the TLS version and cipher suite accepted by API Gateway. Security policies protect your APIs and custom domain names from network security problems such as tampering and eavesdropping between a client and server.

API Gateway supports legacy security policies and enhanced security policies. `TLS_1_0` and `TLS_1_2` are legacy security policies. Use these security policies for backwards compatibility. Any policy that starts with `SecurityPolicy_` is an enhanced security policy. Use these policies for regulated workloads, advanced governance, or to use post-quantum cryptography. When you use an enhanced security policy, you must also set the endpoint access mode for additional governance. For more information, see [Endpoint access mode](#apigateway-security-policies-endpoint-access-mode).

## How API Gateway applies security policies
<a name="apigateway-security-policies-understanding"></a>

The following example shows how API Gateway applies security policies using the `SecurityPolicy_TLS13_1_3_2025_09` security policy as an example.

The `SecurityPolicy_TLS13_1_3_2025_09` security policy accepts TLS 1.3 traffic and rejects TLS 1.2 and TLS 1.0 traffic. For TLS 1.3 traffic, the security policy accepts the following cipher suites:
+ `TLS_AES_128_GCM_SHA256`
+ `TLS_AES_256_GCM_SHA384`
+ `TLS_CHACHA20_POLY1305_SHA256`

API Gateway does not accept any other cipher suites. For instance, the security policy would reject any TLS 1.3 traffic that uses the `AES128-SHA` cipher suite. For more information about the supported TLS versions and ciphers, see [Supported security policies](apigateway-security-policies-list.md).

To monitor which TLS protocol and ciphers clients used to access your API Gateway, you can use the `$context.tlsVersion` and `$context.cipherSuite` context variables in your access logs. For more information, see [Monitor REST APIs in API Gateway](rest-api-monitor.md).

## Endpoint access mode
<a name="apigateway-security-policies-endpoint-access-mode"></a>

Endpoint access mode is an additional parameter that you must specify for any REST API or custom domain name that uses an enhanced security policy that begins with `SecurityPolicy_`. You do this when you create your resource or if you change the security policy from a legacy policy to an enhanced policy.

When the endpoint access mode is set to `STRICT`, any requests to your REST API or custom domain name must pass the following checks:
+ The request must originate from the same API Gateway endpoint type as your resource. This could be from a Regional, an edge-optimized, or a private endpoint.
+ If you use a Regional or private endpoint, API Gateway uses SNI host matching. If you use an edge-optimized endpoint, API Gateway conforms to CloudFront's domain fronting protection. For more information, see [Domain fronting](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html#alternate-domain-names-restrictions).

If either of these conditions are not met, API Gateway rejects the request. We recommend that you use `STRICT` endpoint access mode when possible.

To migrate an existing API or domain name to use strict endpoint access mode, first update your security policy to an enhanced security policy and keep the endpoint access mode set to `BASIC`. After you validate your traffic and access logs, set the endpoint access mode to `STRICT`. When you migrate the endpoint access mode from `STRICT` to `BASIC`, your endpoint will be unavailable for around 15 minutes as the changes propagate.

You should not set the endpoint access mode to `STRICT` for certain application architectures and instead set the endpoint access mode to `BASIC`. The following table shows some application architectures and a recommendation so your REST API or custom domain name can use `STRICT` endpoint access mode.


| Architecture | Suggested migration | 
| --- | --- | 
| Using a VPC endpoint to access a public custom domain name. | This architecture uses cross-endpoint type traffic. We recommend that you migrate to [Custom domain names for private APIs in API Gateway](apigateway-private-custom-domains.md). | 
|  Using any method to invoke a private API that doesn't use a custom domain name or private DNS names. | This architecture creates a mismatch between the host header and the SNI used in the TLS handshake and does not pass CloudFront's domain fronting restrictions. We recommend you migrate your VPC to use private DNS. | 
| Using domain sharding to distribute content across multiple domains or subdomains. | This architecture creates a mismatch between the host header and the SNI used in the TLS handshake and does not pass CloudFront's domain fronting restrictions. We recommend that you use `HTTP/2` and migrate away from this anti-pattern. | 

The following are considerations for using endpoint access mode:
+ If the endpoint access mode of an API or domain name is `STRICT`, you can't change the endpoint type. To change the endpoint type, first change the endpoint access mode to `BASIC`.
+ After you change the endpoint access mode from `BASIC` to `STRICT`, there is a 15 minute delay for API Gateway to enforce the strict endpoint access mode.
+ When you change a security policy from a policy that begins with `SecurityPolicy_` to a legacy policy, you must unset the endpoint access mode to `""`.

## Considerations
<a name="apigateway-security-policies-considerations"></a>

The following are considerations for security policies for REST APIs in API Gateway:
+ You can import the security policy in an OpenAPI definition file. For more information, see [x-amazon-apigateway-endpoint-access-modex-amazon-apigateway-security-policy](openapi-extensions-security-policy.md).
+ Your API can be mapped to a custom domain name with a different security policy than your API. When you invoke that custom domain name, API Gateway uses the security policy of the API to negotiate the TLS handshake. If you disable your default API endpoint, this might affect how callers can invoke your API.
+ If you change your security policy, it takes about 15 minutes for the update to complete. You can monitor the `apiStatus` of your API. As your API updates, the `apiStatus` is `UPDATING` and when it completes, it will be `AVAILABLE`. When your API status is `UPDATING`, you can still invoke it.
+ API Gateway supports security policies on all APIs. However, you can only choose a security policy for REST APIs. API Gateway only supports the `TLS_1_2` security policy for HTTP or WebSocket APIs.
+ You can't update the security policy for an API from `TLS_1_0` to `TLS_1_2`.
+ Some security policies support both ECDSA and RSA cipher suites. If you use this type of policy with a custom domain name, the cipher suites match the customer-provided certificate key type, either RSA or ECDSA. If you use this type of policy with a REST API, the cipher suites match the cipher suites compatible with RSA certificate types.

# Supported security policies
<a name="apigateway-security-policies-list"></a>

The following tables describe the [security policies](apigateway-security-policies.md) that can be specified for each REST API endpoint type and custom domain name type. These policies allow you to control incoming connections. API Gateway only supports TLS 1.2 on egress. You can update the security policy for your API or custom domain name at any time.

Policies that contain `FIPS` in the title are compatible with the Federal Information Processing Standard (FIPS), which is a US and Canadian government standard that specifies the security requirements for cryptographic modules that protect sensitive information. To learn more, see [Federal Information Processing Standard (FIPS) 140](https://aws.amazon.com/compliance/fips/) on the *AWS Cloud Security Compliance* page.

All FIPS policies leverage the AWS-LC FIPS validated cryptographic module. To learn more, see the [ AWS-LC Cryptographic Module](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/4631) page on the *NIST Cryptographic Module Validation Program* site.

Policies that contain `PQ` in the title use [Post-Quantum Cryptography (PQC)](https://aws.amazon.com/security/post-quantum-cryptography/) to implement hybrid key exchange algorithms for TLS to ensure traffic confidentiality against future quantum computing threats.

Policies that contain `PFS` in the title use [Perfect Forward Secrecy (PFS)](https://en.wikipedia.org/wiki/Forward_secrecy) to make sure session keys aren't compromised.

Policies that contain both `FIPS` and `PQ` in their title support both of these features.

## Default security policies
<a name="apigateway-security-policies-default"></a>

When you create a new REST API or custom domain, the resource is assigned a default security policy. The following table shows the default security policy for these resources.


| **Resource** | **Default security policy name** | 
| --- | --- | 
| Regional APIs | TLS\$11\$10 | 
| Edge-optimized APIs | TLS\$11\$10 | 
| Private APIs | TLS\$11\$12 | 
| Regional domain | TLS\$11\$12 | 
| Edge-optimized domain | TLS\$11\$12 | 
| Private domain | TLS\$11\$12 | 

## Supported security policies for Regional and private APIs and custom domain names
<a name="apigateway-security-policies-non-edge"></a>

The following table describes the security policies that can be specified for Regional and private APIs and custom domain names:


| **Security policy** | **Supported TLS versions** | **Supported ciphers** | 
| --- | --- | --- | 
| SecurityPolicy\$1TLS13\$11\$13\$12025\$109 | TLS1.3 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$13\$1FIPS\$12025\$109 | TLS1.3 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$12\$1FIPS\$1PFS\$1PQ\$12025\$109 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$12\$1PFS\$1PQ\$12025\$109 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$12\$1PQ\$12025\$109 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS13\$11\$12\$12021\$106 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| TLS\$11\$12 | TLS1.3 TLS1.2 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| TLS\$11\$10 |  TLS1.3 TLS1.2 TLS1.1 TLS1.0  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 

## Supported security policies for edge-optimized APIs and custom domain names
<a name="apigateway-security-policies-edge-optimized"></a>

The following table describes the security policies that can be specified for edge-optimized APIs and edge-optimized custom domain names:


| **Security policy name** | **Supported TLS versions** | **Supported ciphers** | 
| --- | --- | --- | 
| SecurityPolicy\$1TLS13\$12025\$1EDGE | TLS1.3 |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS12\$1PFS\$12025\$1EDGE |  TLS1.3 TLS1.2  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| SecurityPolicy\$1TLS12\$12018\$1EDGE |  TLS1.3 TLS1.2  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 
| TLS\$11\$10 |  TLS1.3 TLS1.2 TLS1.1 TLS1.0  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html) [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-security-policies-list.html)  | 

## OpenSSL and RFC cipher names
<a name="apigateway-secure-connections-openssl-rfc-cipher-names"></a>

OpenSSL and IETF RFC 5246 use different names for the same ciphers. The following table maps the OpenSSL name to the RFC name for each cipher. For more information, see [ciphers](https://docs.openssl.org/1.1.1/man1/ciphers/) in the OpenSSL Documentation.


| **OpenSSL cipher name** | **RFC cipher name** | 
| --- | --- | 
| TLS\$1AES\$1128\$1GCM\$1SHA256 | TLS\$1AES\$1128\$1GCM\$1SHA256 | 
| TLS\$1AES\$1256\$1GCM\$1SHA384 | TLS\$1AES\$1256\$1GCM\$1SHA384 | 
| TLS\$1CHACHA20\$1POLY1305\$1SHA256 | TLS\$1CHACHA20\$1POLY1305\$1SHA256 | 
| ECDHE-RSA-AES128-GCM-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| ECDHE-RSA-AES128-SHA256 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256  | 
| ECDHE-RSA-AES128-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| ECDHE-RSA-AES256-GCM-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384  | 
| ECDHE-RSA-AES256-SHA384 | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA384  | 
| ECDHE-RSA-AES256-SHA | TLS\$1ECDHE\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| AES128-GCM-SHA256 | TLS\$1RSA\$1WITH\$1AES\$1128\$1GCM\$1SHA256 | 
| AES256-GCM-SHA384 | TLS\$1RSA\$1WITH\$1AES\$1256\$1GCM\$1SHA384 | 
| AES128-SHA256 | TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA256 | 
| AES256-SHA | TLS\$1RSA\$1WITH\$1AES\$1256\$1CBC\$1SHA | 
| AES128-SHA | TLS\$1RSA\$1WITH\$1AES\$1128\$1CBC\$1SHA | 
| DES-CBC3-SHA | TLS\$1RSA\$1WITH\$13DES\$1EDE\$1CBC\$1SHA | 

# How to change a security policy
<a name="apigateway-security-policies-update"></a>

You can change the security policy for your API. If you are sending traffic to your APIs through your custom domain name, the API and the custom domain name don't need to have the same security policy. When you invoke that custom domain name, API Gateway uses the security policy of the API to negotiate the TLS handshake. However, for consistency, we recommend that you use the same security policy for your custom domain name and API.

If you change your security policy, it takes about 15 minutes for the update to complete. You can monitor the `apiStatus` of your API. As your API updates, the `apiStatus` is `UPDATING` and when it completes, it will be `AVAILABLE`. When your API is updating, you can still invoke it.

------
#### [ AWS Management Console ]

**To change the security policy of an API**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **API settings**, and then choose **Edit**.

1. For **Security policy**, select a new policy that starts with `SecurityPolicy_`.

1. For **Endpoint access mode**, choose **Strict**.

1. Choose **Save changes**.

   Redeploy your API for the changes to take effect. Because you changed the endpoint access mode to strict, it will take about 15 minutes for the changes to fully propagate.

------
#### [ AWS CLI ]

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command updates an API to use the `SecurityPolicy_TLS13_1_3_2025_09` security policy:

```
aws apigateway update-rest-api \
    --rest-api-id abcd1234 \
    --patch-operations '[
        {
            "op": "replace",
            "path": "/securityPolicy",
            "value": "SecurityPolicy_TLS13_1_3_2025_09"
        }, 
        {
            "op": "replace",
            "path": "/endpointAccessMode",
            "value": "STRICT"
        }
    ]'
```

The output will look like the following:

```
{
    "id": "abcd1234",
    "name": "MyAPI",
    "description": "My API with a new security policy",
    "createdDate": "2025-02-04T11:47:06-08:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "REGIONAL"
        ],
        "ipAddressType": "dualstack"
    },
    "tags": {},
    "disableExecuteApiEndpoint": false,
    "securityPolicy": "SecurityPolicy_TLS13_1_3_2025_09",
    "endpointAccessMode": "STRICT"
    "rootResourceId": "efg456"
}
```

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command updates a API that was using an enhanced security policy to use the `TLS_1_0` security policy.

```
aws apigateway update-rest-api \
    --rest-api-id abcd1234 \
    --patch-operations '[
        {
            "op": "replace",
            "path": "/securityPolicy",
            "value": "TLS_1_0"
        }, 
        {
            "op": "replace",
            "path": "/endpointAccessMode",
            "value": ""
        }
    ]'
```

The output will look like the following:

```
{
    "id": "abcd1234",
    "name": "MyAPI",
    "description": "My API with a new security policy",
    "createdDate": "2025-02-04T11:47:06-08:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "REGIONAL"
        ],
        "ipAddressType": "dualstack"
    },
    "tags": {},
    "disableExecuteApiEndpoint": false,
    "securityPolicy": "TLS_1_0",
    "rootResourceId": "efg456"
}
```

------

# IP address types for REST APIs in API Gateway
<a name="api-gateway-ip-address-type"></a>

When you create an API, you specify the type of IP addresses that can invoke your API. You can choose IPv4 to resolve IPv4 addresses to invoke your API, or you can choose dualstack to allow both IPv4 and IPv6 addresses to invoke your API. We recommend that you set the IP address type to dualstack to alleviate IP space exhaustion or for your security posture. For more information about the benefits of a dualstack IP address type, see [IPv6 on AWS](https://docs.aws.amazon.com/whitepapers/latest/ipv6-on-aws/internet-protocol-version-6.html).

To restrict your API to only IPv6 traffic, you can create a resource policy and restrict the source IP addresses to only IPv6 ranges. You can change the IP address type by updating the API’s configuration. This change will take effect immediately, and you don't need to redeploy your API. For more information, see [Example: Deny API traffic based on source IP address or range](apigateway-resource-policies-examples.md#apigateway-resource-policies-source-ip-address-example)

## Considerations for IP address types
<a name="api-gateway-ip-address-type-considerations"></a>

The following considerations might impact your use of IP address types:
+ The default IP address type for all Regional and edge-optimized APIs is IPv4.
+ Private APIs can only have a dualstack IP address type.
+ If you change the IP address type for an existing API from IPv4 to dualstack, confirm that any policies controlling access to your APIs have been updated to account for IPv6 calls. When you change the IP address type, the change takes effect immediately. 
+ If you migrate the endpoint type of an API from Regional or edge-optimized to private, API Gateway changes the IP address type to dualstack. For more information, see [Change a public or private API endpoint type in API Gateway](apigateway-api-migration.md).
+ If you migrate the endpoint type of an API from private to Regional, you must set the IP address type to dualstack. After the endpoint migration is complete, you can change the IP address type to IPv4. For more information, see [Change a public or private API endpoint type in API Gateway](apigateway-api-migration.md).
+ Your API can be mapped to a custom domain name with a different IP address type than your API. If you disable your default API endpoint, this might affect how callers can invoke your API.
+ You can't use an external definition file to configure your API's IP address type.

# Change the IP address type of a REST API
<a name="api-gateway-ip-address-type-change"></a>

You can change the IP address type by updating the API’s configuration. You can update the API's configuration by using the AWS Management Console, the AWS CLI, CloudFormation, or an AWS SDK. If you change the API’s IP address type, you don't redeploy your API for the changes to take effect. Before you change the IP address type, confirm that any policies controlling access to your APIs have been updated to account for IPv6 calls.

------
#### [ AWS Management Console ]

**To change the IP address type of a REST API**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **API settings**, and then choose **Edit**.

1. For IP address type, select either **IPv4** or **Dualstack**.

1. Choose **Save changes**.

   The change to your API's configuration will take effect immediately.

------
#### [ AWS CLI ]

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command updates an API to have an IP address type of dualstack:

```
aws apigateway update-rest-api \
    --rest-api-id abcd1234 \
    --patch-operations "op='replace',path='/endpointConfiguration/ipAddressType',value='dualstack'"
```

The output will look like the following:

```
{
    "id": "abcd1234",
    "name": "MyAPI",
    "description": "My API with a dualstack IP address type",
    "createdDate": "2025-02-04T11:47:06-08:00",
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "REGIONAL"
        ],
        "ipAddressType": "dualstack"
    },
    "tags": {},
    "disableExecuteApiEndpoint": false,
    "rootResourceId": "efg456"
}
```

------

# Methods for REST APIs in API Gateway
<a name="how-to-method-settings"></a>

 In API Gateway, an API method embodies a [method request](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) and a [method response](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html). You set up an API method to define what a client should or must do to submit a request to access the service at the backend and to define the responses that the client receives in return. For input, you can choose method request parameters, or an applicable payload, for the client to provide the required or optional data at run time. For output, you determine the method response status code, headers, and applicable body as targets to map the backend response data into, before they are returned to the client. To help the client developer understand the behaviors and the input and output formats of your API, you can [document your API](api-gateway-documenting-api.md) and [provide proper error messages](api-gateway-gatewayResponse-definition.md#customize-gateway-responses) for [invalid requests](api-gateway-method-request-validation.md). 

An API method request is an HTTP request. To set up the method request, you configure an HTTP method (or verb), the path to an API [resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html), headers, applicable query string parameters. You also configure a payload when the HTTP method is `POST`, `PUT`, or `PATCH`. For example, to retrieve a pet using the [PetStore sample API](api-gateway-create-api-from-example.md), you define the API method request of `GET /pets/{petId}`, where `{petId}` is a path parameter that can take a number at run time.

```
GET /pets/1
Host: apigateway.us-east-1.amazonaws.com
...
```

If the client specifies an incorrect path, for example, `/pet/1` or `/pets/one` instead of `/pets/1`, an exception is thrown.

An API method response is an HTTP response with a given status code. For a non-proxy integration, you must set up method responses to specify the required or optional targets of mappings. These transform integration response headers or body to associated method response headers or body. The mapping can be as simple as an [identity transform](https://en.wikipedia.org/wiki/Identity_transform) that passes the headers or body through the integration as-is. For example, the following `200` method response shows an example of passthrough of a successful integration response as-is.

```
200 OK 
Content-Type: application/json
...

{
    "id": "1",
    "type": "dog",
    "price": "$249.99"
}
```

In principle, you can define a method response corresponding to a specific response from the backend. Typically, this involves any 2XX, 4XX, and 5XX responses. However, this may not be practical, because often you may not know in advance all the responses that a backend may return. In practice, you can designate one method response as the default to handle the unknown or unmapped responses from the backend. It is good practice to designate the 500 response as the default. In any case, you must set up at least one method response for non-proxy integrations. Otherwise, API Gateway returns a 500 error response to the client even when the request succeeds at the backend.

 To support a strongly typed SDK, such as a Java SDK, for your API, you should define the data model for input for the method request, and define the data model for output of the method response. 

## Prerequisites
<a name="method-setting-prerequisites"></a>

Before setting up an API method, verify the following:
+ You must have the method available in API Gateway. Follow the instructions in [Tutorial: Create a REST API with an HTTP non-proxy integration](api-gateway-create-api-step-by-step.md).
+ If you want the method to communicate with a Lambda function, you must have already created the Lambda invocation role and Lambda execution role in IAM. You must also have created the Lambda function with which your method will communicate in AWS Lambda. To create the roles and function, use the instructions in [Create a Lambda function for Lambda non-proxy integration](getting-started-lambda-non-proxy-integration.md#getting-started-new-lambda) of the [Choose an AWS Lambda integration tutorial](getting-started-with-lambda-integration.md). 
+ If you want the method to communicate with an HTTP or HTTP proxy integration, you must have already created, and have access to, the HTTP endpoint URL with which your method will communicate.
+  Verify that your certificates for HTTP and HTTP proxy endpoints are supported by API Gateway. For details see [API Gateway-supported certificate authorities for HTTP and HTTP proxy integrations in API Gateway](api-gateway-supported-certificate-authorities-for-http-endpoints.md). 

**Topics**
+ [Prerequisites](#method-setting-prerequisites)
+ [Set up a method request in API Gateway](api-gateway-method-settings-method-request.md)
+ [Set up a method response in API Gateway](api-gateway-method-settings-method-response.md)
+ [Set up a method using the API Gateway console](how-to-set-up-method-using-console.md)

# Set up a method request in API Gateway
<a name="api-gateway-method-settings-method-request"></a>

Setting up a method request involves performing the following tasks, after creating a [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource:

1.  Creating a new API or choosing an existing API [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) entity. 

1.  Creating an API [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) resource that is a specific HTTP verb on the new or chosen API `Resource`. This task can be further divided into the following sub tasks:
   +  Adding an HTTP method to the method request
   +  Configuring request parameters
   +  Defining a model for the request body
   +  Enacting an authorization scheme
   +  Enabling request validation 

You can perform these tasks using the following methods: 
+  [API Gateway console](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console)
+  AWS CLI commands ([create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) and [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html))
+  AWS SDK functions (for example, in Node.js, [createResource](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#createResource-property) and [putMethod](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/APIGateway.html#putMethod-property))
+  API Gateway REST API ([resource:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateResource.html) and [method:put](https://docs.aws.amazon.com/apigateway/latest/api/API_PutMethod.html)).

**Topics**
+ [Set up API resources](#setup-method-resources)
+ [Set up an HTTP method](#setup-method-add-http-method)
+ [Set up method request parameters](#setup-method-request-parameters)
+ [Set up a method request model](#setup-method-request-model)
+ [Set up method request authorization](#setup-method-request-authorization)
+ [Set up method request validation](#setup-method-request-validation)

## Set up API resources
<a name="setup-method-resources"></a>

In an API Gateway API, you expose addressable resources as a tree of API [Resources](https://docs.aws.amazon.com/apigateway/latest/api/API_GetResources.html) entities, with the root resource (`/`) at the top of the hierarchy. The root resource is relative to the API's base URL, which consists of the API endpoint and a stage name. In the API Gateway console, this base URI is referred to as the **Invoke URI** and is displayed in the API's stage editor after the API is deployed. 

The API endpoint can be a default host name or a custom domain name. The default host name is of the following format:

```
{api-id}.execute-api.{region}.amazonaws.com
```

In this format, the *\$1api-id\$1* represents the API identifier that is generated by API Gateway. The `{region}` variable represents the AWS Region (for example, `us-east-1`) that you chose when creating the API. A custom domain name is any user-friendly name under a valid internet domain. For example, if you have registered an internet domain of `example.com`, any of `*.example.com` is a valid custom domain name. For more information, see [create a custom domain name](how-to-custom-domains.md). 

For the [PetStore sample API](api-gateway-create-api-from-example.md), the root resource (`/`) exposes the pet store. The `/pets` resource represents the collection of pets available in the pet store. The `/pets/{petId}` exposes an individual pet of a given identifier (`petId`). The path parameter of `{petId}` is part of the request parameters. 

To set up an API resource, you choose an existing resource as its parent and then create the child resource under this parent resource. You start with the root resource as a parent, add a resource to this parent, add another resource to this child resource as the new parent, and so on, to its parent identifier. Then you add the named resource to the parent. 

The following [get-resources](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-resources.html) command retrieves all the resources of an API:

```
aws apigateway get-resources --rest-api-id apiId
```

For the PetStore sample API, the output looks like the following:

```
{
    "items": [
        {
            "path": "/pets", 
            "resourceMethods": {
                "GET": {}
            }, 
            "id": "6sxz2j", 
            "pathPart": "pets", 
            "parentId": "svzr2028x8"
        }, 
        {
            "path": "/pets/{petId}", 
            "resourceMethods": {
                "GET": {}
            }, 
            "id": "rjkmth", 
            "pathPart": "{petId}", 
            "parentId": "6sxz2j"
        }, 
        {
            "path": "/", 
            "id": "svzr2028x8"
        }
    ]
}
```

Each item lists the identifiers of the resource (`id`) and, except for the root resource, its immediate parent (`parentId`), as well as the resource name (`pathPart`). The root resource is special in that it does not have any parent. After choosing a resource as the parent, use the following command to add a child resource: 

```
aws apigateway create-resource --rest-api-id apiId \
    --parent-id parentId \
    --path-part resourceName
```

For example, to add pet food for sale on the PetStore website, use the following command:

```
aws apigateway create-resource --rest-api-id a1b2c3 \
    --parent-id svzr2028x8 \
    --path-part food
```

The output will look like the following:

```
{
    "path": "/food", 
    "pathPart": "food", 
    "id": "xdsvhp", 
    "parentId": "svzr2028x8"
}
```

### Use a proxy resource to streamline API setup
<a name="api-gateway-proxy-resource"></a>

As business grows, the PetStore owner may decide to add food, toys, and other pet-related items for sale. To support this, you can add `/food`, `/toys`, and other resources under the root resource. Under each sale category, you may also want to add more resources, such as `/food/{type}/{item}`, `/toys/{type}/{item}`, etc. This can get tedious. If you decide to add a middle layer `{subtype}` to the resource paths to change the path hierarchy into `/food/{type}/{subtype}/{item}`, `/toys/{type}/{subtype}/{item}`, etc., the changes will break the existing API set up. To avoid this, you can use an API Gateway [proxy resource](api-gateway-set-up-simple-proxy.md) to expose a set of API resources all at once.

API Gateway defines a proxy resource as a placeholder for a resource to be specified when the request is submitted. A proxy resource is expressed by a special path parameter of `{proxy+}`, often referred to as a greedy path parameter. The `+` sign indicates whichever child resources are appended to it. The `/parent/{proxy+}` placeholder stands for any resource matching the path pattern of `/parent/*`. You can use any string for the greedy path parameter name.

The following [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) command creates a proxy resource under the root (`/{proxy+}`):

```
aws apigateway create-resource --rest-api-id apiId \
    --parent-id rootResourceId \
    --path-part {proxy+}
```

The output will look like the following: 

```
{
    "path": "/{proxy+}", 
    "pathPart": "{proxy+}", 
    "id": "234jdr", 
    "parentId": "svzr2028x8"
}
```

For the `PetStore` API example, you can use `/{proxy+}` to represent both the `/pets` and `/pets/{petId}`. This proxy resource can also reference any other (existing or to-be-added) resources, such as `/food/{type}/{item}`, `/toys/{type}/{item}`, etc., or `/food/{type}/{subtype}/{item}`, `/toys/{type}/{subtype}/{item}`, etc. The backend developer determines the resource hierarchy and the client developer is responsible for understanding it. API Gateway simply passes whatever the client submitted to the backend. 

An API can have more than one proxy resource. For example, the following proxy resources are allowed within an API, assuming `/parent/{proxy+}` is not the same parent as `/parent/{child}/{proxy+}`.

```
/{proxy+}
/parent/{proxy+}
/parent/{child}/{proxy+}
```

When a proxy resource has non-proxy siblings, the sibling resources are excluded from the representation of the proxy resource. For the preceding examples, `/{proxy+}` refers to any resources under the root resource except for the `/parent[/*]` resources. In other words, a method request against a specific resource takes precedence over a method request against a generic resource at the same level of the resource hierarchy.

The following table shows how API Gateway routes requests to the following resources for the `prod` stage of an API.

```
ANY /{proxy+}
GET /pets/{proxy+}
GET /pets/dog
```


| Request | Selected route | Explanation | 
| --- | --- | --- | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/pets/dog`  |  `GET /pets/dog`  |  The request fully matches this resource.  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/pets/cats`  |  `GET /pets/{proxy+}`  |  The `/pets/{proxy+}` greedy path variable catches this request.  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/prod/animals`  |  `GET /{proxy+}`  |  The `/{proxy+}` greedy path variable catches this request.  | 

A proxy resource cannot have any child resource. Any API resource after `{proxy+}` is redundant and ambiguous. The following proxy resources are not allowed within an API.

```
/{proxy+}/child
/parent/{proxy+}/{child}
/parent/{child}/{proxy+}/{grandchild+}
```

## Set up an HTTP method
<a name="setup-method-add-http-method"></a>

An API method request is encapsulated by the API Gateway [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) resource. To set up the method request, you must first instantiate the `Method` resource, setting at least an HTTP method and an authorization type on the method. 

Closely associated with the proxy resource, API Gateway supports an HTTP method of `ANY`. This `ANY` method represents any HTTP method that is to be supplied at run time. It allows you to use a single API method setup for all of the supported HTTP methods of `DELETE`, `GET`, `HEAD`, `OPTIONS`, `PATCH`, `POST`, and `PUT`. 

You can set up the `ANY` method on a non-proxy resource as well. Combining the `ANY` method with a proxy resource, you get a single API method setup for all of the supported HTTP methods against any resources of an API. Furthermore, the backend can evolve without breaking the existing API setup. 

 Before setting up an API method, consider who can call the method. Set the authorization type according to your plan. For open access, set it to `NONE`. To use IAM permissions, set the authorization type to `AWS_IAM`. To use a Lambda authorizer function, set this property to `CUSTOM`. To use an Amazon Cognito user pool, set the authorization type to `COGNITO_USER_POOLS`. 

The following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command creates a method request for the `ANY` verb using IAM permissions to control its access. 

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method ANY \
    --authorization-type AWS_IAM
```

To create an API method request with a different authorization type, see [Set up method request authorization](#setup-method-request-authorization).

## Set up method request parameters
<a name="setup-method-request-parameters"></a>

Method request parameters are a way for a client to provide input data or execution context necessary to complete the method request. A method parameter can be a path parameter, a header, or a query string parameter. As part of method request setup, you must declare required request parameters to make them available for the client. For non-proxy integration, you can translate these request parameters to a form that is compatible with the backend requirement. 

For example, for the `GET /pets/{petId}` method request, the `{petId}` path variable is a required request parameter. You can declare this path parameter when calling the `put-method` command of the AWS CLI. The following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command creates a method with a required path parameter:

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id rjkmth \
    --http-method GET \
    --authorization-type "NONE" \
    --request-parameters method.request.path.petId=true
```

If a parameter is not required, you can set it to `false` in `request-parameters`. For example, if the `GET /pets` method uses an optional query string parameter of `type`, and an optional header parameter of `age`, you can declare them using the following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command:

```
aws apigateway put-method --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method GET \
    --authorization-type "NONE" \
    --request-parameters method.request.querystring.type=false,method.request.header.age=false
```

Instead of this abbreviated form, you can use a JSON string to set the `request-parameters` value:

```
'{"method.request.querystring.type":false,"method.request.header.age":false}'
```

With this setup, the client can query pets by type: 

```
GET /pets?type=dog
```

 And the client can query dogs who are puppies as follows:

```
GET /pets?type=dog
age:puppy
```

For information on how to map method request parameters to integration request parameters, see [Integrations for REST APIs in API Gateway](how-to-integration-settings.md).

## Set up a method request model
<a name="setup-method-request-model"></a>

For an API method that can take input data in a payload, you can use a model. A model is expressed in a [JSON schema draft 4](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04) and describes the data structure of the request body. With a model, a client can determine how to construct a method request payload as input. More importantly, API Gateway uses the model to [validate a request](api-gateway-method-request-validation.md), [generate an SDK](how-to-generate-sdk.md), and initialize a mapping template for setting up the integration in the API Gateway console. For information about how to create a [model](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html), see [Understanding data models](models-mappings-models.md). 

Depending on the content types, a method payload can have different formats. A model is indexed against the media type of the applied payload. API Gateway uses the `Content-Type` request header to determine the content type. To set up method request models, add key-value pairs of the `"media-type":"model-name"` format to the `requestModels` map when calling the AWS CLI `put-method` command. 

To use the same model regardless of the content type, specify `$default` as the key.

For example, to set a model on the JSON payload of the `POST /pets` method request of the PetStore example API, you can use the following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command:

```
aws apigateway put-method \
    --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method POST \
    --authorization-type "NONE" \
    --request-models '{"application/json":"petModel"}'
```

Here, `petModel` is the `name` property value of a [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) resource describing a pet. The actual schema definition is expressed as a JSON string value of the [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html#schema](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html#schema) property of the `Model` resource. 

 In a Java, or other strongly typed SDK, of the API, the input data is cast as the `petModel` class derived from the schema definition. With the request model, the input data in the generated SDK is cast into the `Empty` class, which is derived from the default `Empty` model. In this case, the client cannot instantiate the correct data class to provide the required input. 



## Set up method request authorization
<a name="setup-method-request-authorization"></a>



 To control who can call the API method, you can configure the [authorization type](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizationType) on the method. You can use this type to enact one of the supported authorizers, including IAM roles and policies (`AWS_IAM`), an Amazon Cognito user pool (`COGNITO_USER_POOLS`), or a Lambda authorizer (`CUSTOM`).

To use IAM permissions to authorize access to the API method, set the `authorization-type` input property to **AWS\$1IAM**. When you set this option, API Gateway verifies the caller's signature on the request based on the caller's credentials. If the verified user has permission to call the method, it accepts the request. Otherwise, it rejects the request and the caller receives an unauthorized error response. The call to the method doesn't succeed unless the caller has permission to invoke the API method. The following IAM policy grants permission to the caller to call any API methods created within the same AWS account: 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": "arn:aws:execute-api:*:*:*"
        }
    ]
}
```

------

For more information, see [Control access to a REST API with IAM permissions](permissions.md).

Currently, you can only grant this policy to the users, groups, and roles within the API owner's AWS account. Users from a different AWS account can call the API methods only if allowed to assume a role within the API owner's AWS account with the necessary permissions to call the `execute-api:Invoke` action. For information on cross-account permissions, see [Using IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html). 

You can use AWS CLI, an AWS SDK, or a REST API client, such as [Postman](https://www.postman.com/), which implements [Signature Version 4 (SigV4) signing](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html). 

To use a Lambda authorizer to authorize access to the API method, set the `authorization-type` input property to `CUSTOM` and set the [https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId) input property to the [https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id) property value of a Lambda authorizer that already exists. The referenced Lambda authorizer can be of the `TOKEN` or `REQUEST` type. For information about creating a Lambda authorizer, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).

To use an Amazon Cognito user pool to authorize access to the API method, set the `authorization-type` input property to `COGNITO_USER_POOLS` and set the [https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizerId) input property to the [https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html#id) property value of the `COGNITO_USER_POOLS` authorizer that was already created. For information about creating an Amazon Cognito user pool authorizer, see [Control access to REST APIs using Amazon Cognito user pools as an authorizer](apigateway-integrate-with-cognito.md).

## Set up method request validation
<a name="setup-method-request-validation"></a>

You can enable request validation when setting up an API method request. You need to first create a [request validator](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html). The following [create-request-validator](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-request-validator.html) command creates a body-only request validator. 

```
aws apigateway create-request-validator \
    --rest-api-id 7zw9uyk9kl \
    --name bodyOnlyValidator \
    --validate-request-body  \
    --no-validate-request-parameters
```

The output will look like the following:

```
{
    "validateRequestParameters": false, 
    "validateRequestBody": true, 
    "id": "jgpyy6", 
    "name": "bodyOnlyValidator"
}
```

You can use this request validator, to use request validation as part of the method request setup. The following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command creates a method request that requires the incoming request body to match the `PetModel` and has two request parameter that aren't required: 

```
aws apigateway put-method \
    --rest-api-id 7zw9uyk9kl \
    --resource-id xdsvhp \
    --http-method PUT \
    --authorization-type "NONE" \
    --request-parameters '{"method.request.querystring.type": false, "method.request.querystring.page":false}' \ 
    --request-models '{"application/json":"petModel"}' \
    --request-validator-id jgpyy6
```

To include a request parameter in the request validation, you must set `validateRequestParameters` to `true` for the request validator, and set the specific request parameter to `true` in the `put-method` command.

# Set up a method response in API Gateway
<a name="api-gateway-method-settings-method-response"></a>

An API method response encapsulates the output of an API method request that the client will receive. The output data includes an HTTP status code, some headers, and possibly a body. 

With non-proxy integrations, the specified response parameters and body can be mapped from the associated integration response data or can be assigned certain static values according to mappings. These mappings are specified in the integration response. The mapping can be an identical transformation that passes the integration response through as-is.

With a proxy integration, API Gateway passes the backend response through to the method response automatically. There is no need for you to set up the API method response. However, with the Lambda proxy integration, the Lambda function must return a result of [this output format](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format) for API Gateway to successfully map the integration response to a method response. 

Programmatically, the method response setup amounts to creating a [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) resource of API Gateway and setting the properties of [statusCode](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#statusCode), [responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters), and [responseModels](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseModels). 

When setting status codes for an API method, you should choose one as the default to handle any integration response of an unanticipated status code. It is reasonable to set `500` as the default because this amounts to casting otherwise unmapped responses as a server-side error. For instructional reasons, the API Gateway console sets the `200` response as the default. But you can reset it to the `500` response. 

To set up a method response, you must have created the method request. 

## Set up method response status code
<a name="setup-method-response-status-code"></a>

The status code of a method response defines a type of response. For example, responses of 200, 400, and 500 indicate successful, client-side error and server-side error responses, respectively. 

To set up a method response status code, set the [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#statusCode](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#statusCode) property to an HTTP status code. The following [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) command creates `200` method response.

```
aws apigateway put-method-response \
    --rest-api-id vaz7da96z6 \ 
    --resource-id 6sxz2j \
    --http-method GET \
    --status-code 200
```

## Set up method response parameters
<a name="setup-method-response-parameters"></a>

Method response parameters define which headers the client receives in response to the associated method request. Response parameters also specify a target to which API Gateway maps an integration response parameter, according to mappings prescribed in the API method's integration response. 

To set up the method response parameters, add to the [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters) map of `MethodResponse` key-value pairs of the `"{parameter-name}":"{boolean}"` format. The following [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) command sets the `my-header` header.

```
aws apigateway put-method-response \
        --rest-api-id vaz7da96z6 \
        --resource-id 6sxz2j \
        --http-method GET \
        --status-code 200  \
        --response-parameters method.response.header.my-header=false
```

## Set up method response models
<a name="setup-method-response-models"></a>

 

 A method response model defines a format of the method response body. Setting up a method response model is necessary when you generate a strongly typed SDK for the API. It ensures that the output is cast into an appropriate class in Java or Objective-C. In other cases, setting a model is optional.

Before setting up the response model, you must first create the model in API Gateway. To do so, you can call the `[create-model](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-model.html)` command. The following [create-model](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-model.html) command creates `PetStorePet` model to describe the body of the response to the `GET /pets/{petId}` method request.

```
aws apigateway create-model \
    --rest-api-id vaz7da96z6 \
    --content-type application/json \
    --name PetStorePet \
    --schema '{ \
                  "$schema": "http://json-schema.org/draft-04/schema#", \
                  "title": "PetStorePet", \
                  "type": "object", \
                  "properties": { \
                    "id": { "type": "number" }, \
                    "type": { "type": "string" }, \
                    "price": { "type": "number" } \
                  } \
              }'
```

The result is created as an API Gateway [https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) resource.

To set up the method response models to define the payload format, add the "application/json":"PetStorePet" key-value pair to the [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseModels](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseModels) map of [https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) resource. The following [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) command creates a method response that uses a response model to define the payload format: 

```
aws apigateway put-method-response \
    --rest-api-id vaz7da96z6 \
    --resource-id 6sxz2j \
    --http-method GET \
    --status-code 200  \
    --response-parameters method.response.header.my-header=false \
    --response-models '{"application/json":"PetStorePet"}'
```

# Set up a method using the API Gateway console
<a name="how-to-set-up-method-using-console"></a>

When you create a method using the REST API console, you configure both the integration request and the method request. By default, API Gateway creates the `200` method response for your method.

The following instructions show how to edit the method request settings and how to create additional method responses for your method.

**Topics**
+ [Edit an API Gateway method request in the API Gateway console](#how-to-method-settings-callers-console)
+ [Set up an API Gateway method response using the API Gateway console](#how-to-method-response-settings-console)

## Edit an API Gateway method request in the API Gateway console
<a name="how-to-method-settings-callers-console"></a>

 These instructions assume you have already created your method request. For more information on how to create a method, see [Set up an API integration request using the API Gateway console](how-to-method-settings-console.md).

1. In the **Resources** pane, choose your method, and then choose the **Method request** tab. 

1. In the **Method request settings** section, choose **Edit**.

1. For **Authorization**, select an available authorizer. 

   1. To enable open access to the method for any user, select **None**. This step can be skipped if the default setting has not been changed.

   1. To use IAM permissions to control the client access to the method, select `AWS_IAM`. With this choice, only users of the IAM roles with the correct IAM policy attached are allowed to call this method. 

      To create the IAM role, specify an access policy with a format like the following: 

------
#### [ JSON ]

****  

      ```
      {
        "Version":"2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "execute-api:Invoke"
            ],
            "Resource": [
              "arn:aws:execute-api:us-east-1:111111111111:aaabbb/*/GET/"
            ]
          }
        ]
      }
      ```

------

      In this access policy, `arn:aws:execute-api:us-east-1:111111111111:aaabbb/*/GET/` is the ARN of your method. You can find the ARN of your method by selecting the method on the **Resources** page. For more information about setting the IAM permissions, see [Control access to a REST API with IAM permissions](permissions.md). 

      To create the IAM role, you can adapt the instructions in the following tutorial, [Create a Lambda function for Lambda non-proxy integration](getting-started-lambda-non-proxy-integration.md#getting-started-new-lambda). 

   1.  To use a Lambda authorizer, select a token or a request authorizer. Create the Lambda authorizer to have this choice displayed in the dropdown menu. For information on how to create a Lambda authorizer, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md). 

   1.  To use an Amazon Cognito user pool, choose an available user pool under **Cognito user pool authorizers**. Create a user pool in Amazon Cognito and an Amazon Cognito user pool authorizer in API Gateway to have this choice displayed in the dropdown menu. For information on how to create an Amazon Cognito user pool authorizer, see [Control access to REST APIs using Amazon Cognito user pools as an authorizer](apigateway-integrate-with-cognito.md). 

1.  To specify request validation, select a value from the **Request Validator** dropdown menu. To turn off request validation, select **None**. For more information about each option, see [Request validation for REST APIs in API Gateway](api-gateway-method-request-validation.md). 

1. Select **API key required** to require an API key. When enabled, API keys are used in [usage plans](api-gateway-api-usage-plans.md) to throttle client traffic. 

1. (Optional) To assign an operation name in a Java SDK of this API, generated by API Gateway, for **Operation name**, enter a name. For example, for the method request of `GET /pets/{petId}`, the corresponding Java SDK operation name is, by default ,`GetPetsPetId`. This name is constructed from the method's HTTP verb (`GET`) and the resource path variable names (`Pets` and `PetId`). If you set the operation name as `getPetById`, the SDK operation name becomes `GetPetById`.

1. To add a query string parameter to the method, do the following:

   1. Choose **URL Query string parameters**, and then choose **Add query string**.

   1. For **Name**, enter the name of the query string parameter.

   1. Select **Required** if the newly created query string parameter is to be used for request validation. For more information about the request validation, see [Request validation for REST APIs in API Gateway](api-gateway-method-request-validation.md).

   1. Select **Caching** if the newly created query string parameter is to be used as part of a caching key. For more information about caching, see [Use method or integration parameters as cache keys to index cached responses](api-gateway-caching.md#enable-api-gateway-cache-keys).

   To remove the query string parameter, choose **Remove**. 

1. To add a header parameter to the method, do the following:

   1. Choose **HTTP request headers**, and then choose **Add header**.

   1. For **Name**, enter the name of the header.

   1. Select **Required** if the newly created header is to be used for request validation. For more information about the request validation, see [Request validation for REST APIs in API Gateway](api-gateway-method-request-validation.md).

   1. Select **Caching** if the newly created header is to be used as part of a caching key. For more information about caching, see [Use method or integration parameters as cache keys to index cached responses](api-gateway-caching.md#enable-api-gateway-cache-keys).

   To remove the header, choose **Remove**. 

1.  To declare the payload format of a method request with the `POST`, `PUT`, or `PATCH` HTTP verb, choose **Request body**, and do the following: 

   1. Choose **Add model**.

   1. For **Content-type**, enter a MIME-type (for example, `application/json`).

   1. For **Model**, select a model from the dropdown menu. The currently available models for the API include the default `Empty` and `Error` models as well as any models you have created and added to the [Models](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) collection of the API. For more information about creating a model, see [Data models for REST APIs](models-mappings-models.md). 
**Note**  
 The model is useful to inform the client of the expected data format of a payload. It is helpful to generate a skeletal mapping template. It is important to generate a strongly typed SDK of the API in such languages as Java, C\$1, Objective-C, and Swift. It is only required if request validation is enabled against the payload. 

1. Choose **Save**.

## Set up an API Gateway method response using the API Gateway console
<a name="how-to-method-response-settings-console"></a>

 An API method can have one or more responses. Each response is indexed by its HTTP status code. By default, the API Gateway console adds `200` response to the method responses. You can modify it, for example, to have the method return `201` instead. You can add other responses, for example, `409` for access denial and `500` for uninitialized stage variables used. 

 To use the API Gateway console to modify, delete, or add a response to an API method, follow these instructions.

1. In the **Resources** pane, choose your method, and then choose the **Method response** tab. You might need to choose the right arrow button to show the tab.

1. In the **Method response settings** section, choose **Create response**.

1. For **HTTP status code**, enter an HTTP status code such as `200`, `400`, or `500`.

    When a backend-returned response does not have a corresponding method response defined, API Gateway fails to return the response to the client. Instead, it returns a `500 Internal server error` error response. 

1. Choose **Add header**.

1.  For **Header name**, enter a name.

    To return a header from the backend to the client, add the header in the method response. 

1.  Choose **Add model** to define a format of the method response body.

   Enter the media type of the response payload for **Content type** and choose a model from the **Models** dropdown menu.

1. Choose **Save**.

To modify an existing response, navigate to your method response, and then choose **Edit**. To change the **HTTP status code**, choose **Delete** and create a new method response.

For every response returned from the backend, you must have a compatible response configured as the method response. However, the configuring method response headers and payload model are optional unless you map the result from the backend to the method response before returning to the client. Also, a method response payload model is important if you are generating a strongly typed SDK for your API.

# Control and manage access to REST APIs in API Gateway
<a name="apigateway-control-access-to-api"></a>

API Gateway supports multiple mechanisms for controlling and managing access to your API.

You can use the following mechanisms for authentication and authorization:
+ **Resource policies** let you create resource-based policies to allow or deny access to your APIs and methods from specified source IP addresses or VPC endpoints. For more information, see [Control access to a REST API with API Gateway resource policies](apigateway-resource-policies.md).
+ **Standard AWS IAM roles and policies** offer flexible and robust access controls that can be applied to an entire API or individual methods. IAM roles and policies can be used for controlling who can create and manage your APIs, as well as who can invoke them. For more information, see [Control access to a REST API with IAM permissions](permissions.md).
+ **IAM tags** can be used together with IAM policies to control access. For more information, see [Using tags to control access to API Gateway REST API resources](apigateway-tagging-iam-policy.md).
+ **Endpoint policies for interface VPC endpoints** allow you to attach IAM resource policies to interface VPC endpoints to improve the security of your [private APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html). For more information, see [Use VPC endpoint policies for private APIs in API Gateway](apigateway-vpc-endpoint-policies.md).
+ **Lambda authorizers** are Lambda functions that control access to REST API methods using bearer token authentication—as well as information described by headers, paths, query strings, stage variables, or context variables request parameters. Lambda authorizers are used to control who can invoke REST API methods. For more information, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).
+ **Amazon Cognito user pools** let you create customizable authentication and authorization solutions for your REST APIs. Amazon Cognito user pools are used to control who can invoke REST API methods. For more information, see [Control access to REST APIs using Amazon Cognito user pools as an authorizer](apigateway-integrate-with-cognito.md).

You can use the following mechanisms for performing other tasks related to access control:
+ **Cross-origin resource sharing (CORS)** lets you control how your REST API responds to cross-domain resource requests. For more information, see [CORS for REST APIs in API Gateway](how-to-cors.md).
+ **Client-side SSL certificates** can be used to verify that HTTP requests to your backend system are from API Gateway. For more information, see [Generate and configure an SSL certificate for backend authentication in API Gateway](getting-started-client-side-ssl-authentication.md).
+ **AWS WAF** can be used to protect your API Gateway API from common web exploits. For more information, see [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md).

You can use the following mechanisms for tracking and limiting the access that you have granted to authorized clients:
+ **Usage plans** let you provide **API keys** to your customers—and then track and limit usage of your API stages and methods for each API key. For more information, see [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md).

# Control access to a REST API with API Gateway resource policies
<a name="apigateway-resource-policies"></a>

Amazon API Gateway *resource policies* are JSON policy documents that you attach to an API to control whether a specified principal (typically an IAM role or group) can invoke the API. You can use API Gateway resource policies to allow your API to be securely invoked by:
+ Users from a specified AWS account.
+ Specified source IP address ranges or CIDR blocks.
+ Specified virtual private clouds (VPCs) or VPC endpoints (in any account).

You can attach a resource policy for any API endpoint type in API Gateway by using the AWS Management Console, AWS CLI, or AWS SDKs. For [private APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-apis.html), you can use resource policies together with VPC endpoint policies to control which principals have access to which resources and actions. For more information, see [Use VPC endpoint policies for private APIs in API Gateway](apigateway-vpc-endpoint-policies.md).

 API Gateway resource policies are different from IAM identity-based policies. IAM identity-based policies are attached to IAM users, groups, or roles and define what actions those identities are capable of doing on which resources. API Gateway resource policies are attached to resources. You can use API Gateway resource policies together with IAM policies. For more information, see [Identity-Based Policies and Resource-Based Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html).

**Topics**
+ [Access policy language overview for Amazon API Gateway](apigateway-control-access-policy-language-overview.md)
+ [How API Gateway resource policies affect authorization workflow](apigateway-authorization-flow.md)
+ [API Gateway resource policy examples](apigateway-resource-policies-examples.md)
+ [Create and attach an API Gateway resource policy to an API](apigateway-resource-policies-create-attach.md)
+ [AWS condition keys that can be used in API Gateway resource policies](apigateway-resource-policies-aws-condition-keys.md)

# Access policy language overview for Amazon API Gateway
<a name="apigateway-control-access-policy-language-overview"></a>

This page describes the basic elements used in Amazon API Gateway resource policies.

Resource policies are specified using the same syntax as IAM policies. For complete policy language information, see [ Overview of IAM Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) and [AWS Identity and Access Management Policy Reference](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html) in the *IAM User Guide*.

For information about how an AWS service decides whether a given request should be allowed or denied, see [Determining Whether a Request is Allowed or Denied](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow).

## Common elements in an access policy
<a name="apigateway-common-elements-in-an-access-policy"></a>

In its most basic sense, a resource policy contains the following elements:
+ **Resources** – APIs are the Amazon API Gateway resources for which you can allow or deny permissions. In a policy, you use the Amazon Resource Name (ARN) to identify the resource. You can also use abbreviated syntax, which API Gateway automatically expands to the full ARN when you save a resource policy. To learn more, see [API Gateway resource policy examples](apigateway-resource-policies-examples.md).

  For the format of the full `Resource` element, see [Resource format of permissions for executing API in API Gateway](api-gateway-control-access-using-iam-policies-to-invoke-api.md#api-gateway-iam-policy-resource-format-for-executing-api).
+ **Actions** – For each resource, Amazon API Gateway supports a set of operations. You identify resource operations that you will allow (or deny) by using action keywords.

  For example, the `execute-api:Invoke` permission will allow the user permission to invoke an API upon a client request.

  For the format of the `Action` element, see [Action format of permissions for executing API in API Gateway](api-gateway-control-access-using-iam-policies-to-invoke-api.md#api-gateway-iam-policy-action-format-for-executing-api).
+ **Effect** – What the effect is when the user requests the specific action—this can be either `Allow` or `Deny`. You can also explicitly deny access to a resource, which you might do in order to make sure that a user cannot access it, even if a different policy grants access. 
**Note**  
"Implicit deny" is the same thing as "deny by default".  
An "implicit deny" is different from an "explicit deny". For more information, see [The Difference Between Denying by Default and Explicit Deny](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#AccessPolicyLanguage_Interplay).
+ **Principal** – The account or user allowed access to the actions and resources in the statement. In a resource policy, the principal is the user or account who receives this permission.

The following example resource policy shows the previous common policy elements. The policy grants access to the API under the specified *account-id* in the specified *region* to any user whose source IP address is in the address block *123.4.5.6/24*. The policy denies all access to the API if the user's source IP is not within the range.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:*"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "123.4.5.6/24"
                }
            }
        }
    ]
}
```

------

# How API Gateway resource policies affect authorization workflow
<a name="apigateway-authorization-flow"></a>

When API Gateway evaluates the resource policy attached to your API, the result is affected by the authentication type that you have defined for the API, as illustrated in the flowcharts in the following sections.

**Topics**
+ [API Gateway resource policy only](#apigateway-authorization-flow-resource-policy-only)
+ [Lambda authorizer and resource policy](#apigateway-authorization-flow-lambda)
+ [IAM authentication and resource policy](#apigateway-authorization-flow-iam)
+ [Amazon Cognito authentication and resource policy](#apigateway-authorization-flow-cognito)
+ [Policy evaluation outcome tables](#apigateway-resource-policies-iam-policies-interaction)

## API Gateway resource policy only
<a name="apigateway-authorization-flow-resource-policy-only"></a>

In this workflow, an API Gateway resource policy is attached to the API, but no authentication type is defined for the API. Evaluation of the policy involves seeking an explicit allow based on the inbound criteria of the caller. An implicit denial or any explicit denial results in denying the caller.

![\[Authorization flow of a resource policy only.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/apigateway-auth-resource-policy-only.png)


The following is an example of such a resource policy.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:api-id/",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}
```

------

## Lambda authorizer and resource policy
<a name="apigateway-authorization-flow-lambda"></a>

In this workflow, a Lambda authorizer is configured for the API in addition to a resource policy. The resource policy is evaluated in two phases. Before calling the Lambda authorizer, API Gateway first evaluates the policy and checks for any explicit denials. If found, the caller is denied access immediately. Otherwise, the Lambda authorizer is called, and it returns a [policy document](api-gateway-lambda-authorizer-output.md), which is evaluated in conjunction with the resource policy. If your authorizer uses caching, API Gateway might return the cached policy document. The result is determined based on [Table A](#apigateway-resource-policies-iam-policies-interaction).

The following example resource policy allows calls only from the VPC endpoint whose VPC endpoint ID is `vpce-1a2b3c4d`. During the "pre-auth" evaluation, only the calls coming from the VPC endpoint indicated in the example are allowed to move forward and evaluate the Lambda authorizer. All remaining calls are blocked. This authorization workflow is the same if you use a custom domain name for a private API.

![\[Authorization flow for a resource policy and a Lambda authorizer.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/apigateway-auth-lambda-resource-policy.png)


------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:us-east-1:111111111111:api-id/"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-1a2b3c4d"
                }
            }
        }
    ]
}
```

------

## IAM authentication and resource policy
<a name="apigateway-authorization-flow-iam"></a>

In this workflow, you configure IAM authentication for the API in addition to a resource policy. After you authenticate the user with the IAM service, the API evaluates both the policies attached to the user and the resource policy. The outcome varies based on whether the caller is in the same AWS account or a separate AWS account, from the API owner. 

If the caller and API owner are from separate accounts, both the IAM policies and the resource policy explicitly allow the caller to proceed. For more information, see [Table B](#apigateway-resource-policies-iam-policies-interaction). 

However, if the caller and the API owner are in the same AWS account, then either the IAM user policies or the resource policy must explicitly allow the caller to proceed. For more information, see [Table A](#apigateway-resource-policies-iam-policies-interaction).

![\[Authorization flow for a resource policy and IAM authentication.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/apigateway-auth-iam-resource-policy.png)


The following is an example of a cross-account resource policy. Assuming the IAM policy contains an allow effect, this resource policy allows calls only from the VPC whose VPC ID is `vpc-2f09a348`. For more information, see [Table B](#apigateway-resource-policies-iam-policies-interaction).

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:us-east-1:111111111111:api-id/"
            ],
            "Condition" : {
                "StringEquals": {
                    "aws:SourceVpc": "vpc-2f09a348"
                    }
            }
        }
    ]
}
```

------

## Amazon Cognito authentication and resource policy
<a name="apigateway-authorization-flow-cognito"></a>

In this workflow, an [Amazon Cognito user pool](apigateway-integrate-with-cognito.md) is configured for the API in addition to a resource policy. API Gateway first attempts to authenticate the caller through Amazon Cognito. This is typically performed through a [JWT token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html) that is provided by the caller. If authentication is successful, the resource policy is evaluated independently, and an explicit allow is required. A deny or "neither allow or deny" results in a deny. The following is an example of a resource policy that might be used together with Amazon Cognito user pools.

![\[Authorization flow for a resource policy and a Amazon Cognito authorizer.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/apigateway-auth-cognito-resource-policy.png)


The following is an example of a resource policy that allows calls only from specified source IPs, assuming that the Amazon Cognito authentication token contains an allow. For more information, see [Table B](#apigateway-resource-policies-iam-policies-interaction).

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-east-1:111111111111:api-id/",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}
```

------

## Policy evaluation outcome tables
<a name="apigateway-resource-policies-iam-policies-interaction"></a>

Table A lists the resulting behavior when access to an API Gateway API is controlled by an IAM policy or a Lambda authorizer and an API Gateway resource policy, both of which are in the same AWS account.


| **IAM policy (or Lambda authorizer)** | **API Gateway resource policy** | **Resulting behavior** | 
| --- | --- | --- | 
| Allow | Allow | Allow | 
| Allow | Neither Allow nor Deny | Allow | 
| Allow | Deny | Explicit Deny | 
| Neither Allow nor Deny | Allow | Allow | 
| Neither Allow nor Deny | Neither Allow nor Deny | Implicit Deny | 
| Neither Allow nor Deny | Deny | Explicit Deny | 
| Deny | Allow | Explicit Deny | 
| Deny | Neither Allow nor Deny | Explicit Deny | 
| Deny | Deny | Explicit Deny | 

Table B lists the resulting behavior when access to an API Gateway API is controlled by an IAM policy or a Amazon Cognito user pools authorizer and an API Gateway resource policy, which are in different AWS accounts. If either is silent (neither allow nor deny), cross-account access is denied. This is because cross-account access requires that both the resource policy and the IAM policy or Amazon Cognito user pools authorizer explicitly grant access.


| **IAM policy (or Amazon Cognito user pools authorizer)** | **API Gateway resource policy** | **Resulting behavior** | 
| --- | --- | --- | 
| Allow | Allow | Allow | 
| Allow | Neither Allow nor Deny | Implicit Deny | 
| Allow | Deny | Explicit Deny | 
| Neither Allow nor Deny | Allow | Implicit Deny | 
| Neither Allow nor Deny | Neither Allow nor Deny | Implicit Deny | 
| Neither Allow nor Deny | Deny | Explicit Deny | 
| Deny | Allow | Explicit Deny | 
| Deny | Neither Allow nor Deny | Explicit Deny | 
| Deny | Deny | Explicit Deny | 

# API Gateway resource policy examples
<a name="apigateway-resource-policies-examples"></a>

This page presents a few examples of typical use cases for API Gateway resource policies.

The following example policies use a simplified syntax to specify the API resource. This simplified syntax is an abbreviated way that you can refer to an API resource, instead of specifying the full Amazon Resource Name (ARN). API Gateway converts the abbreviated syntax to the full ARN when you save the policy. For example, you can specify the resource `execute-api:/stage-name/GET/pets` in a resource policy. API Gateway converts the resource to `arn:aws:execute-api:us-east-2:123456789012:aabbccddee/stage-name/GET/pets` when you save the resource policy. API Gateway builds the full ARN by using the current Region, your AWS account ID, and the ID of the REST API that the resource policy is associated with. You can use `execute-api:/*` to represent all stages, methods, and paths in the current API. For information about access policy language, see [Access policy language overview for Amazon API Gateway](apigateway-control-access-policy-language-overview.md).

**Topics**
+ [Example: Allow roles in another AWS account to use an API](#apigateway-resource-policies-cross-account-example)
+ [Example: Deny API traffic based on source IP address or range](#apigateway-resource-policies-source-ip-address-example)
+ [Example: Deny API traffic based on source IP address or range when using a private API](#apigateway-resource-policies-source-ip-address-vpc-example)
+ [Example: Allow private API traffic based on source VPC or VPC endpoint](#apigateway-resource-policies-source-vpc-example)

## Example: Allow roles in another AWS account to use an API
<a name="apigateway-resource-policies-cross-account-example"></a>

The following example resource policy grants API access in one AWS account to two roles in a different AWS account via [Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html) (SigV4) or [Signature Version 4a](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html#how-sigv4a-works) (SigV4a) protocols. Specifically, the developer and the administrator role for the AWS account identified by `account-id-2` are granted the `execute-api:Invoke` action to execute the `GET` action on the `pets` resource (API) in your AWS account.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111122223333:role/developer",
                    "arn:aws:iam::111122223333:role/Admin"
                ]
            },
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/stage/GET/pets"
            ]
        }
    ]
}
```

------

## Example: Deny API traffic based on source IP address or range
<a name="apigateway-resource-policies-source-ip-address-example"></a>

The following example resource policy denies (blocks) incoming traffic to an API from two specified source IP address blocks.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
               "execute-api:/*"
            ],
            "Condition" : {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}
```

------

If you use any IAM user policies or API Gateway resource policies to control access to API Gateway or any API Gateway APIs, confirm that your policies are updated to include IPv6 address ranges. Policies that aren’t updated to handle IPv6 addresses might impact client’s access to API Gateway when they start using the dualstack endpoint. For more information, see [Using IPv6 addresses in IAM policies](api-ref.md#api-reference-service-endpoints-dualstack-iam).

## Example: Deny API traffic based on source IP address or range when using a private API
<a name="apigateway-resource-policies-source-ip-address-vpc-example"></a>

The following example resource policy denies (blocks) incoming traffic to a private API from two specified source IP address blocks. When using private APIs, the VPC endpoint for `execute-api` re-writes the original source IP address. The `aws:VpcSourceIp` condition filters the request against the original requester IP address.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
               "execute-api:/*"
            ],
            "Condition" : {
                "IpAddress": {
                    "aws:VpcSourceIp": ["192.0.2.0/24", "198.51.100.0/24"]
                }
            }
        }
    ]
}
```

------

## Example: Allow private API traffic based on source VPC or VPC endpoint
<a name="apigateway-resource-policies-source-vpc-example"></a>

The following example resource policies allow incoming traffic to a private API only from a specified virtual private cloud (VPC) or VPC endpoint.

This example resource policy specifies a source VPC:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                   "aws:SourceVpc": "vpc-1a2b3c4d"
                }
            }
        }
    ]
}
```

------

This example resource policy specifies a source VPC endpoint:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-1a2b3c4d"
                }
            }
        }
    ]
}
```

------

# Create and attach an API Gateway resource policy to an API
<a name="apigateway-resource-policies-create-attach"></a>

To allow a user to access your API by calling the API execution service, you must create an API Gateway resource policy and attach the policy to the API. When you attach a policy to your API, it applies the permissions in the policy to the methods in the API. If you update the resource policy, you'll need to deploy the API.

**Topics**
+ [Prerequisites](#apigateway-resource-policies-prerequisites)
+ [Attach a resource policy to an API Gateway API](#apigateway-resource-policies-create-attach-procedure)
+ [Troubleshoot your resource policy](#apigateway-resource-policies-troubleshoot)

## Prerequisites
<a name="apigateway-resource-policies-prerequisites"></a>

 To update an API Gateway resource policy, you'll need the `apigateway:UpdateRestApiPolicy` permission and the `apigateway:PATCH` permission.

For an edge-optimized or Regional API, you can attach your resource policy to your API as you create it, or after it has been deployed. For a private API, you can't deploy your API without a resource policy. For more information, see [Private REST APIs in API Gateway](apigateway-private-apis.md).

## Attach a resource policy to an API Gateway API
<a name="apigateway-resource-policies-create-attach-procedure"></a>

The following procedure shows you how to attach a resource policy to an API Gateway API.

------
#### [ AWS Management Console ]

**To attach a resource policy to an API Gateway API**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the main navigation pane, choose **Resource policy**.

1. Choose **Create policy**.

1. (Optional) Choose **Select a template** to generate an example policy.

   In the example policies, placeholders are enclosed in double curly braces (`"{{placeholder}}"`). Replace each of the placeholders, including the curly braces, with the necessary information.

1. If you don't use one of the template examples, enter your resource policy.

1. Choose **Save changes**.

If the API has been deployed previously in the API Gateway console, you'll need to redeploy it for the resource policy to take effect.

------
#### [ AWS CLI ]

To use the AWS CLI to create a new API and attach a resource policy to it, use the following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command:

```
aws apigateway create-rest-api \
    --name "api-name" \
    --policy "{\"jsonEscapedPolicyDocument\"}"
```

To use the AWS CLI to attach a resource policy to an existing API, use the following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command: 

```
aws apigateway update-rest-api \
    --rest-api-id api-id \
    --patch-operations op=replace,path=/policy,value='"{\"jsonEscapedPolicyDocument\"}"'
```

You can also attach your resource policy as a separate `policy.json` file and including it in your [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command. The following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command creates a new API with a resource policy:

```
aws apigateway create-rest-api \
    --name "api-name" \
    --policy file://policy.json
```

`policy.json` is an API Gateway resource policy, such as [Example: Deny API traffic based on source IP address or range](apigateway-resource-policies-examples.md#apigateway-resource-policies-source-ip-address-example).

------
#### [ AWS CloudFormation ]

You can use CloudFormation to create an API with a resource policy. The following example creates a REST API with the example resource policy, [Example: Deny API traffic based on source IP address or range](apigateway-resource-policies-examples.md#apigateway-resource-policies-source-ip-address-example). 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: testapi
      Policy:
        Statement:
          - Action: 'execute-api:Invoke'
            Effect: Allow
            Principal: '*'
            Resource: 'execute-api:/*'
          - Action: 'execute-api:Invoke'
            Effect: Deny
            Principal: '*'
            Resource: 'execute-api:/*'
            Condition:
              IpAddress: 
                'aws:SourceIp': ["192.0.2.0/24", "198.51.100.0/24" ]
        Version: 2012-10-17		 	 	 
  Resource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'helloworld'
  MethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref Resource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: MOCK
        RequestTemplates:
          application/json: '{"statusCode": 200}'
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: '{}'
      MethodResponses:
        - StatusCode: 200
          ResponseModels:
            application/json: 'Empty'
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - MethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: test
```

------

## Troubleshoot your resource policy
<a name="apigateway-resource-policies-troubleshoot"></a>

The following troubleshooting guidance might help resolve issues with your resource policy.

### My API returns \$1"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-1:\$1\$1\$1\$1\$1\$1\$1\$1/\$1\$1\$1\$1/\$1\$1\$1\$1/"\$1
<a name="apigateway-resource-policies-troubleshoot-auth"></a>

In your resource policy, if you set the Principal to an AWS principal, such as the following:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111111111111:role/developer",
                    "arn:aws:iam::111111111111:role/Admin"
                ]
            },
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/stage/GET/pets"
            ]
        }
    ]
}
```

------

You must use `AWS_IAM` authorization for every method in your API, or else your API returns the previous error message. For more instructions on how to turn on `AWS_IAM` authorization for a method, see [Methods for REST APIs in API Gateway](how-to-method-settings.md).

### My resource policy is not updating
<a name="apigateway-resource-policies-troubleshoot-deploy"></a>

 If you update the resource policy after the API is created, you'll need to deploy the API to propagate the changes after you've attached the updated policy. Updating or saving the policy alone won't change the runtime behavior of the API. For more information about deploying your API, see [Deploy REST APIs in API Gateway](how-to-deploy-api.md). 

### My resource policy returns the following error: Invalid policy document. Please check the policy syntax and ensure that Principals are valid.
<a name="apigateway-resource-policies-troubleshoot-invalid-principal"></a>

To troubleshoot this error, we first recommend that you check the policy syntax. For more information, see [Access policy language overview for Amazon API Gateway](apigateway-control-access-policy-language-overview.md). We also recommend that you check that all the principals specified are valid and haven’t been deleted.

In addition, if your API is in an [opt-in Region](https://docs.aws.amazon.com/glossary/latest/reference/glos-chap.html?icmpid=docs_homepage_addtlrcs#optinregion), verify that all accounts in the resource policy have the Region enabled. 

# AWS condition keys that can be used in API Gateway resource policies
<a name="apigateway-resource-policies-aws-condition-keys"></a>

The following table contains AWS condition keys that can be used in resource policies for APIs in API Gateway for each authorization type.

For more information about AWS condition keys, see [AWS Global Condition Context Keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html).


| **Condition keys** | **Criteria** | **Needs `AuthN`?** | **Authorization type** | 
| --- | --- | --- | --- | 
| aws:CurrentTime | None | No | All | 
| aws:EpochTime | None | No | All | 
| aws:TokenIssueTime | Key is present only in requests that are signed using temporary security credentials. | Yes | IAM | 
| aws:MultiFactorAuthPresent | Key is present only in requests that are signed using temporary security credentials. | Yes | IAM | 
| aws:MultiFactorAuthAge | Key is present only if MFA is present in the requests. | Yes | IAM | 
| aws:PrincipalAccount | None | Yes | IAM | 
| aws:PrincipalArn | None | Yes | IAM | 
| aws:PrincipalOrgID | This key is included in the request context only if the principal is a member of an organization. | Yes | IAM | 
| aws:PrincipalOrgPaths | This key is included in the request context only if the principal is a member of an organization. | Yes | IAM | 
| aws:PrincipalTag | This key is included in the request context if the principal is using an IAM user with attached tags. It is included for a principal using an IAM role with attached tags or session tags. | Yes | IAM | 
| aws:PrincipalType | None | Yes | IAM | 
| aws:Referer | Key is present only if the value is provided by the caller in the HTTP header. | No | All | 
| aws:SecureTransport | None | No | All | 
| aws:SourceArn | None | No | All | 
| aws:SourceIp | None | No | All | 
| aws:SourceVpc | This key can be used only for private APIs. | No | All | 
| aws:SourceVpce | This key can be used only for private APIs. | No | All | 
| aws:VpcSourceIp | This key can be used only for private APIs. | No | All | 
| aws:UserAgent | Key is present only if the value is provided by the caller in the HTTP header. | No | All | 
| aws:userid | None | Yes | IAM | 
| aws:username | None | Yes | IAM | 

# Control access to a REST API with IAM permissions
<a name="permissions"></a>

 You control access to your Amazon API Gateway API with [IAM permissions](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_controlling.html) by controlling access to the following two API Gateway component processes: 
+  To create, deploy, and manage an API in API Gateway, you must grant the API developer permissions to perform the required actions supported by the API management component of API Gateway. 
+  To call a deployed API or to refresh the API caching, you must grant the API caller permissions to perform required IAM actions supported by the API execution component of API Gateway. 

 The access control for the two processes involves different permissions models, explained next.

## API Gateway permissions model for creating and managing an API
<a name="api-gateway-control-access-iam-permissions-model-for-managing-api"></a>

 To allow an API developer to create and manage an API in API Gateway, you must [create IAM permissions policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html) that allow a specified API developer to create, update, deploy, view, or delete required [API entities](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html). You attach the permissions policy to a user, role, or group. 

To provide access, add permissions to your users, groups, or roles:
+ Users and groups in AWS IAM Identity Center:

  Create a permission set. Follow the instructions in [Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/howtocreatepermissionset.html) in the *AWS IAM Identity Center User Guide*.
+ Users managed in IAM through an identity provider:

  Create a role for identity federation. Follow the instructions in [Create a role for a third-party identity provider (federation)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-idp.html) in the *IAM User Guide*.
+ IAM users:
  + Create a role that your user can assume. Follow the instructions in [Create a role for an IAM user](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-user.html) in the *IAM User Guide*.
  + (Not recommended) Attach a policy directly to a user or add a user to a user group. Follow the instructions in [Adding permissions to a user (console)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_users_change-permissions.html#users_change_permissions-add-console) in the *IAM User Guide*.

For more information on how to use this permissions model, see [API Gateway identity-based policies](security_iam_service-with-iam.md#security_iam_service-with-iam-id-based-policies). 

## API Gateway permissions model for invoking an API
<a name="api-gateway-control-access-iam-permissions-model-for-calling-api"></a>

To allow an API caller to invoke the API or refresh its caching, you must create IAM policies that permit a specified API caller to invoke the API method for which user authentication is enabled. The API developer sets the method's `authorizationType` property to `AWS_IAM` to require that the caller submit the user's credentials to be authenticated. API Gateway supports Signature Version 4a (SigV4a) and Signature Version 4 (SigV4) to authenticate the user's credentials. For more information, see [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html). Then, you attach the policy to a user, role, or group. 

In this IAM permissions policy statement, the IAM `Resource` element contains a list of deployed API methods identified by given HTTP verbs and API Gateway [resource paths](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html). The IAM `Action` element contains the required API Gateway API executing actions. These actions include `execute-api:Invoke` or `execute-api:InvalidateCache`, where `execute-api` designates the underlying API execution component of API Gateway. 

For more information on how to use this permissions model, see [Control access for invoking an API](api-gateway-control-access-using-iam-policies-to-invoke-api.md). 

 When an API is integrated with an AWS service (for example, AWS Lambda) in the back end, API Gateway must also have permissions to access integrated AWS resources (for example, invoking a Lambda function) on behalf of the API caller. To grant these permissions, create an IAM role of the **AWS service for API Gateway** type. When you create this role in the IAM Management console, this resulting role contains the following IAM trust policy that declares API Gateway as a trusted entity permitted to assume the role: 

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

If you create the IAM role by calling the [create-role](https://docs.aws.amazon.com/cli/latest/reference/iam/create-role.html) command of CLI or a corresponding SDK method, you must supply the above trust policy as the input parameter of `assume-role-policy-document`. Do not attempt to create such a policy directly in the IAM Management console or calling AWS CLI [create-policy](https://docs.aws.amazon.com/cli/latest/reference/iam/create-policy.html) command or a corresponding SDK method.

For API Gateway to call the integrated AWS service, you must also attach to this role appropriate IAM permissions policies for calling integrated AWS services. For example, to call a Lambda function, you must include the following IAM permissions policy in the IAM role: 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "*"
        }
    ]
}
```

------

Note that Lambda supports resource-based access policy, which combines both trust and permissions policies. When integrating an API with a Lambda function using the API Gateway console, you are not asked to set this IAM role explicitly, because the console sets the resource-based permissions on the Lambda function for you, with your consent. 

**Note**  
 To enact access control to an AWS service, you can use either the caller-based permissions model, where a permissions policy is directly attached to the caller's user or group, or the role-based permission model, where a permissions policy is attached to an IAM role that API Gateway can assume. The permissions policies may differ in the two models. For example, the caller-based policy blocks the access while the role-based policy allows it. You can take advantage of this to require that a user access an AWS service through an API Gateway API only. 

# Control access for invoking an API
<a name="api-gateway-control-access-using-iam-policies-to-invoke-api"></a>

In this section, you learn about the permissions model for controlling access to your API using IAM permissions. When IAM authorization is enabled, clients must use Signature Version 4a (SigV4a) and Signature Version 4 (SigV4) to sign their requests with AWS credentials. For more information, see [AWS Signature Version 4](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html).

In this section, we show a template IAM policy statement and the policy statement reference. The policy statement reference includes the formats of `Action` and `Resource` fields related to the API execution service. Use these references to create your IAM policy statement. When you create your IAM policy statement, you might need to consider the how API Gateway resource policies affect the authorization workflow. For more information, see [How API Gateway resource policies affect authorization workflow](apigateway-authorization-flow.md).

For private APIs, you should use a combination of an API Gateway resource policy and a VPC endpoint policy. For more information, see the following topics:
+ [Control access to a REST API with API Gateway resource policies](apigateway-resource-policies.md)
+ [Use VPC endpoint policies for private APIs in API Gateway](apigateway-vpc-endpoint-policies.md)

## Control who can call an API Gateway API method with IAM policies
<a name="api-gateway-who-can-invoke-an-api-method-using-iam-policies"></a>

 To control who can or cannot call a deployed API with IAM permissions, create an IAM policy document with required permissions. A template for such a policy document is shown as follows. 

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Permission",
      "Action": [
        "execute-api:Execution-operation"           
      ],
      "Resource": [
        "arn:aws:execute-api:region:123456789012:api-id/stage/METHOD_HTTP_VERB/Resource-path"
      ]
    }
  ]
}
```

------

 Here, `Permission` is to be replaced by `Allow` or `Deny` depending on whether you want to grant or revoke the included permissions. `Execution-operation` is to be replaced by the operations supported by the API execution service. `METHOD_HTTP_VERB` stands for a HTTP verb supported by the specified resources. `Resource-path` is the placeholder for the URL path of a deployed API `[Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html)` instance supporting the said `METHOD_HTTP_VERB`. For more information, see [Statement reference of IAM policies for executing API in API Gateway](#api-gateway-calling-api-permissions). 

**Note**  
For IAM policies to be effective, you must have enabled IAM authentication on API methods by setting `AWS_IAM` for the methods' `[authorizationType](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#authorizationType)` property. Failing to do so will make these API methods publicly accessible.

 For example, to grant a user permission to view a list of pets exposed by a specified API, but to deny the user permission to add a pet to the list, you could include the following statement in the IAM policy: 

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:111111111111:api-id/*/GET/pets"
      ]
    },
    {
      "Effect": "Deny",
      "Action": [
        "execute-api:Invoke"           
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:111111111111:api-id/*/POST/pets"
      ]
    }
  ]
}
```

------

To grant a user permission to view a specific pet exposed by an API that is configured as `GET /pets/{petId}`, you could include the following statement in the IAM policy:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": [
                "arn:aws:execute-api:us-east-1:111122223333:api-id/*/GET/pets/a1b2"
            ]
        }
    ]
}
```

------

## Statement reference of IAM policies for executing API in API Gateway
<a name="api-gateway-calling-api-permissions"></a>

The following information describes the Action and Resource format of IAM policy statements of access permissions for executing an API.

### Action format of permissions for executing API in API Gateway
<a name="api-gateway-iam-policy-action-format-for-executing-api"></a>

The API-executing `Action` expression has the following general format:

```
execute-api:action
```

where *action* is an available API-executing action:
+ **\$1**, which represents all of the following actions.
+ **Invoke**, used to invoke an API upon a client request.
+ **InvalidateCache**, used to invalidate API cache upon a client request.

### Resource format of permissions for executing API in API Gateway
<a name="api-gateway-iam-policy-resource-format-for-executing-api"></a>

The API-executing `Resource` expression has the following general format:

```
arn:aws:execute-api:region:account-id:api-id/stage-name/HTTP-VERB/resource-path-specifier
```

where:
+ *region* is the AWS region (such as **us-east-1** or **\$1** for all AWS regions) that corresponds to the deployed API for the method.
+ *account-id* is the 12-digit AWS account Id of the REST API owner. 
+ *api-id* is the identifier API Gateway has assigned to the API for the method.
+ *stage-name* is the name of the stage associated with the method.
+ *HTTP-VERB* is the HTTP verb for the method. It can be one of the following: GET, POST, PUT, DELETE, PATCH.
+ *resource-path-specifier* is the path to the desired method.

**Note**  
If you specify a wildcard (`*`), the `Resource` expression applies the wildcard to the rest of the expression.

Some example resource expressions include:
+ **arn:aws:execute-api:\$1:\$1:\$1** for any resource path in any stage, for any API in any AWS region.
+ **arn:aws:execute-api:us-east-1:\$1:\$1** for any resource path in any stage, for any API in the AWS region of `us-east-1`.
+ **arn:aws:execute-api:us-east-1:\$1:*api-id*/\$1** for any resource path in any stage, for the API with the identifier of *api-id* in the AWS region of us-east-1.
+ **arn:aws:execute-api:us-east-1:\$1:*api-id*/`test`/\$1** for any resource path in the stage of `test`, for the API with the identifier of *api-id* in the AWS region of us-east-1.

To learn more, see [API Gateway Amazon Resource Name (ARN) reference](arn-format-reference.md).

# IAM policy examples for API execution permissions
<a name="api-gateway-iam-policy-examples-for-api-execution"></a>

For permissions model and other background information, see [Control access for invoking an API](api-gateway-control-access-using-iam-policies-to-invoke-api.md).

The following policy statement gives the user permission to call any POST method along the path of `mydemoresource`, in the stage of `test`, for the API with the identifier of `a123456789`, assuming the corresponding API has been deployed to the AWS region of us-east-1:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": [
        "arn:aws:execute-api:us-east-1:*:a123456789/test/POST/my-demo-resource-path/*"
      ]
    }
  ]
}
```

------

The following example policy statement gives the user permission to call any method on the resource path of `petstorewalkthrough/pets`, in any stage, for the API with the identifier of `a123456789`, in any AWS region where the corresponding API has been deployed:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "execute-api:Invoke"
      ],
      "Resource": [
        "arn:aws:execute-api:*:*:a123456789/*/*/petstorewalkthrough/pets"
      ]
    }
  ]
}
```

------

# Use VPC endpoint policies for private APIs in API Gateway
<a name="apigateway-vpc-endpoint-policies"></a>

To improve the security of your private API, you can create a VPC endpoint policy. A VPC endpoint policy is an IAM resource policy that you attach to a VPC endpoint. For more information, see [Controlling Access to Services with VPC Endpoints](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-access.html).

You might want to create a VPC endpoint policy to do the following tasks.
+ Allow only certain organizations or resources to access your VPC endpoint and invoke your API.
+ Use a single policy and avoid session-based or role-based policies to control traffic to your API.
+ Tighten the security perimeter of your application while migrating from on premises to AWS.

## VPC endpoint policy considerations
<a name="apigateway-vpc-endpoint-policies-considerations"></a>

The following are considerations for your VPC endpoint policy:
+ The identity of the invoker is evaluated based on the `Authorization` header value. The VPC endpoint policy is evaluated first, and then API Gateway evaluates the request, based on the type of authorization configured on the method request. The following table shows how the VPC endpoint policy is evaluated based on the content of the `Authorization` header value.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-vpc-endpoint-policies.html)
+ If your access control depends on using a bearer token, such as a Lambda or Amazon Cognito authorizer, you can control your security perimeter by using [properties of the resource](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resource-properties).
+  If your authorization controls use IAM authorization, you can control your security perimeter by using [properties of the resource](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resource-properties) and [ properties of the principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resource-principal).
+ VPC endpoint policies can be used together with API Gateway resource policies. The API Gateway resource policy specifies which principals can access the API. The endpoint policy specifies who can access the VPC and which APIs can be called from the VPC endpoint. Your private API needs a resource policy but you don't need to create a custom VPC endpoint policy.

## VPC endpoint policy examples
<a name="apigateway-vpc-endpoint-policies-examples"></a>

You can create policies for Amazon Virtual Private Cloud endpoints for Amazon API Gateway in which you can specify the following.
+ The principal that can perform actions.
+ The actions that can be performed.
+ The resources that can have actions performed on them.

This might depend on the contents of your authorization header. For more information, see [VPC endpoint policy considerations](#apigateway-vpc-endpoint-policies-considerations). For additional example policies, see [Data perimeter policy examples](https://github.com/aws-samples/data-perimeter-policy-examples) on the GitHub website.

To attach the policy to the VPC endpoint, you'll need to use the VPC console. For more information, see [Controlling Access to Services with VPC Endpoints](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-access.html). 

## Example 1: VPC endpoint policy granting access to two APIs
<a name="apigateway-vpc-endpoint-policies-example-1"></a>

The following example policy grants access to only two specific APIs via the VPC endpoint that the policy is attached to.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Principal": "*",
            "Action": [
                "execute-api:Invoke"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:execute-api:us-east-1:123412341234:a1b2c3d4e5/*",
                "arn:aws:execute-api:us-east-1:123412341234:aaaaa11111/*"
            ]
        }
    ]
}
```

------

## Example 2: VPC endpoint policy granting access to GET methods
<a name="apigateway-vpc-endpoint-policies-example-2"></a>

The following example policy grants users access to `GET` methods for a specific API via the VPC endpoint that the policy is attached to.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Principal": "*",
            "Action": [
                "execute-api:Invoke"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:execute-api:us-east-1:123412341234:a1b2c3d4e5/stageName/GET/*"
            ]
        }
    ]
}
```

------

## Example 3: VPC endpoint policy granting a specific user access to a specific API
<a name="apigateway-vpc-endpoint-policies-example-3"></a>

The following example policy grants a specific user access to a specific API via the VPC endpoint that the policy is attached to.

In this case, because the policy restricts access to specific IAM principals, you must set the `authorizationType` of the method to `AWS_IAM` or `NONE`.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Principal": {
                "AWS": [
                    "arn:aws:iam::123412341234:user/MyUser"
                ]
            },
            "Action": [
                "execute-api:Invoke"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:execute-api:us-east-1:123412341234:a1b2c3d4e5/*"
            ]
        }
    ]
}
```

------

## Example 4: VPC endpoint policy granting users access to a specific custom domain name and every API mapped to the domain
<a name="apigateway-vpc-endpoint-policies-example-4"></a>

The following example policy grants users access to a specific custom domain name for private APIs via the VPC endpoint that the policy is attached to. With this policy, as long as a user has created a domain name access association between the VPC endpoint and the custom domain name and is granted access to invoke the custom domain name and any private API's mapped to the custom domain name, the user can invoke any APIs mapped to this custom domain name. For more information, see [Custom domain names for private APIs in API Gateway](apigateway-private-custom-domains.md).

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "execute-api:Invoke",
      "Resource": [
        "*"
      ],
       "Condition": {
        "ArnEquals": {
          "execute-api:viaDomainArn": "arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.test.com+f4g5h6",
        }
      }
    }
  ]
}
```

------

## Example 5: VPC endpoint policy granting or denying access to specific APIs and domain resources
<a name="apigateway-vpc-endpoint-policies-example-5"></a>

The following example policy grants users access to specific APIs and domain resources. With this policy, as long as a user has created a domain name access association between the VPC endpoint and the custom domain name and is granted access to invoke the custom domain name and any private API's mapped to the custom domain name, the user can invoke allowed private APIs and domain resources. For more information, see [Custom domain names for private APIs in API Gateway](apigateway-private-custom-domains.md).

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "execute-api:Invoke",
      "Resource": [
        "arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.test.com+f4g5h6",
        "arn:aws:execute-api:us-west-2:111122223333:a1b2c3d4e5/*"
      ]
    },
    {
      "Effect": "Deny",
      "Principal": {
        "AWS": "*"
      },
      "Action": "execute-api:Invoke",
      "Resource": [
        "arn:aws:execute-api:us-west-2:111122223333:a1b2c3d4e5/admin/*",
        "arn:aws:execute-api:us-west-2:111122223333:bcd123455/*"
      ]
    }
  ]
}
```

------

## Example 6: VPC endpoint policy granting or denying access by principals and resources belonging to an organization
<a name="apigateway-vpc-endpoint-policies-example-6"></a>

The following example policy grants access to principals and resources that belong to an organization.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Condition": {
                "StringEquals": {
                    "aws:ResourceOrgID": "o-abcd1234",
                    "aws:PrincipalOrgID": "o-abcd1234"
                }
            },
            "Action": "*",
            "Resource": "*",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Sid": "AllowRequestsByOrgsIdentitiesToOrgsResources"
        }
    ]
}
```

------

# Use tags to control access to REST APIs in API Gateway
<a name="apigateway-control-access-tags"></a>

Permission to access REST APIs can be fine-tuned using attribute-based access control in IAM policies.

For more information, see [Using tags to control access to API Gateway REST API resources](apigateway-tagging-iam-policy.md).

# Use API Gateway Lambda authorizers
<a name="apigateway-use-lambda-authorizer"></a>

Use a *Lambda authorizer* (formerly known as a *custom authorizer*) to control access to your API. When a client makes a request to your API's method, API Gateway calls your Lambda authorizer. The Lambda authorizer takes the caller's identity as the input and returns an IAM policy as the output.

Use a Lambda authorizer to implement a custom authorization scheme. Your scheme can use request parameters to determine the caller's identity or use a bearer token authentication strategy such as OAuth or SAML. Create a Lambda authorizer in the API Gateway REST API console, using the AWS CLI, or an AWS SDK.

## Lambda authorizer authorization workflow
<a name="api-gateway-lambda-authorizer-flow"></a>

The following diagram shows the authorization workflow for a Lambda authorizer.

![\[API Gateway Lambda authorization workflow\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/custom-auth-workflow.png)


**API Gateway Lambda authorization workflow**

1. The client calls a method on an API Gateway API, passing a bearer token or request parameters.

1. API Gateway checks if the method request is configured with a Lambda authorizer. If it is, API Gateway calls the Lambda function.

1. The Lambda function authenticates the caller. The function can authenticate in the following ways:
   + By calling out to an OAuth provider to get an OAuth access token.
   + By calling out to a SAML provider to get a SAML assertion.
   + By generating an IAM policy based on the request parameter values.
   + By retrieving credentials from a database.

1. The Lambda function returns an IAM policy and a principal identifier. If the Lambda function does not return that information, the call fails. 

1. API Gateway evaluates the IAM policy.
   + If access is denied, API Gateway returns a suitable HTTP status code, such as `403 ACCESS_DENIED`.
   + If access is allowed, API Gateway invokes the method. 

     If you enable authorization caching, API Gateway caches the policy so that the Lambda authorizer function isn’t invoked again. Ensure that your policy is applicable to all resources and methods across your API.

You can customize the `403 ACCESS_DENIED` or the `401 UNAUTHORIZED` gateway responses. To learn more, see [Gateway responses for REST APIs in API Gateway](api-gateway-gatewayResponse-definition.md).

## Choosing a type of Lambda authorizer
<a name="api-gateway-lambda-authorizer-choose"></a>

There are two types of Lambda authorizers:

**Request parameter-based Lambda authorizer (`REQUEST` authorizer)**  
A `REQUEST` authorizer receives the caller's identity in a combination of headers, query string parameters, [`stageVariables`](api-gateway-mapping-template-reference.md#stagevariables-template-reference), and [`$context`](api-gateway-mapping-template-reference.md#context-variable-reference) variables. You can use a `REQUEST` authorizer to create fine-grained policies based on the information from multiple identity sources, such as the `$context.path` and `$context.httpMethod` context variables.  
If you turn on authorization caching for a `REQUEST` authorizer, API Gateway verifies that all specified identity sources are present in the request. If a specified identify source is missing, null, or empty, API Gateway returns a `401 Unauthorized` HTTP response without calling the Lambda authorizer function. When multiple identity sources are defined, they are all used to derive the authorizer's cache key, with the order preserved. You can define a fine-grained cache key by using multiple identity sources.  
If you change any of the cache key parts, and redeploy your API, the authorizer discards the cached policy document and generates a new one.  
If you turn off authorization caching for a `REQUEST` authorizer, API Gateway directly passes the request to the Lambda function. 

**Token-based Lambda authorizer (`TOKEN` authorizer)**  
A `TOKEN` authorizer receives the caller's identity in a bearer token, such as a JSON Web Token (JWT) or an OAuth token.  
If you turn on authorization caching for a `TOKEN` authorizer, the header name specified in the token source becomes the cache key.   
Additionally, you can use token validation to enter a RegEx statement. API Gateway performs initial validation of the input token against this expression and invokes the Lambda authorizer function upon successful validation. This helps reduce calls to your API.   
The `IdentityValidationExpression` property is supported for `TOKEN` authorizers only. For more information, see [x-amazon-apigateway-authorizer object](api-gateway-swagger-extensions-authorizer.md).

**Note**  
We recommend that you use a `REQUEST` authorizer to control access to your API. You can control access to your API based on multiple identity sources when using a `REQUEST` authorizer, compared to a single identity source when using a `TOKEN` authorizer. In addition, you can separate cache keys using multiple identity sources for a `REQUEST` authorizer.

## Example `REQUEST` authorizer Lambda function
<a name="api-gateway-lambda-authorizer-request-lambda-function-create"></a>

The following example code creates a Lambda authorizer function that allows a request if the client-supplied `HeaderAuth1` header, `QueryString1` query parameter, and stage variable of `StageVar1` all match the specified values of `headerValue1`, `queryValue1`, and `stageValue1`, respectively. 

------
#### [ Node.js ]

```
// A simple request-based authorizer example to demonstrate how to use request 
// parameters to allow or deny a request. In this example, a request is  
// authorized if the client-supplied HeaderAuth1 header, QueryString1
// query parameter, and stage variable of StageVar1 all match
// specified values of 'headerValue1', 'queryValue1', and 'stageValue1',
// respectively.
    
export const handler = function(event, context, callback) {
    console.log('Received event:', JSON.stringify(event, null, 2));
    
    // Retrieve request parameters from the Lambda function input:
    var headers = event.headers;
    var queryStringParameters = event.queryStringParameters;
    var pathParameters = event.pathParameters;
    var stageVariables = event.stageVariables;
        
    // Parse the input for the parameter values
    var tmp = event.methodArn.split(':');
    var apiGatewayArnTmp = tmp[5].split('/');
    var awsAccountId = tmp[4];
    var region = tmp[3];
    var restApiId = apiGatewayArnTmp[0];
    var stage = apiGatewayArnTmp[1];
    var method = apiGatewayArnTmp[2];
    var resource = '/'; // root resource
    if (apiGatewayArnTmp[3]) {
        resource += apiGatewayArnTmp[3];
    }
        
    // Perform authorization to return the Allow policy for correct parameters and 
    // the 'Unauthorized' error, otherwise.

     
    if (headers.HeaderAuth1 === "headerValue1"
        && queryStringParameters.QueryString1 === "queryValue1"
        && stageVariables.StageVar1 === "stageValue1") {
        callback(null, generateAllow('me', event.methodArn));
    }  else {
        callback(null, generateDeny('me', event.methodArn));
    }
}
     
// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    // Required output:
    var authResponse = {};
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; // default version
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; // default action
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };
    return authResponse;
}
     
var generateAllow = function(principalId, resource) {
    return generatePolicy(principalId, 'Allow', resource);
}
     
var generateDeny = function(principalId, resource) {
    return generatePolicy(principalId, 'Deny', resource);
}
```

------
#### [ Python ]

```
# A simple request-based authorizer example to demonstrate how to use request
# parameters to allow or deny a request. In this example, a request is
# authorized if the client-supplied headerauth1 header, QueryString1
# query parameter, and stage variable of StageVar1 all match
# specified values of 'headerValue1', 'queryValue1', and 'stageValue1',
# respectively.

def lambda_handler(event, context):
    print(event)

    # Retrieve request parameters from the Lambda function input:
    headers = event['headers']
    queryStringParameters = event['queryStringParameters']
    pathParameters = event['pathParameters']
    stageVariables = event['stageVariables']

    # Parse the input for the parameter values
    tmp = event['methodArn'].split(':')
    apiGatewayArnTmp = tmp[5].split('/')
    awsAccountId = tmp[4]
    region = tmp[3]
    restApiId = apiGatewayArnTmp[0]
    stage = apiGatewayArnTmp[1]
    method = apiGatewayArnTmp[2]
    resource = '/'

    if (apiGatewayArnTmp[3]):
        resource += apiGatewayArnTmp[3]

    # Perform authorization to return the Allow policy for correct parameters
    # and the 'Unauthorized' error, otherwise.

    if (headers['HeaderAuth1'] == "headerValue1" and queryStringParameters['QueryString1'] == "queryValue1" and stageVariables['StageVar1'] == "stageValue1"):
        response = generateAllow('me', event['methodArn'])
        print('authorized')
        return response
    else:
        print('unauthorized')
        response = generateDeny('me', event['methodArn'])
        return response
    # Help function to generate IAM policy


def generatePolicy(principalId, effect, resource):
    authResponse = {}
    authResponse['principalId'] = principalId
    if (effect and resource):
        policyDocument = {}
        policyDocument['Version'] = '2012-10-17'
        policyDocument['Statement'] = []
        statementOne = {}
        statementOne['Action'] = 'execute-api:Invoke'
        statementOne['Effect'] = effect
        statementOne['Resource'] = resource
        policyDocument['Statement'] = [statementOne]
        authResponse['policyDocument'] = policyDocument

    authResponse['context'] = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": True
    }

    return authResponse


def generateAllow(principalId, resource):
    return generatePolicy(principalId, 'Allow', resource)


def generateDeny(principalId, resource):
    return generatePolicy(principalId, 'Deny', resource)
```

------

In this example, the Lambda authorizer function checks the input parameters and acts as follows:
+ If all the required parameter values match the expected values, the authorizer function returns a `200 OK` HTTP response and an IAM policy that looks like the following, and the method request succeeds:

------
#### [ JSON ]

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow",
        "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/"
      }
    ]
  }
  ```

------
+ Otherwise, the authorizer function returns a `401 Unauthorized` HTTP response, and the method request fails.

In addition to returning an IAM policy, the Lambda authorizer function must also return the caller's principal identifier. Optionally, it can return a `context` object containing additional information that can be passed into the integration backend. For more information, see [Output from an API Gateway Lambda authorizer](api-gateway-lambda-authorizer-output.md).

In production code, you might need to authenticate the user before granting authorization. You can add authentication logic in the Lambda function by calling an authentication provider as directed in the documentation for that provider.

## Example `TOKEN` authorizer Lambda function
<a name="api-gateway-lambda-authorizer-token-lambda-function-create"></a>

The following example code creates a `TOKEN` Lambda authorizer function that allows a caller to invoke a method if the client-supplied token value is `allow`. The caller is not allowed to invoke the request if the token value is `deny`. If the token value is `unauthorized` or an empty string, the authorizer function returns an `401 UNAUTHORIZED` response.

------
#### [ Node.js ]

```
// A simple token-based authorizer example to demonstrate how to use an authorization token 
// to allow or deny a request. In this example, the caller named 'user' is allowed to invoke 
// a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke 
// the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty
// string, the authorizer function returns an HTTP 401 status code. For any other token value, 
// the authorizer returns an HTTP 500 status code. 
// Note that token values are case-sensitive.

export const handler =  function(event, context, callback) {
    var token = event.authorizationToken;
    switch (token) {
        case 'allow':
            callback(null, generatePolicy('user', 'Allow', event.methodArn));
            break;
        case 'deny':
            callback(null, generatePolicy('user', 'Deny', event.methodArn));
            break;
        case 'unauthorized':
            callback("Unauthorized");   // Return a 401 Unauthorized response
            break;
        default:
            callback("Error: Invalid token"); // Return a 500 Invalid token response
    }
};

// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    var authResponse = {};
    
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; 
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; 
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
    
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };
    return authResponse;
}
```

------
#### [ Python ]

```
# A simple token-based authorizer example to demonstrate how to use an authorization token
# to allow or deny a request. In this example, the caller named 'user' is allowed to invoke
# a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke
# the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty
# string, the authorizer function returns an HTTP 401 status code. For any other token value,
# the authorizer returns an HTTP 500 status code.
# Note that token values are case-sensitive.

import json


def lambda_handler(event, context):
    token = event['authorizationToken']
    if token == 'allow':
        print('authorized')
        response = generatePolicy('user', 'Allow', event['methodArn'])
    elif token == 'deny':
        print('unauthorized')
        response = generatePolicy('user', 'Deny', event['methodArn'])
    elif token == 'unauthorized':
        print('unauthorized')
        raise Exception('Unauthorized')  # Return a 401 Unauthorized response
        return 'unauthorized'
    try:
        return json.loads(response)
    except BaseException:
        print('unauthorized')
        return 'unauthorized'  # Return a 500 error


def generatePolicy(principalId, effect, resource):
    authResponse = {}
    authResponse['principalId'] = principalId
    if (effect and resource):
        policyDocument = {}
        policyDocument['Version'] = '2012-10-17'
        policyDocument['Statement'] = []
        statementOne = {}
        statementOne['Action'] = 'execute-api:Invoke'
        statementOne['Effect'] = effect
        statementOne['Resource'] = resource
        policyDocument['Statement'] = [statementOne]
        authResponse['policyDocument'] = policyDocument
    authResponse['context'] = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": True
    }
    authResponse_JSON = json.dumps(authResponse)
    return authResponse_JSON
```

------

In this example, when the API receives a method request, API Gateway passes the source token to this Lambda authorizer function in the `event.authorizationToken` attribute. The Lambda authorizer function reads the token and acts as follows:
+ If the token value is `allow`, the authorizer function returns a `200 OK` HTTP response and an IAM policy that looks like the following, and the method request succeeds:

------
#### [ JSON ]

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow",
        "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/"
      }
    ]
  }
  ```

------
+ If the token value is `deny`, the authorizer function returns a `200 OK` HTTP response and a `Deny` IAM policy that looks like the following, and the method request fails:

------
#### [ JSON ]

****  

  ```
  {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Deny",
        "Resource": "arn:aws:execute-api:us-east-1:123456789012:ivdtdhp7b5/ESTestInvoke-stage/GET/"
      }
    ]
  }
  ```

------
**Note**  
Outside of the test environment, API Gateway returns a `403 Forbidden` HTTP response and the method request fails.
+ If the token value is `unauthorized` or an empty string, the authorizer function returns a `401 Unauthorized` HTTP response, and the method call fails.
+ If the token is anything else, the client receives a `500 Invalid token` response, and the method call fails.

In addition to returning an IAM policy, the Lambda authorizer function must also return the caller's principal identifier. Optionally, it can return a `context` object containing additional information that can be passed into the integration backend. For more information, see [Output from an API Gateway Lambda authorizer](api-gateway-lambda-authorizer-output.md).

In production code, you might need to authenticate the user before granting authorization. You can add authentication logic in the Lambda function by calling an authentication provider as directed in the documentation for that provider.

## Additional examples of Lambda authorizer functions
<a name="api-gateway-lambda-authorizer-lambda-function-create"></a>

The following list shows additional examples of Lambda authorizer functions. You can create a Lambda function in the same account, or a different account, from where you created your API.

For the previous example Lambda functions, you can use the built-in [AWSLambdaBasicExecutionRole](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html), as these functions don't call other AWS services. If your Lambda function calls other AWS services, you'll need to assign an IAM execution role to the Lambda function. To create the role, follow the instructions in [AWS Lambda Execution Role](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html).

**Additional examples of Lambda authorizer functions**
+  For an example application, see [Open Banking Brazil - Authorization Samples](https://github.com/aws-samples/openbanking-brazilian-auth-samples) on GitHub. 
+  For more example Lambda functions, see [ aws-apigateway-lambda-authorizer-blueprints](https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints) on GitHub. 
+ You can create a Lambda authorizer that authenticates users using Amazon Cognito user pools and authorizes callers based on a policy store using Verified Permissions. For more information, see [Control access based on an identity’s attributes with Verified Permissions](apigateway-lambda-authorizer-verified-permissions.md).
+ The Lambda console provides a Python blueprint, which you can use by choosing **Use a blueprint** and choosing the **api-gateway-authorizer-python** blueprint.

# Configure an API Gateway Lambda authorizer
<a name="configure-api-gateway-lambda-authorization"></a>

After you create a Lambda function, you configure the Lambda function as an authorizer for your API. You then configure your method to invoke your Lambda authorizer to determine if a caller can invoke your method. You can create a Lambda function in the same account, or a different account, from where you created your API.

You can test your Lambda authorizer using built-in tools in the API Gateway console or by using [Postman](https://www.postman.com/). For instructions for how to use Postman to test your Lambda authorizer function, see [Call an API with an API Gateway Lambda authorizer](call-api-with-api-gateway-lambda-authorization.md).

## Configure a Lambda authorizer (console)
<a name="configure-api-gateway-lambda-authorization-with-console"></a>

 The following procedure shows how to create a Lambda authorizer in the API Gateway REST API console. To learn more about the different types of Lambda authorizers, see [Choosing a type of Lambda authorizer](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-choose). 

------
#### [ REQUEST authorizer ]

**To configure a `REQUEST` Lambda authorizer**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Select an API, and then choose **Authorizers**. 

1. Choose **Create authorizer**. 

1. For **Authorizer name**, enter a name for the authorizer.

1. For **Authorizer type**, select **Lambda**. 

1. For **Lambda function**, select the AWS Region where you created your Lambda authorizer function, and then enter the function name.

1. Keep **Lambda invoke role** blank to let the API Gateway REST API console set a resource-based policy. The policy grants API Gateway permissions to invoke the Lambda authorizer function. You can also choose to enter the name of an IAM role to allow API Gateway to invoke the Lambda authorizer function. For an example role, see [Create an assumable IAM role](integrating-api-with-aws-services-lambda.md#api-as-lambda-proxy-setup-iam-role-policies). 

1. For **Lambda event payload**, select **Request**.

1. For **Identity source type**, select a parameter type. Supported parameter types are `Header`, `Query string`, `Stage variable`, and `Context`. To add more identity sources, choose **Add parameter**. 

1. To cache the authorization policy generated by the authorizer, keep **Authorization caching** turned on. When policy caching is enabled, you can modify the **TTL** value. Setting the **TTL** to zero disables policy caching.

   If you enable caching, your authorizer must return a policy that is applicable to all methods across an API. To enforce a method-specific policy, use the context variables `$context.path` and `$context.httpMethod`.

1. Choose **Create authorizer**.

------
#### [ TOKEN authorizer ]

**To configure a `TOKEN` Lambda authorizer**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Select an API, and then choose **Authorizers**. 

1. Choose **Create authorizer**. 

1. For **Authorizer name**, enter a name for the authorizer.

1. For **Authorizer type**, select **Lambda**. 

1. For **Lambda function**, select the AWS Region where you created your Lambda authorizer function, and then enter the function name.

1. Keep **Lambda invoke role** blank to let the API Gateway REST API console set a resource-based policy. The policy grants API Gateway permissions to invoke the Lambda authorizer function. You can also choose to enter the name of an IAM role to allow API Gateway to invoke the Lambda authorizer function. For an example role, see [Create an assumable IAM role](integrating-api-with-aws-services-lambda.md#api-as-lambda-proxy-setup-iam-role-policies). 

1. For **Lambda event payload**, select **Token**.

1. For **Token source**, enter the header name that contains the authorization token. The caller must include a header of this name to send the authorization token to the Lambda authorizer.

1. (Optional) For **Token validation**, enter a RegEx statement. API Gateway performs initial validation of the input token against this expression and invokes the authorizer upon successful validation.

1. To cache the authorization policy generated by the authorizer, keep **Authorization caching** turned on. When policy caching is enabled, the header name specified in **Token source** becomes the cache key. When policy caching is enabled, you can modify the **TTL** value. Setting the **TTL** to zero disables policy caching. 

   If you enable caching, your authorizer must return a policy that is applicable to all methods across an API. To enforce a method-specific policy, you can turn off **Authorization caching**.

1. Choose **Create authorizer**.

------

After your create your Lambda authorizer, you can test it. The following procedure shows how to test your Lambda authorizer.

------
#### [ REQUEST authorizer ]

**To test a `REQUEST` Lambda authorizer**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Select the name of your authorizer.

1. Under **Test authorizer**, enter a value for your identity source.

   If you are using the [Example `REQUEST` authorizer Lambda function](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-request-lambda-function-create), do the following:

   1. Select **Header** and enter **headerValue1**, and then choose **Add parameter**.

   1. Under **Identity source type**, select **Query string** and enter **queryValue1**, and then choose **Add parameter**.

   1. Under **Identity source type**, select **Stage variable** and enter **stageValue1**.

   You can't modify the context variables for the test invocation, but you can modify the **API Gateway Authorizer** test event template for your Lambda function. Then, you can test your Lambda authorizer function with modified context variables. For more information, see [Testing Lambda functions in the console](https://docs.aws.amazon.com/lambda/latest/dg/testing-functions.html) in the *AWS Lambda Developer Guide*.

1. Choose **Test authorizer**.

------
#### [ TOKEN authorizer ]

**To test a `TOKEN` Lambda authorizer**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Select the name of your authorizer.

1. Under **Test authorizer**, enter a value for your token.

   If you are using the [Example `TOKEN` authorizer Lambda function](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-token-lambda-function-create), do the following:

   1. For the **authorizationToken**, enter **allow**.

1. Choose **Test authorizer**.

    If your Lambda authorizer successfully denies a request in the test environment, the test responds with a `200 OK` HTTP response. However, outside of the test environment, API Gateway returns a `403 Forbidden` HTTP response and the method request fails.

------

## Configure a Lambda authorizer (AWS CLI)
<a name="configure-api-gateway-lambda-authorization-cli"></a>

The following [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-authorizer.html) command shows to create a Lambda authorizer using the AWS CLI.

------
#### [ REQUEST authorizer ]

The following [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-authorizer.html) command creates a `REQUEST` authorizer and uses the `Authorizer` header and `accountId` context variable as identity sources:

```
aws apigateway create-authorizer \
    --rest-api-id 1234123412 \
    --name 'First_Request_Custom_Authorizer' \
    --type REQUEST \
    --authorizer-uri 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123412341234:function:customAuthFunction/invocations' \
    --identity-source 'method.request.header.Authorization,context.accountId' \
    --authorizer-result-ttl-in-seconds 300
```

------
#### [ TOKEN authorizer ]

The following [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-authorizer.html) command creates a `TOKEN` authorizer and uses the `Authorization` header as the identity source:

```
aws apigateway create-authorizer \
    --rest-api-id 1234123412 \
    --name 'First_Token_Custom_Authorizer' \
    --type TOKEN \
    --authorizer-uri 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123412341234:function:customAuthFunction/invocations' \
    --identity-source 'method.request.header.Authorization' \
    --authorizer-result-ttl-in-seconds 300
```

------

After your create your Lambda authorizer, you can test it. The following [test-invoke-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigateway/test-invoke-authorizer.html) command tests a Lambda authorizer:

```
aws apigateway test-invoke-authorizer --rest-api-id 1234123412 \
   --authorizer-id efg1234 \
   --headers Authorization='Value'
```

## Configure a method to use a Lambda authorizer (console)
<a name="configure-api-gateway-lambda-authorization-method-console"></a>

After you configure your Lambda authorizer, you must attach it to a method for your API. If your authorizer uses authorization caching, make sure you update the policy to control access for the additional method.

**To configure an API method to use a Lambda authorizer**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Select an API.

1. Choose **Resources**, and then choose a new method or choose an existing method.

1. On the **Method request** tab, under **Method request settings**, choose **Edit**. 

1. For **Authorizer**, from the dropdown menu, select the Lambda authorizer you just created. 

1.  (Optional) If you want to pass the authorization token to the backend, choose **HTTP request headers**. Choose **Add header**, and then add the name of the authorization header. For **Name**, enter the header name that matches the **Token source** name you specified when you created the Lambda authorizer for the API. This step does not apply to `REQUEST` authorizers. 

1. Choose **Save**.

1. Choose **Deploy API** to deploy the API to a stage. For a `REQUEST` authorizer using stage variables, you must also define the required stage variables and specify their values while on the **Stages ** page.

## Configure a method to use a Lambda authorizer (AWS CLI)
<a name="configure-api-gateway-lambda-authorization-method-cli"></a>

After you configure your Lambda authorizer, you must attach it to a method for your API. You can create a new method or use a patch operation to attach an authorizer to an existing method. If your authorizer uses authorization caching, make sure you update the policy to control access for the additional method.

The following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command creates a new method that uses an Lambda authorizer:

```
aws apigateway put-method --rest-api-id 1234123412 \
  --resource-id a1b2c3 \
  --http-method PUT \
  --authorization-type CUSTOM \
  --authorizer-id efg1234
```

The following [update-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-method.html) command update an existing method to use a Lambda authorizer:

```
aws apigateway update-method \
    --rest-api-id 1234123412 \
    --resource-id a1b2c3 \
    --http-method PUT \
    --patch-operations op="replace",path="/authorizationType",value="CUSTOM" op="replace",path="/authorizerId",value="efg1234"
```

# Input to an API Gateway Lambda authorizer
<a name="api-gateway-lambda-authorizer-input"></a>

The following section explains the format of the input from API Gateway to a Lambda authorizer.

## `TOKEN` input format
<a name="w2aac15b9c23c25c19b5"></a>

 For a Lambda authorizer (formerly known as a custom authorizer) of the `TOKEN` type, you must specify a custom header as the **Token Source** when you configure the authorizer for your API. The API client must pass the required authorization token in that header in the incoming request. Upon receiving the incoming method request, API Gateway extracts the token from the custom header. It then passes the token as the `authorizationToken` property of the `event` object of the Lambda function, in addition to the method ARN as the `methodArn` property: 

```
{
    "type":"TOKEN",
    "authorizationToken":"{caller-supplied-token}",
    "methodArn":"arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}
```

 In this example, the `type` property specifies the authorizer type, which is a `TOKEN` authorizer. The `{caller-supplied-token}` originates from the authorization header in a client request, and can be any string value. The `methodArn` is the ARN of the incoming method request and is populated by API Gateway in accordance with the Lambda authorizer configuration. 

## `REQUEST` input format
<a name="w2aac15b9c23c25c19b7"></a>

For a Lambda authorizer of the `REQUEST` type, API Gateway passes request parameters to the authorizer Lambda function as part of the `event` object. The request parameters include headers, path parameters, query string parameters, stage variables, and some of request context variables. The API caller can set the path parameters, headers, and query string parameters. The API developer must set the stage variables during the API deployment and API Gateway provides the request context at run time. 

**Note**  
Path parameters can be passed as request parameters to the Lambda authorizer function, but they cannot be used as identity sources.

 The following example shows an input to a `REQUEST` authorizer for an API method (`GET /request`) with a proxy integration: 

```
{
  "type": "REQUEST",
  "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "resource": "/request",
  "path": "/request",
  "httpMethod": "GET",
  "headers": {
    "X-AMZ-Date": "20170718T062915Z",
    "Accept": "*/*",
    "HeaderAuth1": "headerValue1",
    "CloudFront-Viewer-Country": "US",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Is-Mobile-Viewer": "false",
    "User-Agent": "..."
  },
  "queryStringParameters": {
    "QueryString1": "queryValue1"
  },
  "pathParameters": {},
  "stageVariables": {
    "StageVar1": "stageValue1"
  },
  "requestContext": {
    "path": "/request",
    "accountId": "123456789012",
    "resourceId": "05c7jb",
    "stage": "test",
    "requestId": "...",
    "identity": {
      "apiKey": "...",
      "sourceIp": "...",
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "resourcePath": "/request",
    "httpMethod": "GET",
    "apiId": "abcdef123"
  }
}
```

 The `requestContext` is a map of key-value pairs and corresponds to the [\$1context](api-gateway-mapping-template-reference.md#context-variable-reference) variable. Its outcome is API-dependent.

 API Gateway might add new keys to the map. For more information about Lambda function input in Lambda proxy integration, see [Input format of a Lambda function for proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format). 

# Output from an API Gateway Lambda authorizer
<a name="api-gateway-lambda-authorizer-output"></a>

A Lambda authorizer function's output is a dictionary-like object, which must include the principal identifier (`principalId`) and a policy document (`policyDocument`) containing a list of policy statements. The output can also include a `context` map containing key-value pairs. If the API uses a usage plan (the [https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apiKeySource](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apiKeySource) is set to `AUTHORIZER`), the Lambda authorizer function must return one of the usage plan's API keys as the `usageIdentifierKey` property value.

The following shows an example of this output. 

------
#### [ JSON ]

****  

```
{
  "principalId": "yyyyyyyy", 
  "policyDocument": {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow|Deny",
        "Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
      }
    ]
  },
  "context": {
    "stringKey": "value",
    "numberKey": "1",
    "booleanKey": "true"
  },
  "usageIdentifierKey": "{api-key}"
}
```

------

 Here, a policy statement specifies whether to allow or deny (`Effect`) the API Gateway execution service to invoke (`Action`) the specified API method (`Resource`). You might need to control access to multiple resources based on your authorizer. You can use a wild card (`*`) to specify a resource type (method). For information about setting valid policies for calling an API, see [Statement reference of IAM policies for executing API in API Gateway](api-gateway-control-access-using-iam-policies-to-invoke-api.md#api-gateway-calling-api-permissions). 

For an authorization-enabled method ARN, e.g., `arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]`, the maximum length is 1600 bytes. The path parameter values, the size of which are determined at run time, can cause the ARN length to exceed the limit. When this happens, the API client will receive a `414 Request URI too long` response. 

In addition, the Resource ARN, as shown in the policy statement output by the authorizer, is currently limited to 512 characters long. For this reason, you must not use URI with a JWT token of a significant length in a request URI. You can safely pass the JWT token in a request header, instead.

 You can access the `principalId` value in a mapping template using the `$context.authorizer.principalId` variable. This is useful if you want to pass the value to the backend. For more information, see [Context variables for data transformations](api-gateway-mapping-template-reference.md#context-variable-reference). 

 You can access the `stringKey`, `numberKey`, or `booleanKey` value (for example, `"value"`, `"1"`, or `"true"`) of the `context` map in a mapping template by calling `$context.authorizer.stringKey`, `$context.authorizer.numberKey`, or `$context.authorizer.booleanKey`, respectively. The returned values are all stringified. Notice that you cannot set a JSON object or array as a valid value of any key in the `context` map. 

 You can use the `context` map to return cached credentials from the authorizer to the backend, using an integration request mapping template. This enables the backend to provide an improved user experience by using the cached credentials to reduce the need to access the secret keys and open the authorization tokens for every request. 

 For the Lambda proxy integration, API Gateway passes the `context` object from a Lambda authorizer directly to the backend Lambda function as part of the input `event`. You can retrieve the `context` key-value pairs in the Lambda function by calling `$event.requestContext.authorizer.key`. 

`{api-key}` stands for an API key in the API stage's usage plan. For more information, see [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md).

 The following shows example output from the example Lambda authorizer. The example output contains a policy statement to block (`Deny`) calls to the `GET` method for the `dev` stage of an API (`ymy8tbxw7b`) of an AWS account (`123456789012`).

------
#### [ JSON ]

****  

```
{
  "principalId": "user",
  "policyDocument": {
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Deny",
        "Resource": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/dev/GET/"
      }
    ]
  }
}
```

------

# Call an API with an API Gateway Lambda authorizer
<a name="call-api-with-api-gateway-lambda-authorization"></a>

 Having configured the Lambda authorizer (formerly known as the custom authorizer) and deployed the API, you should test the API with the Lambda authorizer enabled. For this, you need a REST client, such as cURL or [Postman](https://www.postman.com/). For the following examples, we use Postman. 

**Note**  
 When calling an authorizer-enabled method, API Gateway does not log the call to CloudWatch if the required token for the `TOKEN` authorizer is not set, is null, or is invalidated by the specified **Token validation expression**. Similarly, API Gateway does not log the call to CloudWatch if any of the required identity sources for the `REQUEST` authorizer are not set, are null, or are empty.

 In the following, we show how to use Postman to call or test an API with a Lambda `TOKEN` authorizer. The method can be applied to calling an API with a Lambda `REQUEST` authorizer, if you specify the required path, header, or query string parameters explicitly. 

**To call an API with the custom `TOKEN` authorizer**

1.  Open **Postman**, choose the **GET** method, and paste the API's **Invoke URL** into the adjacent URL field. 

    Add the Lambda authorization token header and set the value to `allow`. Choose **Send**.   
![\[Call API with Lambda authorization allow token\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/custom-auth-call-api-with-allow-token.png)

    The response shows that the API Gateway Lambda authorizer returns a **200 OK** response and successfully authorizes the call to access the HTTP endpoint (http://httpbin.org/get) integrated with the method. 

1.  Still in Postman, change the Lambda authorization token header value to `deny`. Choose **Send**.   
![\[Call API with Lambda authorization deny token\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/custom-auth-call-api-with-deny-token.png)

   The response shows that the API Gateway Lambda authorizer returns a **403 Forbidden** response without authorizing the call to access the HTTP endpoint.

1.  In Postman, change the Lambda authorization token header value to `unauthorized` and choose **Send**.   
![\[Call API with Lambda authorization unauthorized token\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/custom-auth-call-api-with-unauthorized-token.png)

    The response shows that API Gateway returns a **401 Unauthorized** response without authorizing the call to access the HTTP endpoint. 

1.  Now, change the Lambda authorization token header value to `fail`. Choose **Send**.   
![\[Call API with Lambda authorization fail token\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/custom-auth-call-api-with-fail-token.png)

    The response shows that API Gateway returns a **500 Internal Server Error** response without authorizing the call to access the HTTP endpoint. 

# Configure a cross-account API Gateway Lambda authorizer
<a name="apigateway-lambda-authorizer-cross-account-lambda-authorizer"></a>

You can now also use an AWS Lambda function from a different AWS account as your API authorizer function. Each account can be in any region where Amazon API Gateway is available. The Lambda authorizer function can use bearer token authentication strategies such as OAuth or SAML. This makes it easy to centrally manage and share a central Lambda authorizer function across multiple API Gateway APIs.

In this section, we show how to configure a cross-account Lambda authorizer function using the Amazon API Gateway console.

These instructions assume that you already have an API Gateway API in one AWS account and a Lambda authorizer function in another account.

## Configure a cross-account Lambda authorizer using the API Gateway console
<a name="apigateway-cross-account-lambda-auth-configure-cross-account-authorizer"></a>

Log in to the Amazon API Gateway console in the account that has your API in it, and then do the following:

1. Choose your API, and then in the main navigation pane, choose **Authorizers**.

1. Choose **Create authorizer**. 

1. For **Authorizer name**, enter a name for the authorizer.

1. For **Authorizer type**, select **Lambda**.

1. For **Lambda Function**, enter the full ARN for the Lambda authorizer function that you have in your second account.
**Note**  
In the Lambda console, you can find the ARN for your function in the upper right corner of the console window.

1. A warning with an `aws lambda add-permission` command string will appear. This policy grants API Gateway permission to invoke the authorizer Lambda function. Copy the command and save it for later. You run the command after you create the authorizer.

1. For **Lambda event payload**, select either **Token** for a `TOKEN` authorizer or **Request** for a `REQUEST` authorizer.

1. Depending on the choice of the previous step, do one of the following:

   1.  For the **Token** option, do the following: 
      + For **Token source**, enter the header name that contains the authorization token. The API client must include a header of this name to send the authorization token to the Lambda authorizer. 
      + Optionally, for **Token validation**, enter a RegEx statement. API Gateway performs initial validation of the input token against this expression and invokes the authorizer upon successful validation. This helps reduce calls to your API. 
      + To cache the authorization policy generated by the authorizer, keep **Authorization caching** turned on. When policy caching is enabled, you can choose to modify the **TTL** value. Setting the **TTL** to zero disables policy caching. When policy caching is enabled, the header name specified in **Token source** becomes the cache key. If multiple values are passed to this header in the request, all values will become the cache key, with the order preserved.
**Note**  
The default **TTL** value is 300 seconds. The maximum value is 3600 seconds; this limit cannot be increased.

   1. For the **Request** option, do the following:
      + For **Identity source type**, select a parameter type. Supported parameter types are `Header`, `Query string`, `Stage variable`, and `Context`. To add more identity sources, choose **Add parameter**. 
      + To cache the authorization policy generated by the authorizer, keep **Authorization caching** turned on. When policy caching is enabled, you can choose to modify the **TTL** value. Setting the **TTL** to zero disables policy caching.

        API Gateway uses the specified identity sources as the request authorizer caching key. When caching is enabled, API Gateway calls the authorizer's Lambda function only after successfully verifying that all the specified identity sources are present at runtime. If a specified identity source is missing, null, or empty, API Gateway returns a `401 Unauthorized` response without calling the authorizer Lambda function. 

        When multiple identity sources are defined, they are all used to derive the authorizer's cache key. Changing any of the cache key parts causes the authorizer to discard the cached policy document and generate a new one. If a header with multiple values is passed in the request, then all values will be part of the cache key, with the order preserved. 
      + When caching is turned off, it is not necessary to specify an identity source.
**Note**  
 To enable caching, your authorizer must return a policy that is applicable to all methods across an API. To enforce method-specific policy, you can turn off **Authorization caching**. 

1. Choose **Create authorizer**.

1. Paste the `aws lambda add-permission` command string that you copied in a previous step into an AWS CLI window that is configured for your second account. Replace `AUTHORIZER_ID` with your authorizer's ID. This will grant your first account access to your second account's Lambda authorizer function.

# Control access based on an identity’s attributes with Verified Permissions
<a name="apigateway-lambda-authorizer-verified-permissions"></a>

Use Amazon Verified Permissions to control access to your API Gateway API. When you use API Gateway with Verified Permissions, Verified Permissions creates a Lambda authorizer that uses fine-grained authorization decisions to control access to your API. Verified Permissions authorizes callers based on a policy store schema and policies using the Cedar policy language to define fine-grained permissions for application users. For more information, see [Create a policy store with a connected API and identity provider](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/getting-started-api-policy-store.html) in the *Amazon Verified Permissions User Guide*.

Verified Permissions supports Amazon Cognito user pools or OpenID Connect (OIDC) identity providers as identity sources. Verified Permissions presumes that the principal has been previously identified and authenticated. Verified Permissions is only supported for Regional and edge-optimized REST APIs.

## Create a Lambda authorizer using Verified Permissions
<a name="apigateway-lambda-authorizer-verified-permissions-attach"></a>

Verified Permissions creates a Lambda authorizer to determine if a principal is allowed to perform an action on your API. You create the Cedar policy that Verified Permissions uses to perform its authorization tasks.

The following is an example Cedar policy that allows access to invoke an API based on the Amazon Cognito user pool, `us-east-1_ABC1234` for the `developer` group on the `GET /users` resource of an API. Verified Permissions determines group membership by parsing the bearer token for the caller's identity. 

```
permit(
  principal in MyAPI::UserGroup::"us-east-1_ABC1234|developer",
  action in [ MyAPI::Action::"get /users" ],
  resource
  );
```

Optionally, Verified Permissions can attach the authorizer to the methods of your API. On production stages for your API, we recommend that you don't allow Verified Permissions to attach the authorizer for you.

The following list show how to configure Verified Permissions to attach or not to attach the Lambda authorizer to the method request of your API's methods.

**Attach the authorizer for you (AWS Management Console)**  
When you choose **Create policy store** in the Verified Permissions console, on the **Deploy app integration** page, choose **Now**.

**Don't attach the authorizer for you (AWS Management Console)**  
When you choose **Create policy store** in the Verified Permissions console, on the **Deploy app integration** page, choose **Later**.  
Verified Permissions still creates a Lambda authorizer for you. The Lambda authorizer starts with `AVPAuthorizerLambda-`. For more instructions on how to attach your authorizer on a method, see [Configure a method to use a Lambda authorizer (console)](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-method-console).

**Attach the authorizer for you (CloudFormation)**  
In the Verified Permissions-generated CloudFormation template, in the `Conditions` section, set `"Ref": "shouldAttachAuthorizer"` to `true`.

**Don't attach the authorizer for you (CloudFormation)**  
In the Verified Permissions-generated CloudFormation template, in the `Conditions` section, set `"Ref": "shouldAttachAuthorizer"` to `false`.  
Verified Permissions still creates a Lambda authorizer for you. The Lambda authorizer starts with `AVPAuthorizerLambda-`. For more instructions on how to attach your authorizer on a method, see [Configure a method to use a Lambda authorizer (AWS CLI)](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-method-cli).

## Call a Lambda authorizer using Verified Permissions
<a name="apigateway-lambda-authorizer-verified-permissions-call"></a>

You can call your Lambda authorizer by providing an identity or access token in the `Authorization` header. For more information, see [Call an API with an API Gateway Lambda authorizer](call-api-with-api-gateway-lambda-authorization.md).

API Gateway caches the policy that your Lambda authorizer returns for 120 seconds. You can modify the TTL in the API Gateway console or by using the AWS CLI.

# Control access to REST APIs using Amazon Cognito user pools as an authorizer
<a name="apigateway-integrate-with-cognito"></a>

As an alternative to using [IAM roles and policies](permissions.md) or [Lambda authorizers](apigateway-use-lambda-authorizer.md) (formerly known as custom authorizers), you can use an [Amazon Cognito user pool](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html) to control who can access your API in Amazon API Gateway. 

To use an Amazon Cognito user pool with your API, you must first create an authorizer of the `COGNITO_USER_POOLS` type and then configure an API method to use that authorizer. After the API is deployed, the client must first sign the user in to the user pool, obtain an [identity or access token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html) for the user, and then call the API method with one of the tokens, which are typically set to the request's `Authorization` header. The API call succeeds only if the required token is supplied and the supplied token is valid, otherwise, the client isn't authorized to make the call because the client did not have credentials that could be authorized. 

The identity token is used to authorize API calls based on identity claims of the signed-in user. The access token is used to authorize API calls based on the custom scopes of specified access-protected resources. For more information, see [Using Tokens with User Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html) and [Resource Server and Custom Scopes](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html).

To create and configure an Amazon Cognito user pool for your API, you perform the following tasks:
+ Use the Amazon Cognito console, CLI/SDK, or API to create a user pool—or use one that's owned by another AWS account.
+ Use the API Gateway console, CLI/SDK, or API to create an API Gateway authorizer with the chosen user pool.
+ Use the API Gateway console, CLI/SDK, or API to enable the authorizer on selected API methods.

 To call any API methods with a user pool enabled, your API clients perform the following tasks:
+  Use the Amazon Cognito CLI/SDK or API to sign a user in to the chosen user pool, and obtain an identity token or access token. To learn more about using the SDKs, see [Code examples for Amazon Cognito using AWS SDKs](https://docs.aws.amazon.com/cognito/latest/developerguide/service_code_examples.html).
+  Use a client-specific framework to call the deployed API Gateway API and supply the appropriate token in the `Authorization` header.

As the API developer, you must provide your client developers with the user pool ID, a client ID, and possibly the associated client secrets that are defined as part of the user pool. 

**Note**  
To let a user sign in using Amazon Cognito credentials and also obtain temporary credentials to use with the permissions of an IAM role, use [Amazon Cognito Federated Identities](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html). For each API resource endpoint HTTP method, set the authorization type, category `Method Execution`, to `AWS_IAM`. 

In this section, we describe how to create a user pool, how to integrate an API Gateway API with the user pool, and how to invoke an API that's integrated with the user pool. 

**Topics**
+ [Create an Amazon Cognito user pool for a REST API](apigateway-create-cognito-user-pool.md)
+ [Integrate a REST API with an Amazon Cognito user pool](apigateway-enable-cognito-user-pool.md)
+ [Call a REST API integrated with an Amazon Cognito user pool](apigateway-invoke-api-integrated-with-cognito-user-pool.md)
+ [Configure cross-account Amazon Cognito authorizer for a REST API using the API Gateway console](apigateway-cross-account-cognito-authorizer.md)
+ [Create an Amazon Cognito authorizer for a REST API using CloudFormation](apigateway-cognito-authorizer-cfn.md)

# Create an Amazon Cognito user pool for a REST API
<a name="apigateway-create-cognito-user-pool"></a>

Before integrating your API with a user pool, you must create the user pool in Amazon Cognito. Your user pool configuration must follow all [resource quotas for Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/limits.html). All user-defined Amazon Cognito variables such as groups, users, and roles should use only alphanumeric characters. For instructions on how to create a user pool, see [Tutorial: Creating a user pool](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html) in the *Amazon Cognito Developer Guide*.

Note the user pool ID, client ID, and any client secret. The client must provide them to Amazon Cognito for the user to register with the user pool, to sign in to the user pool, and to obtain an identity or access token to be included in requests to call API methods that are configured with the user pool. Also, you must specify the user pool name when you configure the user pool as an authorizer in API Gateway, as described next.

If you're using access tokens to authorize API method calls, be sure to configure the app integration with the user pool to set up the custom scopes that you want on a given resource server. For more information about using tokens with Amazon Cognito user pools, see [Using Tokens with User Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html). For more information about resource servers, see [Defining Resource Servers for Your User Pool](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html).

Note the configured resource server identifiers and custom scope names. You need them to construct the access scope full names for **OAuth Scopes**, which is used by the `COGNITO_USER_POOLS` authorizer. 

![\[Amazon Cognito user pool resource servers and scopes\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/cognito-user-pool-custom-scopes-new-console.png)


# Integrate a REST API with an Amazon Cognito user pool
<a name="apigateway-enable-cognito-user-pool"></a>

After creating an Amazon Cognito user pool, in API Gateway, you must then create a `COGNITO_USER_POOLS` authorizer that uses the user pool. The following procedure shows you how to do this using the API Gateway console.

**Note**  
You can use the [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateAuthorizer.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateAuthorizer.html) action to create a `COGNITO_USER_POOLS` authorizer that uses multiple user pools. You can use up to 1,000 user pools for one `COGNITO_USER_POOLS` authorizer. This limit cannot be increased.

**Important**  
After performing any of the procedures below, you'll need to deploy or redeploy your API to propagate the changes. For more information about deploying your API, see [Deploy REST APIs in API Gateway](how-to-deploy-api.md).

**To create a `COGNITO_USER_POOLS` authorizer by using the API Gateway console**

1. Create a new API, or select an existing API in API Gateway.

1. In the main navigation pane, choose **Authorizers**.

1. Choose **Create authorizer**. 

1. To configure the new authorizer to use a user pool, do the following:

   1.  For **Authorizer name**, enter a name. 

   1. For **Authorizer type**, select **Cognito**.

   1. For **Cognito user pool**, choose the AWS Region where you created your Amazon Cognito and select an available user pool.

      You can use a stage variable to define your user pool. Use the following format for your user pool: `arn:aws:cognito-idp:us-east-2:111122223333:userpool/${stageVariables.MyUserPool}`.

   1.  For **Token source**, enter **Authorization** as the header name to pass the identity or access token that's returned by Amazon Cognito when a user signs in successfully. 

   1. (Optional) Enter a regular expression in the **Token validation** field to validate the `aud` (audience) field of the identity token before the request is authorized with Amazon Cognito. Note that when using an access token this validation rejects the request due to the access token not containing the `aud` field.

   1. Choose **Create authorizer**. 

1. After creating the `COGNITO_USER_POOLS` authorizer, you can test invoke it by supplying an identity token that's provisioned from the user pool. You can't use an access token to test invoke your authorizer.

   You can obtain this identity token by calling the [Amazon Cognito Identity SDK](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-integrate-apps.html) to perform user sign-in. You can also use the [https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) action. If you do not configure any **Authorization scopes**, API Gateway treats the supplied token as an identity token. 

The preceding procedure creates a `COGNITO_USER_POOLS` authorizer that uses the newly created Amazon Cognito user pool. Depending on how you enable the authorizer on an API method, you can use either an identity token or an access token that's provisioned from the integrated user pool.

**To configure a `COGNITO_USER_POOLS` authorizer on methods**

1. Choose **Resources**. Choose a new method or choose an existing method. If necessary, create a resource.

1. On the **Method request** tab, under **Method request settings**, choose **Edit**.

1. For **Authorizer**, from the dropdown menu, select the **Amazon Cognito user pool authorizers** you just created.

1.  To use an identity token, do the following:

   1. Keep **Authorization Scopes** empty.

   1. If needed, in the **Integration request**, add the `$context.authorizer.claims['property-name']` or `$context.authorizer.claims.property-name` expressions in a body-mapping template to pass the specified identity claims property from the user pool to the backend. For simple property names, such as `sub` or `custom-sub`, the two notations are identical. For complex property names, such as `custom:role`, you can't use the dot notation. For example, the following mapping expressions pass the claim's [standard fields](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims) of `sub` and `email` to the backend:

      ```
      {
      	"context" : {
      		"sub" : "$context.authorizer.claims.sub",
      		"email" : "$context.authorizer.claims.email"
      	}
      }
      ```

      If you declared a custom claim field when you configured a user pool, you can follow the same pattern to access the custom fields. The following example gets a custom `role` field of a claim:

      ```
      {
      	"context" : {
      		"role" : "$context.authorizer.claims.role"
          }
      }
      ```

      If the custom claim field is declared as `custom:role`, use the following example to get the claim's property:

      ```
      {
      	"context" : {
      		"role" : "$context.authorizer.claims['custom:role']"
          }
      }
      ```

1.  To use an access token, do the following: 

   1. For **Authorization Scopes**, enter one or more full names of a scope that has been configured when the Amazon Cognito user pool was created. For example, following the example given in [Create an Amazon Cognito user pool for a REST API](apigateway-create-cognito-user-pool.md), one of the scopes is `https://my-petstore-api.example.com/cats.read`. 

      At runtime, the method call succeeds if any scope that's specified on the method in this step matches a scope that's claimed in the incoming token. Otherwise, the call fails with a `401 Unauthorized` response.

   1.  Choose **Save**.

1. Repeat these steps for other methods that you choose.

With the `COGNITO_USER_POOLS` authorizer, if the **OAuth Scopes** option isn't specified, API Gateway treats the supplied token as an identity token and verifies the claimed identity against the one from the user pool. Otherwise, API Gateway treats the supplied token as an access token and verifies the access scopes that are claimed in the token against the authorization scopes declared on the method.

Instead of using the API Gateway console, you can also enable an Amazon Cognito user pool on a method by specifying an OpenAPI definition file and importing the API definition into API Gateway.

**To import a COGNITO\$1USER\$1POOLS authorizer with an OpenAPI definition file**

1. Create (or export) an OpenAPI definition file for your API.

1. Specify the `COGNITO_USER_POOLS` authorizer (`MyUserPool`) JSON definition as part of the `securitySchemes` section in OpenAPI 3.0 or the `securityDefinitions` section in Open API 2.0 as follows:

------
#### [ OpenAPI 3.0 ]

   ```
     "securitySchemes": {
       "MyUserPool": {
         "type": "apiKey",
         "name": "Authorization",
         "in": "header",
         "x-amazon-apigateway-authtype": "cognito_user_pools",
         "x-amazon-apigateway-authorizer": {
           "type": "cognito_user_pools",
           "providerARNs": [
             "arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}"
           ]
         }
       }
   ```

------
#### [ OpenAPI 2.0 ]

   ```
     "securityDefinitions": {
       "MyUserPool": {
         "type": "apiKey",
         "name": "Authorization",
         "in": "header",
         "x-amazon-apigateway-authtype": "cognito_user_pools",
         "x-amazon-apigateway-authorizer": {
           "type": "cognito_user_pools",
           "providerARNs": [
             "arn:aws:cognito-idp:{region}:{account_id}:userpool/{user_pool_id}"
           ]
         }
       }
   ```

------

1. To use the identity token for method authorization, add `{ "MyUserPool": [] }` to the `security` definition of the method, as shown in the following GET method on the root resource.

   ```
     "paths": {
       "/": {
         "get": {
           "consumes": [
             "application/json"
           ],
           "produces": [
             "text/html"
           ],
           "responses": {
             "200": {
               "description": "200 response",
               "headers": {
                 "Content-Type": {
                   "type": "string"
                 }
               }
             }
           },
           "security": [
             {
               "MyUserPool": []
             }
           ],        
           "x-amazon-apigateway-integration": {
             "type": "mock",
             "responses": {
               "default": {
                 "statusCode": "200",
                 "responseParameters": {
                   "method.response.header.Content-Type": "'text/html'"
                 },
               }
             },
             "requestTemplates": {
               "application/json": "{\"statusCode\": 200}"
             },
             "passthroughBehavior": "when_no_match"
           }
         },
         ...
      }
   ```

1.  To use the access token for method authorization, change the above security definition to `{ "MyUserPool": [resource-server/scope, ...] }`:

   ```
     "paths": {
       "/": {
         "get": {
           "consumes": [
             "application/json"
           ],
           "produces": [
             "text/html"
           ],
           "responses": {
             "200": {
               "description": "200 response",
               "headers": {
                 "Content-Type": {
                   "type": "string"
                 }
               }
             }
           },
           "security": [
             {
               "MyUserPool": ["https://my-petstore-api.example.com/cats.read", "http://my.resource.com/file.read"]
             }
           ],        
           "x-amazon-apigateway-integration": {
             "type": "mock",
             "responses": {
               "default": {
                 "statusCode": "200",
                 "responseParameters": {
                   "method.response.header.Content-Type": "'text/html'"
                 },
               }
             },
             "requestTemplates": {
               "application/json": "{\"statusCode\": 200}"
             },
             "passthroughBehavior": "when_no_match"
           }
         },
         ...
      }
   ```

1. If needed, you can set other API configuration settings by using the appropriate OpenAPI definitions or extensions. For more information, see [OpenAPI extensions for API Gateway](api-gateway-swagger-extensions.md).

# Call a REST API integrated with an Amazon Cognito user pool
<a name="apigateway-invoke-api-integrated-with-cognito-user-pool"></a>

To call a method with a user pool authorizer configured, the client must do the following: 
+ Enable the user to sign up with the user pool.
+ Enable the user to sign in to the user pool.
+ Obtain an [identity or access token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html) of the signed-in user from the user pool.
+ Include the token in the `Authorization` header (or another header you specified when you created the authorizer).

You can use [AWS Amplify]() to perform these tasks. See [Integrating Amazon Cognito With Web and Mobile Apps](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-integrate-apps.html) for more information.
+ For Android, see [Getting Started with Amplify for Android](https://docs.amplify.aws/android/build-a-backend/auth/).
+ To use iOS see [Getting started with Amplify for iOS](https://docs.amplify.aws/swift/build-a-backend/auth/).
+ To use JavaScript, see [Getting Started with Amplify for Javascript](https://docs.amplify.aws/javascript/build-a-backend/auth/).

# Configure cross-account Amazon Cognito authorizer for a REST API using the API Gateway console
<a name="apigateway-cross-account-cognito-authorizer"></a>

You can now also use a Amazon Cognito user pool from a different AWS account as your API authorizer. The Amazon Cognito user pool can use bearer token authentication strategies such as OAuth or SAML. This makes it easy to centrally manage and share a central Amazon Cognito user pool authorizer across multiple API Gateway APIs.

In this section, we show how to configure a cross-account Amazon Cognito user pool using the Amazon API Gateway console.

These instructions assume that you already have an API Gateway API in one AWS account and a Amazon Cognito user pool in another account.

## Create a cross-account Amazon Cognito authorizer for a REST API
<a name="apigateway-configure-cross-account-cognito-authorizer"></a>

Log in to the Amazon API Gateway console in the account that has your API in it, and then do the following:

1. Create a new API, or select an existing API in API Gateway.

1. In the main navigation pane, choose **Authorizers**.

1. Choose **Create authorizer**.

1. To configure the new authorizer to use a user pool, do the following:

   1.  For **Authorizer name**, enter a name. 

   1. For **Authorizer type**, select **Cognito**.

   1. For **Cognito user pool**, enter the full ARN for the user pool that you have in your second account.
**Note**  
In the Amazon Cognito console, you can find the ARN for your user pool in the **Pool ARN** field of the **General Settings** pane.

   1.  For **Token source**, enter **Authorization** as the header name to pass the identity or access token that's returned by Amazon Cognito when a user signs in successfully. 

   1. (Optional) Enter a regular expression in the **Token validation** field to validate the `aud` (audience) field of the identity token before the request is authorized with Amazon Cognito. Note that when using an access token this validation rejects the request due to the access token not containing the `aud` field.

   1. Choose **Create authorizer**.

# Create an Amazon Cognito authorizer for a REST API using CloudFormation
<a name="apigateway-cognito-authorizer-cfn"></a>

You can use CloudFormation to create an Amazon Cognito user pool and an Amazon Cognito authorizer. The example CloudFormation template does the following: 
+ Create an Amazon Cognito user pool. The client must first sign the user in to the user pool and obtain an [identity or access token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html). If you're using access tokens to authorize API method calls, be sure to configure the app integration with the user pool to set up the custom scopes that you want on a given resource server.
+ Creates an API Gateway API with a `GET` method.
+ Creates an Amazon Cognito authorizer that uses the `Authorization` header as the token source.

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      AccountRecoverySetting:
        RecoveryMechanisms:
          - Name: verified_phone_number
            Priority: 1
          - Name: verified_email
            Priority: 2
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: true
      EmailVerificationMessage: The verification code to your new account is {####}
      EmailVerificationSubject: Verify your new account
      SmsVerificationMessage: The verification code to your new account is {####}
      VerificationMessageTemplate:
        DefaultEmailOption: CONFIRM_WITH_CODE
        EmailMessage: The verification code to your new account is {####}
        EmailSubject: Verify your new account
        SmsMessage: The verification code to your new account is {####}
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
  CogAuthorizer:
    Type: AWS::ApiGateway::Authorizer
    Properties:
      Name: CognitoAuthorizer
      RestApiId:
        Ref: Api
      Type: COGNITO_USER_POOLS
      IdentitySource: method.request.header.Authorization
      ProviderARNs:
        - Fn::GetAtt:
            - UserPool
            - Arn
  Api:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: MyCogAuthApi
  ApiDeployment:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId:
        Ref: Api
    DependsOn:
      - CogAuthorizer
      - ApiGET
  ApiDeploymentStageprod:
    Type: AWS::ApiGateway::Stage
    Properties:
      RestApiId:
        Ref: Api
      DeploymentId:
        Ref: ApiDeployment
      StageName: prod
  ApiGET:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: GET
      ResourceId:
        Fn::GetAtt:
          - Api
          - RootResourceId
      RestApiId:
        Ref: Api
      AuthorizationType: COGNITO_USER_POOLS
      AuthorizerId:
        Ref: CogAuthorizer
      Integration:
        IntegrationHttpMethod: GET
        Type: HTTP_PROXY
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
Outputs:
  ApiEndpoint:
    Value:
      Fn::Join:
        - ""
        - - https://
          - Ref: Api
          - .execute-api.
          - Ref: AWS::Region
          - "."
          - Ref: AWS::URLSuffix
          - /
          - Ref: ApiDeploymentStageprod
          - /
```

# Integrations for REST APIs in API Gateway
<a name="how-to-integration-settings"></a>

 After setting up an API method, you must integrate it with an endpoint in the backend. A backend endpoint is also referred to as an integration endpoint and can be a Lambda function, an HTTP webpage, or an AWS service action. 

As with the API method, the API integration has an integration request and an integration response. An integration request encapsulates an HTTP request received by the backend. It might or might not differ from the method request submitted by the client. An integration response is an HTTP response encapsulating the output returned by the backend.

Setting up an integration request involves the following: configuring how to pass client-submitted method requests to the backend; configuring how to transform the request data, if necessary, to the integration request data; and specifying which Lambda function to call, specifying which HTTP server to forward the incoming request to, or specifying the AWS service action to invoke.

Setting up an integration response (applicable to non-proxy integrations only) involves the following: configuring how to pass the backend-returned result to a method response of a given status code, configuring how to transform specified integration response parameters to preconfigured method response parameters, and configuring how to map the integration response body to the method response body according to the specified body-mapping templates. 

Programmatically, an integration request is encapsulated by the [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource and an integration response by the [https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) resource of API Gateway. 

To set up an integration request, you create an [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource and use it to configure the integration endpoint URL. You then set the IAM permissions to access the backend, and specify mappings to transform the incoming request data before passing it to the backend. To set up an integration response for non-proxy integration, you create an [https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) resource and use it to set its target method response. You then configure how to map backend output to the method response.

**Topics**
+ [Set up an integration request in API Gateway](api-gateway-integration-settings-integration-request.md)
+ [Set up an integration response in API Gateway](api-gateway-integration-settings-integration-response.md)
+ [Lambda integrations for REST APIs in API Gateway](set-up-lambda-integrations.md)
+ [HTTP integrations for REST APIs in API Gateway](setup-http-integrations.md)
+ [Stream the integration response for your proxy integrations in API Gateway](response-transfer-mode.md)
+ [Private integrations for REST APIs in API Gateway](private-integration.md)
+ [Mock integrations for REST APIs in API Gateway](how-to-mock-integration.md)

# Set up an integration request in API Gateway
<a name="api-gateway-integration-settings-integration-request"></a>

To set up an integration request, you perform the following required and optional tasks:

1.  Choose an integration type that determines how method request data is passed to the backend.

1.  For non-mock integrations, specify an HTTP method and the URI of the targeted integration endpoint, except for the `MOCK` integration.

1.  For integrations with Lambda functions and other AWS service actions, set an IAM role with required permissions for API Gateway to call the backend on your behalf.

1.  For non-proxy integrations, set necessary parameter mappings to map predefined method request parameters to appropriate integration request parameters.

1.  For non-proxy integrations, set necessary body mappings to map the incoming method request body of a given content type according to the specified mapping template.

1.  For non-proxy integrations, specify the condition under which the incoming method request data is passed through to the backend as-is. 

1.  Optionally, specify how to handle type conversion for a binary payload.

1.  Optionally, declare a cache namespace name and cache key parameters to enable API caching. 

 Performing these tasks involves creating an [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource of API Gateway and setting appropriate property values. You can do so using the API Gateway console, AWS CLI commands, an AWS SDK, or the API Gateway REST API. 

**Topics**
+ [Basic tasks of an API integration request](integration-request-basic-setup.md)
+ [Choose an API Gateway API integration type](api-gateway-api-integration-types.md)
+ [Set up a proxy integration with a proxy resource](api-gateway-set-up-simple-proxy.md)
+ [Set up an API integration request using the API Gateway console](how-to-method-settings-console.md)

# Basic tasks of an API integration request
<a name="integration-request-basic-setup"></a>

 An integration request is an HTTP request that API Gateway submits to the backend, passing along the client-submitted request data, and transforming the data, if necessary. The HTTP method (or verb) and URI of the integration request are dictated by the backend (that is, the integration endpoint). They can be the same as or different from the method request's HTTP method and URI, respectively. 

For example, when a Lambda function returns a file that is fetched from Amazon S3, you can expose this operation intuitively as a `GET` method request to the client even though the corresponding integration request requires that a `POST` request be used to invoke the Lambda function. For an HTTP endpoint, it is likely that the method request and the corresponding integration request both use the same HTTP verb. However, this is not required. You can integrate the following method request: 

```
GET /{var}?query=value
Host: api.domain.net
```

With the following integration request: 

```
POST /
Host: service.domain.com
Content-Type: application/json
Content-Length: ...

{
   path: "{var}'s value",
   type: "value"
}
```

 As an API developer, you can use whatever HTTP verb and URI for a method request suit your requirements. But you must follow the requirements of the integration endpoint. When the method request data differs from the integration request data, you can reconcile the difference by providing mappings from the method request data to the integration request data. 

In the preceding examples, the mapping translates the path variable (`{var}`) and the query parameter (`query`) values of the `GET` method request to the values of the integration request's payload properties of `path` and `type`. Other mappable request data includes request headers and body. These are described in [Parameter mapping for REST APIs in API Gateway](rest-api-parameter-mapping.md).

When setting up the HTTP or HTTP proxy integration request, you assign the backend HTTP endpoint URL as the integration request URI value. For example, in the PetStore API, the method request to get a page of pets has the following integration request URI: 

```
http://petstore-demo-endpoint.execute-api.com/petstore/pets
```

When setting up the Lambda or Lambda proxy integration, you assign the Amazon Resource Name (ARN) for invoking the Lambda function as the integration request URI value. This ARN has the following format:

```
arn:aws:apigateway:api-region:lambda:path//2015-03-31/functions/arn:aws:lambda:lambda-region:account-id:function:lambda-function-name/invocations
```

The part after `arn:aws:apigateway:api-region:lambda:path/`, namely, `/2015-03-31/functions/arn:aws:lambda:lambda-region:account-id:function:lambda-function-name/invocations`, is the REST API URI path of the Lambda [Invoke](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html) action. If you use the API Gateway console to set up the Lambda integration, API Gateway creates the ARN and assigns it to the integration URI after prompting you to choose the `lambda-function-name` from a region. 

When setting up the integration request with another AWS service action, the integration request URI is also an ARN, similar to the integration with the Lambda `Invoke` action. For example, for the integration with the [GetBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) action of Amazon S3, the integration request URI is an ARN of the following format:

```
arn:aws:apigateway:api-region:s3:path/{bucket}
```

The integration request URI is of the path convention to specify the action, where `{bucket}` is the placeholder of a bucket name. Alternatively, an AWS service action can be referenced by its name. Using the action name, the integration request URI for the `GetBucket` action of Amazon S3 becomes the following:

```
arn:aws:apigateway:api-region:s3:action/GetBucket
```

With the action-based integration request URI, the bucket name (`{bucket}`) must be specified in the integration request body (`{ Bucket: "{bucket}" }`), following the input format of `GetBucket` action. 

For AWS integrations, you must also configure [credentials](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#credentials) to allow API Gateway to call the integrated actions. You can create a new or choose an existing IAM role for API Gateway to call the action and then specify the role using its ARN. The following shows an example of this ARN: 

```
arn:aws:iam::account-id:role/iam-role-name
```

This IAM role must contain a policy to allow the action to be executed. It must also have API Gateway declared (in the role's trust relationship) as a trusted entity to assume the role. Such permissions can be granted on the action itself. They are known as resource-based permissions. For the Lambda integration, you can call the Lambda's [addPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html) action to set the resource-based permissions and then set `credentials` to null in the API Gateway integration request.

We discussed the basic integration setup. Advanced settings involve mapping method request data to the integration request data. For more information, see [Data transformations for REST APIs in API Gateway](rest-api-data-transformations.md).

# Choose an API Gateway API integration type
<a name="api-gateway-api-integration-types"></a>



 You choose an API integration type according to the types of integration endpoint you work with and how you want data to pass to and from the integration endpoint. For a Lambda function, you can have the Lambda proxy integration, or the Lambda custom integration. For an HTTP endpoint, you can have the HTTP proxy integration or the HTTP custom integration. For an AWS service action, you have the AWS integration of the non-proxy type only. API Gateway also supports the mock integration, where API Gateway serves as an integration endpoint to respond to a method request.

The Lambda custom integration is a special case of the AWS integration, where the integration endpoint corresponds to the [function-invoking action ](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html)of the Lambda service. 

Programmatically, you choose an integration type by setting the [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#type](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#type) property on the [https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource. For the Lambda proxy integration, the value is `AWS_PROXY`. For the Lambda custom integration and all other AWS integrations, it is `AWS`. For the HTTP proxy integration and HTTP integration, the value is `HTTP_PROXY` and `HTTP`, respectively. For the mock integration, the `type` value is `MOCK`.

The Lambda proxy integration supports a streamlined integration setup with a single Lambda function. The setup is simple and can evolve with the backend without having to tear down the existing setup. For these reasons, it is highly recommended for integration with a Lambda function. 

In contrast, the Lambda custom integration allows for reuse of configured mapping templates for various integration endpoints that have similar requirements of the input and output data formats. The setup is more involved and is recommended for more advanced application scenarios. 

Similarly, the HTTP proxy integration has a streamlined integration setup and can evolve with the backend without having to tear down the existing setup. The HTTP custom integration is more involved to set up, but allows for reuse of configured mapping templates for other integration endpoints. 

The following list summarizes the supported integration types:
+ `AWS`: This type of integration lets an API expose AWS service actions. In `AWS` integration, you must configure both the integration request and integration response and set up necessary data mappings from the method request to the integration request, and from the integration response to the method response.
+  `AWS_PROXY`: This type of integration lets an API method be integrated with the Lambda function invocation action with a flexible, versatile, and streamlined integration setup. This integration relies on direct interactions between the client and the integrated Lambda function. 

  With this type of integration, also known as the Lambda proxy integration, you do not set the integration request or the integration response. API Gateway passes the incoming request from the client as the input to the backend Lambda function. The integrated Lambda function takes the [input of this format](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format) and parses the input from all available sources, including request headers, URL path variables, query string parameters, and applicable body. The function returns the result following this [output format](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format). 

  This is the preferred integration type to call a Lambda function through API Gateway and is not applicable to any other AWS service actions, including Lambda actions other than the function-invoking action. 
+ `HTTP`: This type of integration lets an API expose HTTP endpoints in the backend. With the `HTTP` integration, also known as the HTTP custom integration, you must configure both the integration request and integration response. You must set up necessary data mappings from the method request to the integration request, and from the integration response to the method response.
+  `HTTP_PROXY`: The HTTP proxy integration allows a client to access the backend HTTP endpoints with a streamlined integration setup on single API method. You do not set the integration request or the integration response. API Gateway passes the incoming request from the client to the HTTP endpoint and passes the outgoing response from the HTTP endpoint to the client. 
+ `MOCK`: This type of integration lets API Gateway return a response without sending the request further to the backend. This is useful for API testing because it can be used to test the integration set up without incurring charges for using the backend and to enable collaborative development of an API. 

  In collaborative development, a team can isolate their development effort by setting up simulations of API components owned by other teams by using the `MOCK` integrations. It is also used to return CORS-related headers to ensure that the API method permits CORS access. In fact, the API Gateway console integrates the `OPTIONS` method to support CORS with a mock integration. [Gateway responses](api-gateway-gatewayResponse-definition.md#customize-gateway-responses) are other examples of mock integrations.

# Set up a proxy integration with a proxy resource
<a name="api-gateway-set-up-simple-proxy"></a>

To set up a proxy integration in an API Gateway API with a [proxy resource](api-gateway-method-settings-method-request.md#api-gateway-proxy-resource), you perform the following tasks: 
+ Create a proxy resource with a greedy path variable of `{proxy+}`. 
+ Set the `ANY` method on the proxy resource.
+ Integrate the resource and method with a backend using the HTTP or Lambda integration type.

**Note**  
Greedy path variables, `ANY` methods, and proxy integration types are independent features, although they are commonly used together. You can configure a specific HTTP method on a greedy resource or apply non-proxy integration types to a proxy resource.

API Gateway enacts certain restrictions and limitations when handling methods with either a Lambda proxy integration or an HTTP proxy integration. For details, see [Amazon API Gateway important notes](api-gateway-known-issues.md). 

**Note**  
 When using proxy integration with a passthrough, API Gateway returns the default `Content-Type:application/json` header if the content type of a payload is unspecified. 

A proxy resource is most powerful when it is integrated with a backend using either HTTP proxy integration or Lambda proxy [integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html).

## HTTP proxy integration with a proxy resource
<a name="api-gateway-proxy-integration-types"></a>

The HTTP proxy integration, designated by `HTTP_PROXY` in the API Gateway REST API, is for integrating a method request with a backend HTTP endpoint. With this integration type, API Gateway simply passes the entire request and response between the frontend and the backend, subject to certain [restrictions and limitations](api-gateway-known-issues.md).

**Note**  
HTTP proxy integration supports multi-valued headers and query strings.

When applying the HTTP proxy integration to a proxy resource, you can set up your API to expose a portion or an entire endpoint hierarchy of the HTTP backend with a single integration setup. For example, suppose the backend of the website is organized into multiple branches of tree nodes off the root node (`/site`) as: `/site/a0/a1/.../aN`, `/site/b0/b1/.../bM`, etc. If you integrate the `ANY` method on a proxy resource of `/api/{proxy+}` with the backend endpoints with URL paths of `/site/{proxy}`, a single integration request can support any HTTP operations (GET, POST, etc.) on any of `[a0, a1, ..., aN, b0, b1, ...bM, ...]`. If you apply a proxy integration to a specific HTTP method, for example, `GET`, instead, the resulting integration request works with the specified (that is, `GET`) operations on any of those backend nodes. 

## Lambda proxy integration with a proxy resource
<a name="lambda-proxy-integration-with-proxy-resource"></a>

The Lambda proxy integration, designated by `AWS_PROXY` in the API Gateway REST API, is for integrating a method request with a Lambda function in the backend. With this integration type, API Gateway applies a default mapping template to send the entire request to the Lambda function and transforms the output from the Lambda function to HTTP responses. 

Similarly, you can apply the Lambda proxy integration to a proxy resource of `/api/{proxy+}` to set up a single integration to have a backend Lambda function react individually to changes in any of the API resources under `/api`. 

# Set up an API integration request using the API Gateway console
<a name="how-to-method-settings-console"></a>

 An API method setup defines the method and describes its behaviors. To set up a method, you must specify a resource, including the root ("/"), on which the method is exposed, an HTTP method (`GET`, `POST`, etc.), and how it will be integrated with the targeted backend. The method request and response specify the contract with the calling app, stipulating which parameters the API can receive and what the response looks like. 

 The following procedures describe how to use the API Gateway console to create an integration request.

**Topics**
+ [Set up a Lambda integration](#how-to-method-settings-console-lambda)
+ [Set up an HTTP integration](#how-to-method-settings-console-http)
+ [Set up an AWS service integration](#how-to-method-settings-console-aws)
+ [Set up a mock integration](#how-to-method-settings-console-mock)

## Set up a Lambda integration
<a name="how-to-method-settings-console-lambda"></a>

Use a Lambda function integration to integrate your API with a Lambda function. At the API level, this is an `AWS` integration type if you create a non-proxy integration, or an `AWS_PROXY` integration type if you create a proxy integration.

**To set up a Lambda integration**

1. In the **Resources** pane, choose **Create method**.

1. For **Method type**, select an HTTP method.

1. For **Integration type**, choose **Lambda function**.

1. To use a Lambda proxy integration, turn on **Lambda proxy integration**. To learn more about Lambda proxy integrations, see [Understand API Gateway Lambda proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-create-api-as-simple-proxy).

1. For **Lambda function**, enter the name of the Lambda function.

    If you are using a Lambda function in a different Region than your API, select the Region from the dropdown menu and enter the name of the Lambda function. If you are using a cross-account Lambda function, enter the function ARN. 

1. To use the default timeout value of 29 seconds, keep **Default timeout** turned on. To set a custom timeout, choose **Default timeout** and enter a timeout value between `50` and `29000` milliseconds.

1. (Optional) You can configure the method request settings using the following dropdown menus. Choose **Method request settings** and configure your method request. For more information, see step 3 of [Edit an API Gateway method request in the API Gateway console](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console).

   You can also configure your method request settings after you create your method.

1. Choose **Create method**.

## Set up an HTTP integration
<a name="how-to-method-settings-console-http"></a>

Use an HTTP integration to integrate your API with an HTTP endpoint. At the API level, this is the `HTTP` integration type.

**To set up an HTTP integration**

1. In the **Resources** pane, choose **Create method**.

1. For **Method type**, select an HTTP method.

1. For **Integration type**, choose **HTTP**.

1. To use an HTTP proxy integration, turn on **HTTP proxy integration**. To learn more about HTTP proxy integrations, see [Set up HTTP proxy integrations in API Gateway](setup-http-integrations.md#api-gateway-set-up-http-proxy-integration-on-proxy-resource).

1. For **HTTP method**, choose the HTTP method type that most closely matches the method in the HTTP backend.

1. For **Endpoint URL**, enter the URL of the HTTP backend you want this method to use.

1. For **Content handling**, select a content handling behavior.

1. To use the default timeout value of 29 seconds, keep **Default timeout** turned on. To set a custom timeout, choose **Default timeout** and enter a timeout value between `50` and `29000` milliseconds.

1. (Optional) You can configure the method request settings using the following dropdown menus. Choose **Method request settings** and configure your method request. For more information, see step 3 of [Edit an API Gateway method request in the API Gateway console](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console).

   You can also configure your method request settings after you create your method.

1. Choose **Create method**.

## Set up an AWS service integration
<a name="how-to-method-settings-console-aws"></a>

Use an AWS service integration to integrate your API directly with an AWS service. At the API level, this is the `AWS` integration type.

To set up an API Gateway API to do any of the following:
+ Create a new Lambda function.
+ Set a resource permission on the Lambda function.
+ Perform any other Lambda service actions.

You must choose **AWS service**.

**To set up an AWS service integration**

1. In the **Resources** pane, choose **Create method**.

1. For **Method type**, select an HTTP method.

1. For **Integration type**, choose **AWS service**.

1. For **AWS Region**, choose the AWS Region you want this method to use to call the action.

1. For **AWS service**, choose the AWS service you want this method to call.

1.  For **AWS subdomain**, enter the subdomain used by the AWS service. Typically, you would leave this blank. Some AWS services can support subdomains as part of the hosts. Consult the service documentation for the availability and, if available, details. 

1. For **HTTP method**, choose the HTTP method type that corresponds to the action. For HTTP method type, see the API reference documentation for the AWS service you chose for **AWS service**.

1. For **Action type**, select to either **Use action name** to use an API action or **Use path override** to use a custom resource path. For available actions and custom resource paths, see the API reference documentation for the AWS service you chose for **AWS service**.

1. Enter either an **Action name** or **Path override**.

1. For **Execution role**, enter the ARN of the IAM role that the method will use to call the action.

   To create the IAM role, you can adapt the instructions in [Step 1: Create the AWS service proxy execution role](getting-started-aws-proxy.md#getting-started-aws-proxy-add-roles). Specify an access policy with the desired number of action and resource statements. For more information, see [How Amazon API Gateway works with IAM](security_iam_service-with-iam.md).

   For the action and resource statement syntax, see the documentation for the AWS service you chose for **AWS service**.

   For the IAM role's trust relationship, specify the following, which enables API Gateway to take action on behalf of your AWS account:

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Sid": "",
         "Effect": "Allow",
         "Principal": {
           "Service": "apigateway.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

------

1. To use the default timeout value of 29 seconds, keep **Default timeout** turned on. To set a custom timeout, choose **Default timeout** and enter a timeout value between `50` and `29000` milliseconds.

1. (Optional) You can configure the method request settings using the following dropdown menus. Choose **Method request settings** and configure your method request. For more information, see step 3 of [Edit an API Gateway method request in the API Gateway console](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console).

   You can also configure your method request settings after you create your method.

1. Choose **Create method**.

## Set up a mock integration
<a name="how-to-method-settings-console-mock"></a>

 Use a mock integration if you want API Gateway to act as your backend to return static responses. At the API level, this is the `MOCK` integration type. Typically, you can use the `MOCK` integration when your API is not yet final, but you want to generate API responses to unblock dependent teams for testing. For the `OPTION` method, API Gateway sets the `MOCK` integration as default to return CORS-enabling headers for the applied API resource.

**To set up a mock integration**

1. In the **Resources** pane, choose **Create method**.

1. For **Method type**, select an HTTP method.

1. For **Integration type**, choose **Mock**.

1. (Optional) You can configure the method request settings using the following dropdown menus. Choose **Method request settings** and configure your method request. For more information, see step 3 of [Edit an API Gateway method request in the API Gateway console](how-to-set-up-method-using-console.md#how-to-method-settings-callers-console).

   You can also configure your method request settings after you create your method.

1. Choose **Create method**.

# Set up an integration response in API Gateway
<a name="api-gateway-integration-settings-integration-response"></a>

 For a non-proxy integration, you must set up at least one integration response, and make it the default response, to pass the result returned from the backend to the client. You can choose to pass through the result as-is or to transform the integration response data to the method response data if the two have different formats. 

For a proxy integration, API Gateway automatically passes the backend output to the client as an HTTP response. You do not set either an integration response or a method response.

To set up an integration response, you perform the following required and optional tasks:

1.  Specify an HTTP status code of a method response to which the integration response data is mapped. This is required.

1.  Define a regular expression to select backend output to be represented by this integration response. If you leave this empty, the response is the default response that is used to catch any response not yet configured.

1.  If needed, declare mappings consisting of key-value pairs to map specified integration response parameters to given method response parameters.

1. If needed, add body-mapping templates to transform given integration response payloads into specified method response payloads.

1.  If needed, specify how to handle type conversion for a binary payload.

An integration response is an HTTP response encapsulating the backend response. For an HTTP endpoint, the backend response is an HTTP response. The integration response status code can take the backend-returned status code, and the integration response body is the backend-returned payload. For a Lambda endpoint, the backend response is the output returned from the Lambda function. With the Lambda integration, the Lambda function output is returned as a `200 OK` response. The payload can contain the result as JSON data, including a JSON string or a JSON object, or an error message as a JSON object. You can assign a regular expression to the [selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern) property to map an error response to an appropriate HTTP error response. For more information about the Lambda function error response, see [Handle Lambda errors in API Gateway](handle-errors-in-lambda-integration.md). With the Lambda proxy integration, the Lambda function must return output of the following format:

```
{
    statusCode: "...",            // a valid HTTP status code
    headers: { 
        custom-header: "..."      // any API-specific custom header
    },
    body: "...",                  // a JSON string.
    isBase64Encoded:  true|false  // for binary support
}
```

There is no need to map the Lambda function response to its proper HTTP response.

To return the result to the client, set up the integration response to pass the endpoint response through as-is to the corresponding method response. Or you can map the endpoint response data to the method response data. The response data that can be mapped includes the response status code, response header parameters, and response body. If no method response is defined for the returned status code, API Gateway returns a 500 error. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).



# Lambda integrations for REST APIs in API Gateway
<a name="set-up-lambda-integrations"></a>

 You can integrate an API method with a Lambda function using Lambda proxy integration or Lambda non-proxy (custom) integration. 

In Lambda proxy integration, the required setup is simple. Set the integration's HTTP method to POST, the integration endpoint URI to the ARN of the Lambda function invocation action of a specific Lambda function, and grant API Gateway permission to call the Lambda function on your behalf.

In Lambda non-proxy integration, in addition to the proxy integration setup steps, you also specify how the incoming request data is mapped to the integration request and how the resulting integration response data is mapped to the method response. 

**Topics**
+ [Lambda proxy integrations in API Gateway](set-up-lambda-proxy-integrations.md)
+ [Set up Lambda custom integrations in API Gateway](set-up-lambda-custom-integrations.md)
+ [Set up asynchronous invocation of the backend Lambda function](set-up-lambda-integration-async.md)
+ [Handle Lambda errors in API Gateway](handle-errors-in-lambda-integration.md)

# Lambda proxy integrations in API Gateway
<a name="set-up-lambda-proxy-integrations"></a>

The following section shows how to use a Lambda proxy integration.

**Topics**
+ [Understand API Gateway Lambda proxy integration](#api-gateway-create-api-as-simple-proxy)
+ [Support for multi-value headers and query string parameters](#apigateway-multivalue-headers-and-parameters)
+ [Input format of a Lambda function for proxy integration](#api-gateway-simple-proxy-for-lambda-input-format)
+ [Output format of a Lambda function for proxy integration](#api-gateway-simple-proxy-for-lambda-output-format)
+ [Set up Lambda proxy integration for API Gateway using the AWS CLI](set-up-lambda-proxy-integration-using-cli.md)
+ [Set up a proxy resource with Lambda proxy integration with an OpenAPI definition](api-gateway-set-up-lambda-proxy-integration-on-proxy-resource.md)

## Understand API Gateway Lambda proxy integration
<a name="api-gateway-create-api-as-simple-proxy"></a>

Amazon API Gateway Lambda proxy integration is a simple, powerful, and nimble mechanism to build an API with a setup of a single API method. The Lambda proxy integration allows the client to call a single Lambda function in the backend. The function accesses many resources or features of other AWS services, including calling other Lambda functions. 

 In Lambda proxy integration, when a client submits an API request, API Gateway passes to the integrated Lambda function an [event object](#api-gateway-simple-proxy-for-lambda-input-format), except that the order of the request parameters is not preserved. This [request data](#api-gateway-simple-proxy-for-lambda-input-format) includes the request headers, query string parameters, URL path variables, payload, and API configuration data. The configuration data can include current deployment stage name, stage variables, user identity, or authorization context (if any). The backend Lambda function parses the incoming request data to determine the response that it returns. For API Gateway to pass the Lambda output as the API response to the client, the Lambda function must return the result in [this format](#api-gateway-simple-proxy-for-lambda-output-format). 

 Because API Gateway doesn't intervene very much between the client and the backend Lambda function for the Lambda proxy integration, the client and the integrated Lambda function can adapt to changes in each other without breaking the existing integration setup of the API. To enable this, the client must follow application protocols enacted by the backend Lambda function. 

 You can set up a Lambda proxy integration for any API method. But a Lambda proxy integration is more potent when it is configured for an API method involving a generic proxy resource. The generic proxy resource can be denoted by a special templated path variable of `{proxy+}`, the catch-all `ANY` method placeholder, or both. The client can pass the input to the backend Lambda function in the incoming request as request parameters or applicable payload. The request parameters include headers, URL path variables, query string parameters, and the applicable payload. The integrated Lambda function verifies all of the input sources before processing the request and responding to the client with meaningful error messages if any of the required input is missing.

 When calling an API method integrated with the generic HTTP method of `ANY` and the generic resource of `{proxy+}`, the client submits a request with a particular HTTP method in place of `ANY`. The client also specifies a particular URL path instead of `{proxy+}`, and includes any required headers, query string parameters, or an applicable payload. 

 The following list summarizes runtime behaviors of different API methods with the Lambda proxy integration: 
+ `ANY /{proxy+}`: The client must choose a particular HTTP method, must set a particular resource path hierarchy, and can set any headers, query string parameters, and applicable payload to pass the data as input to the integrated Lambda function. 
+ `ANY /res`: The client must choose a particular HTTP method and can set any headers, query string parameters, and applicable payload to pass the data as input to the integrated Lambda function. 
+ `GET|POST|PUT|... /{proxy+}`: The client can set a particular resource path hierarchy, any headers, query string parameters, and applicable payload to pass the data as input to the integrated Lambda function. 
+  `GET|POST|PUT|... /res/{path}/...`: The client must choose a particular path segment (for the `{path}` variable) and can set any request headers, query string parameters, and applicable payload to pass input data to the integrated Lambda function.
+  `GET|POST|PUT|... /res`: The client can choose any request headers, query string parameters, and applicable payload to pass input data to the integrated Lambda function.

 Both the proxy resource of `{proxy+}` and the custom resource of `{custom}` are expressed as templated path variables. However `{proxy+}` can refer to any resource along a path hierarchy, while `{custom}` refers to a particular path segment only. For example, a grocery store might organize its online product inventory by department names, produce categories, and product types. The grocery store's website can then represent available products by the following templated path variables of custom resources: `/{department}/{produce-category}/{product-type}`. For example, apples are represented by `/produce/fruit/apple` and carrots by `/produce/vegetables/carrot`. It can also use `/{proxy+}` to represent any department, any produce category, or any product type that a customer can search for while shopping in the online store. For example, `/{proxy+}` can refer to any of the following items: 
+ `/produce`
+ `/produce/fruit`
+ `/produce/vegetables/carrot`

 To let customers search for any available product, its produce category, and the associated store department, you can expose a single method of `GET /{proxy+}` with read-only permissions. Similarly, to allow a supervisor to update the `produce` department's inventory, you can set up another single method of `PUT /produce/{proxy+}` with read/write permissions. To allow a cashier to update the running total of a vegetable, you can set up a `POST /produce/vegetables/{proxy+}` method with read/write permissions. To let a store manager perform any possible action on any available product, the online store developer can expose the `ANY /{proxy+}` method with read/write permissions. In any case, at run time, the customer or the employee must select a particular product of a given type in a chosen department, a specific produce category in a chosen department, or a specific department. 



For more information about setting up API Gateway proxy integrations, see [Set up a proxy integration with a proxy resource](api-gateway-set-up-simple-proxy.md). 

 Proxy integration requires that the client have more detailed knowledge of the backend requirements. Therefore, to ensure optimal app performance and user experience, the backend developer must communicate clearly to the client developer the requirements of the backend, and provide a robust error feedback mechanism when the requirements are not met. 

## Support for multi-value headers and query string parameters
<a name="apigateway-multivalue-headers-and-parameters"></a>

API Gateway supports multiple headers and query string parameters that have the same name. Multi-value headers as well as single-value headers and parameters can be combined in the same requests and responses. For more information, see [Input format of a Lambda function for proxy integration](#api-gateway-simple-proxy-for-lambda-input-format) and [Output format of a Lambda function for proxy integration](#api-gateway-simple-proxy-for-lambda-output-format).

## Input format of a Lambda function for proxy integration
<a name="api-gateway-simple-proxy-for-lambda-input-format"></a>

In Lambda proxy integration, API Gateway maps the entire client request to the input `event` parameter of the backend Lambda function. The following example shows the structure of an event that API Gateway sends to a Lambda proxy integration.

In this example, we assume that the invocation to API Gateway was the following:

```
curl 'https://a1b2c3.execute-api.us-east-1.amazonaws.com/my/path?parameter1=value1&parameter2=value1&parameter2=value2&parameter3=value1,value2' -H 'header1: value1' -H 'header2: value1' -H 'header2: value2' -H 'header3: value1,value2'
```

The output looks like the following:

```
{
  "resource": "/my/path",
  "path": "/my/path",
  "httpMethod": "GET",
  "headers": {
      "header1": "value1",
      "header2": "value2",
      "header3": "value1,value2"
  },
  "multiValueHeaders": {
    "header1": ["value1"],
    "header2": ["value1","value2"],
    "header3": ["value1,value2"]
  },
  "queryStringParameters": {
      "parameter1": "value1",
      "parameter2": "value2",
      "parameter3": "value1,value2"
  },
  "multiValueQueryStringParameters": {
    "parameter1": ["value1"],
    "parameter2": ["value1","value2"],
    "parameter3": ["value1,value2"]
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "id",
    "authorizer": {
      "claims": null,
      "scopes": null
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "extendedRequestId": "request-id",
    "httpMethod": "GET",
    "identity": {
      "accessKey": null,
      "accountId": null,
      "caller": null,
      "cognitoAuthenticationProvider": null,
      "cognitoAuthenticationType": null,
      "cognitoIdentityId": null,
      "cognitoIdentityPoolId": null,
      "principalOrgId": null,
      "sourceIp": "IP",
      "user": null,
      "userAgent": "user-agent",
      "userArn": null,
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "path": "/my/path",
    "protocol": "HTTP/1.1",
    "requestId": "id=",
    "requestTime": "04/Mar/2020:19:15:17 +0000",
    "requestTimeEpoch": 1583349317135,
    "resourceId": null,
    "resourcePath": "/my/path",
    "stage": "$default"
  },
  "pathParameters": null,
  "stageVariables": null,
  "body": "Hello from Lambda!",
  "isBase64Encoded": false
}
```

**Note**  
In the input:  
The `headers` key can only contain single-value headers.
The `multiValueHeaders` key can contain multi-value headers as well as single-value headers.
If you specify values for both `headers` and `multiValueHeaders`, API Gateway merges them into a single list. If the same key-value pair is specified in both, only the values from `multiValueHeaders` will appear in the merged list.

In the input to the backend Lambda function, the `requestContext` object is a map of key-value pairs. In each pair, the key is the name of a [\$1context](api-gateway-mapping-template-reference.md#context-variable-reference) variable property, and the value is the value of that property. API Gateway might add new keys to the map.

Depending on the features that are enabled, the `requestContext` map may vary from API to API. For example, in the preceding example, no authorization type is specified, so no `$context.authorizer.*` or `$context.identity.*` properties are present. When an authorization type is specified, this causes API Gateway to pass authorized user information to the integration endpoint in a `requestContext.identity` object as follows:
+ When the authorization type is `AWS_IAM`, the authorized user information includes `$context.identity.*` properties.
+ When the authorization type is `COGNITO_USER_POOLS` (Amazon Cognito authorizer), the authorized user information includes `$context.identity.cognito*` and `$context.authorizer.claims.*` properties.
+ When the authorization type is `CUSTOM` (Lambda authorizer), the authorized user information includes `$context.authorizer.principalId` and other applicable `$context.authorizer.*` properties.

## Output format of a Lambda function for proxy integration
<a name="api-gateway-simple-proxy-for-lambda-output-format"></a>

In Lambda proxy integration, API Gateway requires the backend Lambda function to return output according to the following JSON format:

```
{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}
```

In the output:
+ The `headers` and `multiValueHeaders` keys can be unspecified if no extra response headers are to be returned.
+ The `headers` key can only contain single-value headers.
+ The `multiValueHeaders` key can contain multi-value headers as well as single-value headers. You can use the `multiValueHeaders` key to specify all of your extra headers, including any single-value ones.
+ If you specify values for both `headers` and `multiValueHeaders`, API Gateway merges them into a single list. If the same key-value pair is specified in both, only the values from `multiValueHeaders` will appear in the merged list.

To enable CORS for the Lambda proxy integration, you must add `Access-Control-Allow-Origin:domain-name` to the output `headers`. `domain-name` can be `*` for any domain name. The output `body` is marshalled to the frontend as the method response payload. If `body` is a binary blob, you can encode it as a Base64-encoded string by setting `isBase64Encoded` to `true` and configuring `*/*` as a **Binary Media Type**. Otherwise, you can set it to `false` or leave it unspecified.

**Note**  
For more information about enabling binary support, see [Enabling binary support using the API Gateway console](api-gateway-payload-encodings-configure-with-console.md). For an example Lambda function, see [Return binary media from a Lambda proxy integration in API Gateway](lambda-proxy-binary-media.md).

If the function output is of a different format, API Gateway returns a `502 Bad Gateway` error response. 

To return a response in a Lambda function in Node.js, you can use commands such as the following:
+ To return a successful result, call `callback(null, {"statusCode": 200, "body": "results"})`.
+ To throw an exception, call `callback(new Error('internal server error'))`.
+ For a client-side error (if, for example, a required parameter is missing), you can call `callback(null, {"statusCode": 400, "body": "Missing parameters of ..."})` to return the error without throwing an exception.

In a Lambda `async` function in Node.js, the equivalent syntax would be:
+ To return a successful result, call `return {"statusCode": 200, "body": "results"}`.
+ To throw an exception, call `throw new Error("internal server error")`.
+ For a client-side error (if, for example, a required parameter is missing), you can call `return {"statusCode": 400, "body": "Missing parameters of ..."}` to return the error without throwing an exception.

# Set up Lambda proxy integration for API Gateway using the AWS CLI
<a name="set-up-lambda-proxy-integration-using-cli"></a>

In this section, we show how to set up an API with the Lambda proxy integration using the AWS CLI. For detailed instructions for using the API Gateway console to configure a proxy resource with the Lambda proxy integration, see [Tutorial: Create a REST API with a Lambda proxy integration](api-gateway-create-api-as-simple-proxy-for-lambda.md).

As an example, we use the following sample Lambda function as the backend of the API:

```
export const handler = async(event, context) => {
    console.log('Received event:', JSON.stringify(event, null, 2));
    var res ={
        "statusCode": 200,
        "headers": {
            "Content-Type": "*/*"
        }
    };
    var greeter = 'World';
    if (event.greeter && event.greeter!=="") {
        greeter =  event.greeter;
    } else if (event.body && event.body !== "") {
        var body = JSON.parse(event.body);
        if (body.greeter && body.greeter !== "") {
            greeter = body.greeter;
        }
    } else if (event.queryStringParameters && event.queryStringParameters.greeter && event.queryStringParameters.greeter !== "") {
        greeter = event.queryStringParameters.greeter;
    } else if (event.multiValueHeaders && event.multiValueHeaders.greeter && event.multiValueHeaders.greeter != "") {
        greeter = event.multiValueHeaders.greeter.join(" and ");
    } else if (event.headers && event.headers.greeter && event.headers.greeter != "") {
        greeter = event.headers.greeter;
    } 
    res.body = "Hello, " + greeter + "!";
    return res
};
```

Comparing this to the Lambda custom integration setup in [Set up Lambda custom integrations in API Gateway](set-up-lambda-custom-integrations.md), the input to this Lambda function can be expressed in the request parameters and body. You have more latitude to allow the client to pass the same input data. Here, the client can pass the greeter's name in as a query string parameter, a header, or a body property. The function can also support the Lambda custom integration. The API setup is simpler. You do not configure the method response or integration response at all.

**To set up a Lambda proxy integration using the AWS CLI**

1. Use the following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command to create an API:

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   The output will look like the following:

   ```
   {
       "name": "HelloWorldProxy (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   You use the API `id` (`te6si5ach7`) and the `rootResourceId` ( `krznpq9xpg`) throughout this example.

1. Use the following [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) command to create an API Gateway [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) of `/greeting`:

   ```
   aws apigateway create-resource \
         --rest-api-id te6si5ach7 \
         --parent-id krznpq9xpg \
         --path-part {proxy+}
   ```

   The output will look like the following:

   ```
   {
       "path": "/{proxy+}", 
       "pathPart": "{proxy+}", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   You use the `{proxy+}` resource's `id` value (`2jf6xt`) to create a method on the `/{proxy+}` resource in the next step.

1. Use the following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) to create an `ANY` method request of `ANY /{proxy+}`:

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method ANY \
          --authorization-type "NONE"
   ```

   The output will look like the following:

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "ANY", 
       "authorizationType": "NONE"
   }
   ```

   This API method allows the client to receive or send greetings from the Lambda function at the backend. 

1. Use the following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) command to set up the integration of the `ANY /{proxy+}` method with a Lambda function, named `HelloWorld`. This function responds to the request with a message of `"Hello, {name}!"`, if the `greeter` parameter is provided, or `"Hello, World!"`, if the query string parameter is not set.

   ```
   aws apigateway put-integration \
         --rest-api-id te6si5ach7 \
         --resource-id 2jf6xt \
         --http-method ANY \
         --type AWS_PROXY \
         --integration-http-method POST \
         --uri arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:HelloWorld/invocations \
         --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```
**Important**  
For Lambda integrations, you must use the HTTP method of `POST` for the integration request, according to the [specification of the Lambda service action for function invocations](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html). The IAM role of `apigAwsProxyRole` must have policies allowing the `apigateway` service to invoke Lambda functions. For more information about IAM permissions, see [API Gateway permissions model for invoking an API](permissions.md#api-gateway-control-access-iam-permissions-model-for-calling-api).

   The output will look like the following:

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:1234567890:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "cacheNamespace": "vvom7n", 
       "credentials": "arn:aws:iam::1234567890:role/apigAwsProxyRole", 
       "type": "AWS_PROXY"
   }
   ```

   Instead of supplying an IAM role for `credentials`, you can use the [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command to add resource-based permissions. This is what the API Gateway console does. 

1. Use the following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to deploy the API to a `test` stage:

   ```
   aws apigateway create-deployment  \
         --rest-api-id te6si5ach7 \
         --stage-name test
   ```

1. Test the API using the following cURL commands in a terminal.

   Calling the API with the query string parameter of `?greeter=jane`:

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=jane'
   ```

   Calling the API with a header parameter of `greeter:jane`:

   ```
   curl -X GET https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -H 'greeter: jane'
   ```

   Calling the API with a body of `{"greeter":"jane"}`:

   ```
   curl -X POST https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -d '{ "greeter": "jane" }'
   ```

   In all the cases, the output is a 200 response with the following response body:

   ```
   Hello, jane!
   ```

# Set up a proxy resource with Lambda proxy integration with an OpenAPI definition
<a name="api-gateway-set-up-lambda-proxy-integration-on-proxy-resource"></a>

To set up a proxy resource with the Lambda proxy integration type, create an API resource with a greedy path parameter (for example, `/parent/{proxy+}`) and integrate this resource with a Lambda function backend (for example, `arn:aws:lambda:us-west-2:123456789012:function:SimpleLambda4ProxyResource`) on the `ANY` method. The greedy path parameter must be at the end of the API resource path. As with a non-proxy resource, you can set up the proxy resource by using the API Gateway console, importing an OpenAPI definition file, or calling the API Gateway REST API directly.

The following OpenAPI API definition file shows an example of an API with a proxy resource that is integrated with a Lambda function named `SimpleLambda4ProxyResource`.

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-09-12T17:50:37Z",
      "title": "ProxyIntegrationWithLambda"
   },
   "paths": {
      "/{proxy+}": {
         "x-amazon-apigateway-any-method": {
            "parameters": [
               {
                  "name": "proxy",
                  "in": "path",
                  "required": true,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {},
            "x-amazon-apigateway-integration": {
               "responses": {
                  "default": {
                     "statusCode": "200"
                  }
               },
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "POST",
               "cacheNamespace": "roq9wj",
               "cacheKeyParameters": [
                  "method.request.path.proxy"
               ],
               "type": "aws_proxy"
            }
         }
      }
   },
   "servers": [
      {
         "url": "https://gy415nuibc.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/testStage"
            }
         }
      }
   ]
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-09-12T17:50:37Z",
    "title": "ProxyIntegrationWithLambda"
  },
  "host": "gy415nuibc.execute-api.us-east-1.amazonaws.com",
  "basePath": "/testStage",
  "schemes": [
    "https"
  ],
  "paths": {
    "/{proxy+}": {
      "x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "proxy",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {},
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST",
          "cacheNamespace": "roq9wj",
          "cacheKeyParameters": [
            "method.request.path.proxy"
          ],
          "type": "aws_proxy"
        }
      }
    }
  }
}
```

------

In Lambda proxy integration, at run time, API Gateway maps an incoming request into the input `event` parameter of the Lambda function. The input includes the request method, path, headers, any query string parameters, any payload, associated context, and any defined stage variables. The input format is explained in [Input format of a Lambda function for proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format). For API Gateway to map the Lambda output to HTTP responses successfully, the Lambda function must output the result in the format described in [Output format of a Lambda function for proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format). 

In Lambda proxy integration of a proxy resource through the `ANY` method, the single backend Lambda function serves as the event handler for all requests through the proxy resource. For example, to log traffic patterns, you can have a mobile device send its location information of state, city, street, and building by submitting a request with `/state/city/street/house` in the URL path for the proxy resource. The backend Lambda function can then parse the URL path and insert the location tuples into a DynamoDB table.

# Set up Lambda custom integrations in API Gateway
<a name="set-up-lambda-custom-integrations"></a>

 To show how to set up the Lambda custom, or non-proxy,integration, we create an API Gateway API to expose the `GET /greeting?greeter={name}` method to invoke a Lambda function. Use one of the following example Lambda functions for you API.

Use one of the following example Lambda functions:

------
#### [ Node.js ]

```
'use strict';
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];            
var times = ['morning', 'afternoon', 'evening', 'night', 'day'];

export const handler = async(event) => {
  console.log(event);
  // Parse the input for the name, city, time and day property values
  let name = event.name === null || event.name === undefined || event.name === "" ? 'you' : event.name;
  let city = event.city === undefined ? 'World' : event.city;
  let time = times.indexOf(event.time)<0 ? 'day' : event.time;
  let day = days.indexOf(event.day)<0 ? null : event.day;

  // Generate a greeting
  let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. ';
  if (day) greeting += 'Happy ' + day + '!';
  
  // Log the greeting to CloudWatch
  console.log('Hello: ', greeting);
  
  // Return a greeting to the caller
  return greeting;
};
```

------
#### [ Python ]

```
import json


def lambda_handler(event, context):
    print(event)
    res = {
        "statusCode": 200,
        "headers": {
            "Content-Type": "*/*"
        }
    }

    if event['greeter'] == "":
        res['body'] = "Hello, World"
    elif (event['greeter']):
        res['body'] = "Hello, " + event['greeter'] + "!"
    else:
        raise Exception('Missing the required greeter parameter.')

    return res
```

------

The function responds with a message of `"Hello, {name}!"` if the `greeter` parameter value is a non-empty string. It returns a message of `"Hello, World!"` if the `greeter` value is an empty string. The function returns an error message of `"Missing the required greeter parameter."` if the greeter parameter is not set in the incoming request. We name the function `HelloWorld`.

You can create it in the Lambda console or by using the AWS CLI. In this section, we reference this function using the following ARN:

```
arn:aws:lambda:us-east-1:123456789012:function:HelloWorld
```

With the Lambda function set in the backend, proceed to set up the API.<a name="set-up-lambda-custom-integration-using-cli"></a>

**To set up the Lambda custom integration using the AWS CLI**

1. Use the following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command to create an API:

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   The output will look like the following:

   ```
   {
       "name": "HelloWorld (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   You use the API `id` ( `te6si5ach7`) and the `rootResourceId` (`krznpq9xpg`) throughout this example.

1. Use the following [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) command to create an API Gateway [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) of `/greeting`:

   ```
   aws apigateway create-resource \
         --rest-api-id te6si5ach7 \
         --parent-id krznpq9xpg \
         --path-part greeting
   ```

   The output will look like the following:

   ```
   {
       "path": "/greeting", 
       "pathPart": "greeting", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   You use the `greeting` resource's `id` value (`2jf6xt`) to create a method on the `/greeting` resource in the next step.

1. Use the following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command to create an API method request of `GET /greeting?greeter={name}`:

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method GET \
          --authorization-type "NONE" \
          --request-parameters method.request.querystring.greeter=false
   ```

   The output will look like the following:

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "GET", 
       "authorizationType": "NONE", 
       "requestParameters": {
           "method.request.querystring.greeter": false
       }
   }
   ```

   This API method allows the client to receive a greeting from the Lambda function at the backend. The `greeter` parameter is optional because the backend should handle either an anonymous caller or a self-identified caller.

1. Use the following [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) command to set up the `200 OK` response to the method request of `GET /greeting?greeter={name}`:

   ```
   aws apigateway put-method-response \
           --rest-api-id te6si5ach7 \ 
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200
   ```

   

1. Use the following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) command to set up the integration of the `GET /greeting?greeter={name}` method with a Lambda function, named `HelloWorld`. The function responds to the request with a message of `"Hello, {name}!"`, if the `greeter` parameter is provided, or `"Hello, World!"`, if the query string parameter is not set.

   ```
   aws apigateway put-integration \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --type AWS \
           --integration-http-method POST \
           --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations \
           --request-templates '{"application/json":"{\"greeter\":\"$input.params('greeter')\"}"}' \
           --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```

   The mapping template supplied here translates the `greeter` query string parameter to the `greeter` property of the JSON payload. This is necessary because the input to a Lambda function must be expressed in the body.
**Important**  
For Lambda integrations, you must use the HTTP method of `POST` for the integration request, according to the [specification of the Lambda service action for function invocations](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html). The `uri` parameter is the ARN of the function-invoking action.  
The output will look like the following:

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "requestTemplates": {
           "application/json": "{\"greeter\":\"$input.params('greeter')\"}"
       }, 
       "cacheNamespace": "krznpq9xpg", 
       "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", 
       "type": "AWS"
   }
   ```

   The IAM role of `apigAwsProxyRole` must have policies that allow the `apigateway` service to invoke Lambda functions. Instead of supplying an IAM role for `credentials`, you can call the [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command to add resource-based permissions. This is how the API Gateway console adds these permissions. 

1. Use the following [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) command to set up the integration response to pass the Lambda function output to the client as the `200 OK` method response:

   ```
    aws apigateway put-integration-response \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200 \
           --selection-pattern ""
   ```

   By setting the selection-pattern to an empty string, the `200 OK` response is the default. 

   The output will look like the following:

   ```
    {
       "selectionPattern": "", 
       "statusCode": "200"
   }
   ```

1. Use the following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to deploy the API to a `test` stage:

   ```
   aws apigateway create-deployment \
           --rest-api-id te6si5ach7 \
           --stage-name test
   ```

1.  Test the API using the following cURL command in a terminal:

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=me' \
     -H 'authorization: AWS4-HMAC-SHA256 Credential={access_key}/20171020/us-west-2/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=f327...5751'
   ```

# Set up asynchronous invocation of the backend Lambda function
<a name="set-up-lambda-integration-async"></a>

In Lambda non-proxy (custom) integration, the backend Lambda function is invoked synchronously by default. This is the desired behavior for most REST API operations. Some applications, however, require work to be performed asynchronously (as a batch operation or a long-latency operation), typically by a separate backend component. In this case, the backend Lambda function is invoked asynchronously, and the front-end REST API method doesn't return the result.

You can configure the Lambda function for a Lambda non-proxy integration to be invoked asynchronously by specifying `'Event'` as the [Lambda invocation type](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html). This is done as follows:

## Configure Lambda asynchronous invocation in the API Gateway console
<a name="asynchronous-invocation-console-examples"></a>

For all invocations to be asynchronous:
+ In **Integration request**, add an `X-Amz-Invocation-Type` header with a static value of `'Event'`.

For clients to decide if invocations are asynchronous or synchronous:

1. In **Method request**, add an `InvocationType` header.

1. In **Integration request** add an `X-Amz-Invocation-Type` header with a mapping expression of `method.request.header.InvocationType`.

1. Clients can include the `InvocationType: Event` header in API requests for asynchronous invocations or `InvocationType: RequestResponse` for synchronous invocations.

## Configure Lambda asynchronous invocation using OpenAPI
<a name="asynchronous-invocation-OpenAPI-examples"></a>

For all invocations to be asynchronous:
+  Add the `X-Amz-Invocation-Type` header to the **x-amazon-apigateway-integration** section.

  ```
  "x-amazon-apigateway-integration" : {
            "type" : "aws",
            "httpMethod" : "POST",
            "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
            "responses" : {
              "default" : {
                "statusCode" : "200"
              }
            },
            "requestParameters" : {
              "integration.request.header.X-Amz-Invocation-Type" : "'Event'"
            },
            "passthroughBehavior" : "when_no_match",
            "contentHandling" : "CONVERT_TO_TEXT"
          }
  ```

For clients to decide if invocations are asynchronous or synchronous:

1.  Add the following header on any [OpenAPI Path Item Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject). 

   ```
   "parameters" : [ {
   "name" : "InvocationType",
   "in" : "header",
   "schema" : {
     "type" : "string"
   }
   } ]
   ```

1.  Add the `X-Amz-Invocation-Type` header to **x-amazon-apigateway-integration** section.

   ```
   "x-amazon-apigateway-integration" : {
             "type" : "aws",
             "httpMethod" : "POST",
             "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
             "responses" : {
               "default" : {
                 "statusCode" : "200"
               }
             },
             "requestParameters" : {
               "integration.request.header.X-Amz-Invocation-Type" : "method.request.header.InvocationType"
             },
             "passthroughBehavior" : "when_no_match",
             "contentHandling" : "CONVERT_TO_TEXT"
           }
   ```

1.  Clients can include the `InvocationType: Event` header in API requests for asynchronous invocations or `InvocationType: RequestResponse` for synchronous invocations. 

## Configure Lambda asynchronous invocation using CloudFormation
<a name="asynchronous-invocation-cfn-examples"></a>

The following CloudFormation templates show how to configure the `AWS::ApiGateway::Method` for asynchronous invocations.

For all invocations to be asynchronous:

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: "'Event'"
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

For clients to decide if invocations are asynchronous or synchronous:

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      RequestParameters:
        method.request.header.InvocationType: false
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: method.request.header.InvocationType
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

 Clients can include the `InvocationType: Event` header in API requests for asynchronous invocations or `InvocationType: RequestResponse` for synchronous invocations. 

# Handle Lambda errors in API Gateway
<a name="handle-errors-in-lambda-integration"></a>

 For Lambda custom integrations, you must map errors returned by Lambda in the integration response to standard HTTP error responses for your clients. Otherwise, Lambda errors are returned as `200 OK` responses by default and the result is not intuitive for your API users. 

 There are two types of errors that Lambda can return: standard errors and custom errors. In your API, you must handle these differently. 

 With the Lambda proxy integration, Lambda is required to return an output of the following format: 

```
{
  "isBase64Encoded" : "boolean",
  "statusCode": "number",
  "headers": { ... },
  "body": "JSON string"
}
```

In this output, `statusCode` is typically `4XX` for a client error and `5XX` for a server error. API Gateway handles these errors by mapping the Lambda error to an HTTP error response, according to the specified `statusCode`. For API Gateway to pass the error type (for example, `InvalidParameterException`), as part of the response to the client, the Lambda function must include a header (for example, `"X-Amzn-ErrorType":"InvalidParameterException"`) in the `headers` property. 

**Topics**
+ [Handle standard Lambda errors in API Gateway](#handle-standard-errors-in-lambda-integration)
+ [Handle custom Lambda errors in API Gateway](#handle-custom-errors-in-lambda-integration)

## Handle standard Lambda errors in API Gateway
<a name="handle-standard-errors-in-lambda-integration"></a>

A standard AWS Lambda error has the following format:

```
{
  "errorMessage": "<replaceable>string</replaceable>",
  "errorType": "<replaceable>string</replaceable>",
  "stackTrace": [
    "<replaceable>string</replaceable>",
    ...
  ]
}
```

 Here, `errorMessage` is a string expression of the error. The `errorType` is a language-dependent error or exception type. The `stackTrace` is a list of string expressions showing the stack trace leading to the occurrence of the error. 

 For example, consider the following JavaScript (Node.js) Lambda function. 

```
export const handler = function(event, context, callback) {
    callback(new Error("Malformed input ..."));
};
```

This function returns the following standard Lambda error, containing `Malformed input ...` as the error message:

```
{
  "errorMessage": "Malformed input ...",
  "errorType": "Error",
  "stackTrace": [
    "export const handler (/var/task/index.js:3:14)"
  ]
}
```

 Similarly, consider the following Python Lambda function, which raises an `Exception` with the same `Malformed input ...` error message. 

```
def lambda_handler(event, context):
    raise Exception('Malformed input ...')
```

 This function returns the following standard Lambda error: 

```
{
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      3,
      "lambda_handler",
      "raise Exception('Malformed input ...')"
    ]
  ],
  "errorType": "Exception",
  "errorMessage": "Malformed input ..."
}
```

 Note that the `errorType` and `stackTrace` property values are language-dependent. The standard error also applies to any error object that is an extension of the `Error` object or a subclass of the `Exception` class. 

 To map the standard Lambda error to a method response, you must first decide on an HTTP status code for a given Lambda error. You then set a regular expression pattern on the `[selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern)` property of the [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) associated with the given HTTP status code. In the API Gateway console, this `selectionPattern` is denoted as **Lambda error regex** in the **Integration response** section, under each integration response.

**Note**  
API Gateway uses Java pattern-style regexes for response mapping. For more information, see [Pattern](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) in the Oracle documentation.

 For example, use the following [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) to set up a new `selectionPattern` expression: 

```
aws apigateway put-integration-response --rest-api-id z0vprf0mdh --resource-id x3o5ih --http-method GET --status-code 400 --selection-pattern "Malformed.*" --region us-west-2
```

 Make sure that you also set up the corresponding error code (`400`) on the [method response](api-gateway-method-settings-method-response.md#setup-method-response-status-code). Otherwise, API Gateway throws an invalid configuration error response at runtime. 

**Note**  
 At runtime, API Gateway matches the Lambda error's `errorMessage` against the pattern of the regular expression on the `selectionPattern` property. If there is a match, API Gateway returns the Lambda error as an HTTP response of the corresponding HTTP status code. If there is no match, API Gateway returns the error as a default response or throws an invalid configuration exception if no default response is configured.   
 Setting the `selectionPattern` value to `.*` for a given response amounts to resetting this response as the default response. This is because such a selection pattern will match all error messages, including null, i.e., any unspecified error message. The resulting mapping overrides the default mapping. If you use `.+` as the selection pattern to filter responses, it might not match a response containing be aware that it may not match a response containing a newline ('`\n`) character.

 To update an existing `selectionPattern` value using the AWS CLI, call the [update-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration-response.html) operation to replace the `/selectionPattern` path value with the specified regex expression of the `Malformed*` pattern. 



To set the `selectionPattern` expression using the API Gateway console, enter the expression in the **Lambda error regex** text box when setting up or updating an integration response of a specified HTTP status code. 

## Handle custom Lambda errors in API Gateway
<a name="handle-custom-errors-in-lambda-integration"></a>

 Instead of the standard error described in the preceding section, AWS Lambda allows you to return a custom error object as JSON string. The error can be any valid JSON object. For example, the following JavaScript (Node.js) Lambda function returns a custom error: 

```
export const handler = (event, context, callback) => {
    ...
    // Error caught here:
    var myErrorObj = {
        errorType : "InternalServerError",
        httpStatus : 500,
        requestId : context.awsRequestId,
        trace : {
            "function": "abc()",
            "line": 123,
            "file": "abc.js"
        }
    }
    callback(JSON.stringify(myErrorObj));
};
```

 You must turn the `myErrorObj` object into a JSON string before calling `callback` to exit the function. Otherwise, the `myErrorObj` is returned as a string of `"[object Object]"`. When a method of your API is integrated with the preceding Lambda function, API Gateway receives an integration response with the following payload: 

```
{
    "errorMessage": "{\"errorType\":\"InternalServerError\",\"httpStatus\":500,\"requestId\":\"e5849002-39a0-11e7-a419-5bb5807c9fb2\",\"trace\":{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}}"
}
```

 As with any integration response, you can pass through this error response as-is to the method response. Or you can have a mapping template to transform the payload into a different format. For example, consider the following body-mapping template for a method response of `500` status code: 

```
{
    errorMessage: $input.path('$.errorMessage');
}
```

This template translates the integration response body that contains the custom error JSON string to the following method response body. This method response body contains the custom error JSON object: 

```
{
    "errorMessage" : {
        errorType : "InternalServerError",
        httpStatus : 500,
        requestId : context.awsRequestId,
        trace : {
            "function": "abc()",
            "line": 123,
            "file": "abc.js"
        }
    }
};
```

 Depending on your API requirements, you may need to pass some or all of the custom error properties as method response header parameters. You can achieve this by applying the custom error mappings from the integration response body to the method response headers. 

For example, the following OpenAPI extension defines a mapping from the `errorMessage.errorType`, `errorMessage.httpStatus`, `errorMessage.trace.function`, and `errorMessage.trace` properties to the `error_type`, `error_status`, `error_trace_function`, and `error_trace` headers, respectively. 

```
"x-amazon-apigateway-integration": {
    "responses": {
        "default": {
          "statusCode": "200",
          "responseParameters": {
            "method.response.header.error_trace_function": "integration.response.body.errorMessage.trace.function",
            "method.response.header.error_status": "integration.response.body.errorMessage.httpStatus",
            "method.response.header.error_type": "integration.response.body.errorMessage.errorType",
            "method.response.header.error_trace": "integration.response.body.errorMessage.trace"
          },
          ...
        }
    }
}
```

 At runtime, API Gateway deserializes the `integration.response.body` parameter when performing header mappings. However, this deserialization applies only to body-to-header mappings for Lambda custom error responses and does not apply to body-to-body mappings using `$input.body`. With these custom-error-body-to-header mappings, the client receives the following headers as part of the method response, provided that the `error_status`, `error_trace`, `error_trace_function`, and `error_type` headers are declared in the method request. 

```
"error_status":"500",
"error_trace":"{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}",
"error_trace_function":"abc()",
"error_type":"InternalServerError"
```

The `errorMessage.trace` property of the integration response body is a complex property. It is mapped to the `error_trace` header as a JSON string. 

# HTTP integrations for REST APIs in API Gateway
<a name="setup-http-integrations"></a>

 You can integrate an API method with an HTTP endpoint using the HTTP proxy integration or the HTTP custom integration. 

API Gateway supports the following endpoint ports: 80, 443 and 1024-65535.

 With proxy integration, setup is simple. You only need to set the HTTP method and the HTTP endpoint URI, according to the backend requirements, if you are not concerned with content encoding or caching. 

 With custom integration, setup is more involved. In addition to the proxy integration setup steps, you need to specify how the incoming request data is mapped to the integration request and how the resulting integration response data is mapped to the method response. 

**Topics**
+ [Set up HTTP proxy integrations in API Gateway](#api-gateway-set-up-http-proxy-integration-on-proxy-resource)
+ [Set up HTTP custom integrations in API Gateway](#set-up-http-custom-integrations)

## Set up HTTP proxy integrations in API Gateway
<a name="api-gateway-set-up-http-proxy-integration-on-proxy-resource"></a>

To set up a proxy resource with the HTTP proxy integration type, create an API resource with a greedy path parameter (for example, `/parent/{proxy+}`) and integrate this resource with an HTTP backend endpoint (for example, `https://petstore-demo-endpoint.execute-api.com/petstore/{proxy}`) on the `ANY` method. The greedy path parameter must be at the end of the resource path. 

As with a non-proxy resource, you can set up a proxy resource with the HTTP proxy integration by using the API Gateway console, importing an OpenAPI definition file, or calling the API Gateway REST API directly. For detailed instructions about using the API Gateway console to configure a proxy resource with the HTTP integration, see [Tutorial: Create a REST API with an HTTP proxy integration](api-gateway-create-api-as-simple-proxy-for-http.md).

The following OpenAPI definition file shows an example of an API with a proxy resource that is integrated with the [PetStore](http://petstore-demo-endpoint.execute-api.com/petstore/pets) website.

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-09-12T23:19:28Z",
      "title": "PetStoreWithProxyResource"
   },
   "paths": {
      "/{proxy+}": {
         "x-amazon-apigateway-any-method": {
            "parameters": [
               {
                  "name": "proxy",
                  "in": "path",
                  "required": true,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {},
            "x-amazon-apigateway-integration": {
               "responses": {
                  "default": {
                     "statusCode": "200"
                  }
               },
               "requestParameters": {
                  "integration.request.path.proxy": "method.request.path.proxy"
               },
               "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/{proxy}",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "ANY",
               "cacheNamespace": "rbftud",
               "cacheKeyParameters": [
                  "method.request.path.proxy"
               ],
               "type": "http_proxy"
            }
         }
      }
   },
   "servers": [
      {
         "url": "https://4z9giyi2c1.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/test"
            }
         }
      }
   ]
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-09-12T23:19:28Z",
    "title": "PetStoreWithProxyResource"
  },
  "host": "4z9giyi2c1.execute-api.us-east-1.amazonaws.com",
  "basePath": "/test",
  "schemes": [
    "https"
  ],
  "paths": {
    "/{proxy+}": {
      "x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "proxy",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {},
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "uri": "http://petstore-demo-endpoint.execute-api.com/petstore/{proxy}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "ANY",
          "cacheNamespace": "rbftud",
          "cacheKeyParameters": [
            "method.request.path.proxy"
          ],
          "type": "http_proxy"
        }
      }
    }
  }
}
```

------

In this example, a cache key is declared on the `method.request.path.proxy` path parameter of the proxy resource. This is the default setting when you create the API using the API Gateway console. The API's base path (`/test`, corresponding to a stage) is mapped to the website's PetStore page (`/petstore`). The single integration request mirrors the entire PetStore website using the API's greedy path variable and the catch-all `ANY` method. The following examples illustrate this mirroring. 
+ **Set `ANY` as `GET` and `{proxy+}` as `pets`**

  Method request initiated from the frontend:

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets HTTP/1.1
  ```

  Integration request sent to the backend:

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets HTTP/1.1
  ```

  The run-time instances of the `ANY` method and proxy resource are both valid. The call returns a `200 OK` response with the payload containing the first batch of pets, as returned from the backend.
+ **Set `ANY` as `GET` and `{proxy+}` as `pets?type=dog`**

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets?type=dog HTTP/1.1
  ```

  Integration request sent to the backend:

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets?type=dog HTTP/1.1
  ```

  The run-time instances of the `ANY` method and proxy resource are both valid. The call returns a `200 OK` response with the payload containing the first batch of specified dogs, as returned from the backend.
+ **Set `ANY` as `GET` and `{proxy+}` as `pets/{petId}`**

  Method request initiated from the frontend:

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets/1 HTTP/1.1
  ```

  Integration request sent to the backend:

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets/1 HTTP/1.1
  ```

  The run-time instances of the `ANY` method and proxy resource are both valid. The call returns a `200 OK` response with the payload containing the specified pet, as returned from the backend.
+ **Set `ANY` as `POST` and `{proxy+}` as `pets`**

  Method request initiated from the frontend:

  ```
  POST https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets HTTP/1.1
  Content-Type: application/json
  Content-Length: ...
  
  {
    "type" : "dog",
    "price" : 1001.00
  }
  ```

  Integration request sent to the backend:

  ```
  POST http://petstore-demo-endpoint.execute-api.com/petstore/pets HTTP/1.1
  Content-Type: application/json
  Content-Length: ...
  
  {
    "type" : "dog",
    "price" : 1001.00
  }
  ```

  The run-time instances of the `ANY` method and proxy resource are both valid. The call returns a `200 OK` response with the payload containing the newly created pet, as returned from the backend.
+ **Set `ANY` as `GET` and `{proxy+}` as `pets/cat`**

  Method request initiated from the frontend:

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test/pets/cat
  ```

  Integration request sent to the backend:

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets/cat
  ```

  The run-time instance of the proxy resource path does not correspond to a backend endpoint and the resulting request is invalid. As a result, a `400 Bad Request` response is returned with the following error message. 

  ```
  {
    "errors": [
      {
        "key": "Pet2.type",
        "message": "Missing required field"
      },
      {
        "key": "Pet2.price",
        "message": "Missing required field"
      }
    ]
  }
  ```
+ **Set `ANY` as `GET` and `{proxy+}` as `null`**

  Method request initiated from the frontend:

  ```
  GET https://4z9giyi2c1.execute-api.us-west-2.amazonaws.com/test
  ```

  Integration request sent to the backend:

  ```
  GET http://petstore-demo-endpoint.execute-api.com/petstore/pets
  ```

  The targeted resource is the parent of the proxy resource, but the run-time instance of the `ANY` method is not defined in the API on that resource. As a result, this `GET` request returns a `403 Forbidden` response with the `Missing Authentication Token` error message as returned by API Gateway. If the API exposes the `ANY` or `GET` method on the parent resource (`/`), the call returns a `404 Not Found` response with the `Cannot GET /petstore` message as returned from the backend.

For any client request, if the targeted endpoint URL is invalid or the HTTP verb is valid but not supported, the backend returns a `404 Not Found` response. For an unsupported HTTP method, a `403 Forbidden` response is returned.

## Set up HTTP custom integrations in API Gateway
<a name="set-up-http-custom-integrations"></a>

 With the HTTP custom integration, also known as the non-proxy integration, you have more control of which data to pass between an API method and an API integration and how to pass the data. You do this using data mappings. 

As part of the method request setup, you set the [requestParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#requestParameters) property on a [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) resource. This declares which method request parameters, which are provisioned from the client, are to be mapped to integration request parameters or applicable body properties before being dispatched to the backend. Then, as part of the integration request setup, you set the [requestParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#requestParameters) property on the corresponding [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource to specify the parameter-to-parameter mappings. You also set the [requestTemplates](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#requestTemplates) property to specify mapping templates, one for each supported content type. The mapping templates map method request parameters, or body, to the integration request body. 

 Similarly, as part of the method response setup, you set the [responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html#responseParameters) property on the [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) resource. This declares which method response parameters, to be dispatched to the client, are to be mapped from integration response parameters or certain applicable body properties that were returned from the backend. You then set up the [selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern) to choose an integration response based on the response from the backend. For a non-proxy HTTP integration, this is a regular expression. For example, to map all 2xx HTTP response status codes from an HTTP endpoint to this output mapping, use `2\d{2}`.

**Note**  
API Gateway uses Java pattern-style regexes for response mapping. For more information, see [Pattern](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) in the Oracle documentation.

Then, as part of the integration response setup, you set the [responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#responseParameters) property on the corresponding [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) resource to specify the parameter-to-parameter mappings. You also set the [responseTemplates](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#responseTemplates) map to specify mapping templates, one for each supported content type. The mapping templates map integration response parameters, or integration response body properties, to the method response body. 

 For more information about setting up mapping templates, see [Data transformations for REST APIs in API Gateway](rest-api-data-transformations.md).

# Stream the integration response for your proxy integrations in API Gateway
<a name="response-transfer-mode"></a>

You can configure your proxy integration to control how API Gateway returns your integration response. By default, API Gateway waits to receive the complete response before beginning transmission. However, if you set your integration's response transfer mode to `STREAM`, API Gateway doesn't wait for a response to be completely computed before sending it to the client. Response streaming works for all REST API endpoint types.

Use response streaming for the following use cases:
+ Lower the time-to-first-byte (TTFB) for generative AI applications like chatbots.
+ Stream large image, video, or music files without using an S3 pre-signed URL.
+ Perform long-running operations while reporting incremental progress like server-sent events (SSE).
+ Exceed API Gateway's 10 MB response payload limit.
+ Exceed API Gateway's 29 second timeout limit without requesting an integration timeout limit increase.
+ Receive a binary payload without configuring the binary media types.

## Considerations for response payload streaming
<a name="response-transfer-mode-considerations"></a>

The following considerations might impact your use of response payload streaming:
+ You can only use response payload streaming for `HTTP_PROXY` or `AWS_PROXY` integration types. This includes Lambda proxy integrations and private integrations that use `HTTP_PROXY` integrations.
+ The default transfer mode setting is `BUFFERED`. To use response streaming you must change the response transfer mode to `STREAM`.
+ Response streaming is only supported for REST APIs.
+ Request streaming isn't supported.
+ You can stream your response for up to 15 minutes.
+ Your streams are subject to idle timeouts. For Regional or private endpoints, the timeout is 5 minutes. For edge-optimized endpoints, the timeout is 30 seconds.
+ If you use response streaming for a Regional REST API with your own CloudFront distribution, you can achieve an idle time out greater than 30 seconds by increasing the response timeout of your CloudFront distribution. For more information, see [Response timeout](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesOrigin.html#DownloadDistValuesOriginResponseTimeout).
+ When the response transfer mode is set to `STREAM`, API Gateway can’t support features that require buffering the entire integration response. Because of this, the following features aren't supported with response streaming:
  + Endpoint caching
  + Content encoding. If you want to compress your integration response, do this in your integration.
  + Response transformation with VTL
+ Within each streaming response, the first 10MB of response payload is not subject to any bandwidth restrictions. Response payload data exceeding 10MB is restricted to 2MB/s.
+ When the connection between the client and API Gateway or between API Gateway and Lambda is closed due to timeout, the Lambda function might continue to execute. For more information, see [Configure Lambda function timeout](https://docs.aws.amazon.com/lambda/latest/dg/configuration-timeout.html).
+ Response streaming incurs a cost. For more information, see [API Gateway Pricing](https://aws.amazon.com/api-gateway/pricing/).

# Set up an HTTP proxy integration with payload response streaming in API Gateway
<a name="response-streaming-http"></a>

When you set up response payload streaming, you specify the response transfer mode in the integration request of your method. You configure these settings in the integration request to control how API Gateway behaves before and during the integration response. When you use response streaming, you can configure the integration timeout up to 15 minutes.

When you use payload response streaming with an `HTTP_PROXY` integration, API Gateway won't send the HTTP response status code or any HTTP response headers until it fully receives all headers.

## Create an HTTP proxy integration with payload response streaming
<a name="response-streaming-http-create"></a>

The following procedure shows you how to import a new API with the `responseTransferMode` set to `STREAM`. If you have an existing integration API and want to modify the `responseTransferMode`, see [Update the response transfer mode for an HTTP proxy integration](#response-streaming-http-update).

------
#### [ AWS Management Console ]

**To create an HTTP proxy integration with payload response streaming**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **Create resource**.

1. For **Resource name**, enter **streaming**.

1. Choose **Create resource**.

1. With the **/streaming** resource selected, choose **Create method**.

1. For **Method type**, choose **ANY**.

1. For **Integration type**, choose **HTTP**.

1. Choose **HTTP proxy integration**.

1. For **Response transfer mode**, choose **Stream**.

1. For **HTTP method**, choose a method.

1. For **Endpoint URL**, enter an integration endpoint. Make sure that you choose an endpoint that produces a large payload to be streamed back to you.

1. Choose **Create method**.

After you create your method, deploy your API.

**To deploy your API**

1. Choose **Deploy API**.

1. For **Stage**, select **New stage**.

1. For **Stage name**, enter **prod**.

1. (Optional) For **Description**, enter a description.

1. Choose **Deploy**.

------
#### [ AWS CLI ]

**To create a new API with payload response streaming**

1. Copy the following Open API file, and then save it as `ResponseStreamDemoSwagger.yaml`. In this file, `responseTransferMode` is set to `STREAM`. The integration endpoint is set to `https://example.com`, but we recommend that you modify it to an endpoint that produces a large payload to be streamed back to you.

   ```
   openapi: "3.0.1"
   info:
     title: "ResponseStreamingDemo"
     version: "2025-04-28T17:28:25Z"
   servers:
   - url: "{basePath}"
     variables:
       basePath:
         default: "prod"
   paths:
     /streaming:
       get:
         x-amazon-apigateway-integration:
           httpMethod: "GET"
           uri: "https://example.com"
           type: "http_proxy"
           timeoutInMillis: 900000
           responseTransferMode: "STREAM"
   ```

1. Use the following `import-rest-api` command to import your OpenAPI definition:

   ```
   aws apigateway import-rest-api \
     --body 'fileb://~/ResponseStreamDemoSwagger.yaml' \
     --parameters endpointConfigurationTypes=REGIONAL \
     --region us-west-1
   ```

1. Use the following `create-deployment` command to deploy your new API to a stage:

   ```
   aws apigateway create-deployment \
     --rest-api-id a1b2c3 \
     --stage-name prod \
     --region us-west-1
   ```

------

## Update the response transfer mode for an HTTP proxy integration
<a name="response-streaming-http-update"></a>

The following procedure shows how to update the response transfer mode for an HTTP proxy integration.

------
#### [ AWS Management Console ]

**To update the response transfer mode for an HTTP proxy integration**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose a method.

1. On the **Integration request** tab, under **Integration request settings**, choose **Edit**.

1. For **Response transfer mode**, choose **Stream**.

1. Choose **Save**.

After you update your method, deploy your API.

**To deploy your API**

1. Choose **Deploy API**.

1. For **Stage**, select **New stage**.

1. For **Stage name**, enter **prod**.

1. (Optional) For **Description**, enter a description.

1. Choose **Deploy**.

------
#### [ AWS CLI ]

The following `update-integration` command updates the transfer mode of an integration from `BUFFERED` to `STREAM`. For any existing APIs, the response transfer mode for all integrations is set to `BUFFERED`.

```
aws apigateway update-integration \
 --rest-api-id a1b2c3 \
 --resource-id aaa111 \
 --http-method GET \
 --patch-operations "op='replace',path='/responseTransferMode',value=STREAM" \
 --region us-west-1
```

You need to redeploy your API for the changes to take effect. If you customized the integration timeout, this timeout value is removed, as API Gateway streams your response for up to 5 minutes.

The following `update-integration` command updates the transfer mode of an integration from `STREAM` to `BUFFERED`:

```
aws apigateway update-integration \
 --rest-api-id a1b2c3 \
 --resource-id aaa111 \
 --http-method GET \
 --patch-operations "op='replace',path='/responseTransferMode',value=BUFFERED" \
 --region us-west-1
```

You need to redeploy your API for the changes to take effect.

------

# Set up a Lambda proxy integration with payload response streaming in API Gateway
<a name="response-transfer-mode-lambda"></a>

You can stream the response of a Lambda function to improve time to first byte (TTFB) performance and send partial responses back to the client as they become available. API Gateway requires you to use the [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) Lambda API to invoke your Lambda function. API Gateway passes an event object to the Lambda function. The backend Lambda function parses the incoming request data to determine the response that it returns. In order for API Gateway to stream the Lambda output, the Lambda function must output the [format](#response-transfer-mode-lambda-format) required by API Gateway.

## Differences in Lambda proxy integrations between stream and buffered response transfer mode
<a name="response-transfer-mode-lambda-comparison"></a>

The following list describes the differences between a Lambda proxy integration and a Lambda proxy integration for response streaming:
+ API Gateway uses the [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) API to invoke the Lambda proxy integration for response streaming. This results in a different URI, which is the following:

  ```
  arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations
  ```

  This ARN uses a different date for the API version and a different service action compared to Lambda proxy integration.

  If you use the API Gateway console for response streaming, the console uses the correct URI for you.
+ In a Lambda proxy integration, API Gateway sends the response to client only after it receives the full response from Lambda. In a Lambda proxy integration for response streaming, API Gateway begins the payload stream after it receives the valid metadata and delimiter from Lambda. 
+ Lambda proxy integration for response streaming uses the same input format as the proxy integration, but it requires a different output format.

## Lambda proxy integration format for response streaming
<a name="response-transfer-mode-lambda-format"></a>

When API Gateway invokes a Lambda function with response streaming, the input format is the same as the input format of a Lambda function for proxy integration. For more information, see [Input format of a Lambda function for proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format). 

When Lambda streams a response to API Gateway, the response must adhere to the following format. This format uses a delimiter to separate the metadata JSON and the raw payload. In this case, the payload data is streamed as it is transmitted by your streaming Lambda function:

```
{
  "headers": {"headerName": "headerValue", ...},
  "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
  "cookies" : ["cookie1", "cookie2"],
  "statusCode": httpStatusCode
}<DELIMITER>PAYLOAD1 | PAYLOAD2 | PAYLOAD3
```

In the output:
+ The `headers`, `multiValueHeaders`, `cookies`, and `statusCode` keys can be unspecified if no extra response headers are to be returned.
+ The `headers` key can only contain single-value headers.
+ The output expects the headers to contain either `Transfer-Encoding: chunked` or `Content-length: number`. If your function doesn't return either of these headers, API Gateway appends `Transfer-Encoding: chunked` to the response header.
+ The `multiValueHeaders` key can contain multi-value headers as well as single-value headers. You can use the `multiValueHeaders` key to specify all of your extra headers, including any single-value ones.
+ If you specify values for both `headers` and `multiValueHeaders`, API Gateway merges them into a single list. If the same key-value pair is specified in both, only the values from `multiValueHeaders` will appear in the merged list.
+ The metadata must be valid JSON. Only `headers`, `multiValueHeaders`, `cookies` and the `statusCode` keys are supported.
+ You must provide a delimiter after the metadata JSON. The delimiter must be 8 null bytes and it must appear within the first 16KB of stream data.
+ API Gateway doesn't require a specific format for the method response payload.

If you're using a function URL to stream your Lambda function, you must modify the input and the output of your Lambda function to satisfy these requirements.

If your Lambda function output doesn't adhere to the requirements of this format, API Gateway might still invoke your Lambda function. The following table shows the combinations of API integration request settings and Lambda function code that is supported by API Gateway. This includes supported combinations for response transfer mode of buffered.


| Response transfer mode | Function code adheres to the required format | Lambda invoke API | Supported by API Gateway | 
| --- | --- | --- | --- | 
|  Stream  |  Yes  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  Yes. API Gateway streams your response.  | 
|  Stream  |  No  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  No. API Gateway invokes your Lambda function and return a 500 error response.  | 
|  Stream  |  Yes  |   [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  No. API Gateway doesn't support this integration configuration.  | 
|  Stream  |  No  |   [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  No. API Gateway doesn't support this integration configuration.  | 
|  Buffered  |  Yes  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  No. API Gateway doesn't support this integration configuration.  | 
|  Buffered  |  No  |   [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html)  |  No. API Gateway doesn't support this integration configuration.  | 
|  Buffered  |  Yes  |   [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  API Gateway returns the HTTP headers and status code but not the response body.  | 
|  Buffered  |  No  |   [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html)  |  Yes. This is a Lambda proxy integration. For more information, see [Lambda proxy integration](set-up-lambda-proxy-integrations.md).  | 

# Configure a Lambda proxy integration with payload response streaming in API Gateway
<a name="response-streaming-lambda-configure"></a>

When you set up response payload streaming, you specify the transfer mode in the integration request of your resource. You configure these settings in the integration request to control how API Gateway behaves before and during the integration response.

## Example Lambda functions for response streaming
<a name="response-streaming-lambda-example"></a>

Your Lambda function must adhere to the [Lambda proxy integration format for response streaming](response-transfer-mode-lambda.md#response-transfer-mode-lambda-format). We recommend you use one of the three example Lambda functions to test out response streaming. When you create your Lambda function, make sure to do the following:
+ Provide an adequate timeout for your function. We recommend you configure a timeout of at least 1 minute to learn about response streaming. When you create your production resources, make sure your Lambda function timeout covers the full request cycle. For more information, see [Configure Lambda function timeout](https://docs.aws.amazon.com/lambda/latest/dg/configuration-timeout.html).
+ Use the latest Node.js runtime.
+ Use a Region where Lambda response streaming is available.

------
#### [ Using HttpResponseStream.from ]

The following code example streams the JSON metadata objects and payloads back to the client using the `awslambda.HttpResponseStream()` method without using the pipeline method. You don't need to create the delimiter. For more information, see [Writing response streaming-enabled Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/config-rs-write-functions.html).

```
export const handler = awslambda.streamifyResponse(
  async (event, responseStream, context) => {
    const httpResponseMetadata = {
      "statusCode": 200,
      "headers": {
        "x-foo": "bar"
      },
      "multiValueHeaders": {
        "x-mv1": ["hello", "world"],
        "Set-Cookie": ["c1=blue", "c2=red"]
      }
    };

    responseStream = awslambda.HttpResponseStream.from(responseStream, httpResponseMetadata);
    await new Promise(r => setTimeout(r, 1000)); // synthetic delay

    responseStream.write("First payload ");
    await new Promise(r => setTimeout(r, 1000)); // synthetic delay

    responseStream.write("Final payload");
    responseStream.end();
});
```

------
#### [ Using the pipeline method ]

Lambda recommends that when you write response streaming-enabled functions, you use the `awslambda.streamifyResponse()` decorator that the native Node.js runtimes provide, and the `pipeline()` method. When you use the pipeline method, you don't need to create the delimiter, Lambda does this for you. For more information, see [Writing response streaming-enabled Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/config-rs-write-functions.html).

The following code example streams the JSON metadata objects and three payloads back to the client.

```
import { pipeline } from 'node:stream/promises';
import { Readable } from 'node:stream';

export const handler = awslambda.streamifyResponse(
  async (event, responseStream, context) => {
    const httpResponseMetadata = {
      statusCode: 200,
      headers: {
        "Content-Type": "text/plain",
        "X-Custom-Header": "Example-Custom-Header"
      }
    };

    responseStream = awslambda.HttpResponseStream.from(responseStream, httpResponseMetadata);

    const dataStream = Readable.from(async function* () {
      yield "FIRST payload\n";
      await new Promise(r => setTimeout(r, 1000));
      yield "SECOND payload\n";
      await new Promise(r => setTimeout(r, 1000));
      yield "THIRD payload\n";
      await new Promise(r => setTimeout(r, 1000));
    }());

    await pipeline(dataStream, responseStream);
  }
);
```

------
#### [ Without using the pipeline method ]

The following code example streams the JSON metadata objects and three payloads back to the client without using the `awslambda.HttpResponseStream()` method. Without the `awslambda.HttpResponseStream()` method, you must include a delimiter of 8 null bytes between the metadata and the payload. 

```
export const handler = awslambda.streamifyResponse(async (event, response, ctx) => {
  response.write('{"statusCode": 200, "headers": {"hdr-x": "val-x"}}');
  response.write("\x00".repeat(8)); // DELIMITER
  await new Promise(r => setTimeout(r, 1000));

  response.write("FIRST payload");
  await new Promise(r => setTimeout(r, 1000));

  response.write("SECOND payload");
  await new Promise(r => setTimeout(r, 1000));

  response.write("FINAL payload");
  response.end();
});
```

------

## Create a Lambda proxy integration with payload response streaming
<a name="response-streaming-lambda-create"></a>

The following procedure shows how to create a Lambda proxy integration with payload response streaming. Use the example Lambda function or create your own.

------
#### [ AWS Management Console ]

**To create a Lambda proxy integration with payload response streaming**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **Create resource**.

1. For **Resource name**, enter **streaming**.

1. Choose **Create resource**.

1. With the **/streaming** resource selected, choose **Create method**.

1. For **Method type**, choose **ANY**.

1. For **Integration type**, choose **Lambda**.

1. Choose **Lambda proxy integration**.

1. For **Response transfer mode**, choose **Stream**.

1. For **Lambda function**, choose the name of your Lambda function.

   The API Gateway console automatically uses [InvokeWithResponseStream](https://docs.aws.amazon.com/lambda/latest/api/API_InvokeWithResponseStream.html) API to invoke the Lambda function. You are responsible for writing a response streaming-enabled Lambda function. For an example, see [Example Lambda functions for response streaming](#response-streaming-lambda-example).

1. Choose **Create method**.

After you create your method, deploy your API.

**To deploy your API**

1. Choose **Deploy API**.

1. For **Stage**, select **New stage**.

1. For **Stage name**, enter **prod**.

1. (Optional) For **Description**, enter a description.

1. Choose **Deploy**.

------
#### [ AWS CLI ]

The following procedure shows you how to import a new API with the `responseTransferMode` set to `STREAM`. If you have an existing integration API and want to modify the `responseTransferMode`, see [Update the response transfer mode for a Lambda proxy integration](#response-streaming-lambda-update).

**To create a new API with payload response streaming**

1. Copy the following Open API file, and then save it as `ResponseStreamDemoSwagger.yaml`. In this file, `responseTransferMode` is set to `STREAM`, and the integration URI is set to `arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations`.

   Replace the function name from `my-function` with a streaming-enabled function and replace the credentials with an IAM role that has policies allowing the `apigateway` service to invoke Lambda functions.

   ```
   openapi: "3.0.1"
   info:
     title: "ResponseStreamingDemo"
     version: "2025-04-28T17:28:25Z"
   servers:
   - url: "{basePath}"
     variables:
       basePath:
         default: "prod"
   paths:
     /lambda:
       get:
         x-amazon-apigateway-integration:
           httpMethod: "POST"
           uri: "arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations"
           type: "aws_proxy"
           timeoutInMillis: 90000
           responseTransferMode: "STREAM"
           credentials: "arn:aws:iam::111122223333:role/apigateway-lambda-role"
   ```

   Instead of supplying an IAM role for credentials, you can use the `add-permission` command for Lambda to add resource-based permissions.

1. Use the following `import-rest-api` command to import your OpenAPI definition:

   ```
   aws apigateway import-rest-api \
     --body 'fileb://~/ResponseStreamDemoSwagger.yaml' \
     --parameters endpointConfigurationTypes=REGIONAL \
     --region us-west-1
   ```

1. Use the following `create-deployment` command to deploy your new API to a stage:

   ```
   aws apigateway create-deployment \
     --rest-api-id a1b2c2 \
     --stage-name prod \
     --region us-west-1
   ```

------

### Update the response transfer mode for a Lambda proxy integration
<a name="response-streaming-lambda-update"></a>

The following procedure shows how to update the response transfer mode for a Lambda proxy integration. When you change the response transfer mode to streaming, update your Lambda function so it adheres to the requirements for response streaming. Use the example Lambda function or create your own.

------
#### [ AWS Management Console ]

**To update the response transfer mode for a Lambda proxy integration**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose a method.

1. On the **Integration request** tab, under **Integration request settings**, choose **Edit**.

1. For **Response transfer mode**, choose **Stream**.

1. For **Lambda function**, choose the name of your Lambda function.

1. Choose **Save**.

After you update your method, deploy your API.

**To deploy your API**

1. Choose **Deploy API**.

1. For **Stage**, select **New stage**.

1. For **Stage name**, enter **prod**.

1. (Optional) For **Description**, enter a description.

1. Choose **Deploy**.

------
#### [ AWS CLI ]

1. Update your Lambda function to be streaming-enabled.

1. Use the following AWS CLI command to update the integration URI and response transfer mode of your integration:

   ```
   aws apigateway update-integration \
    --rest-api-id a1b2c3 \
    --resource-id aaa111 \
    --http-method ANY \
    --patch-operations "[{\"op\":\"replace\",\"path\":\"/uri\",\"value\":\"arn:aws:apigateway:us-west-1:lambda:path/2021-11-15/functions/arn:aws:lambda:us-west-1:111122223333:function:my-function-name/response-streaming-invocations\"}, {\"op\":\"replace\",\"path\":\"/responseTransferMode\",\"value\":\"STREAM\"}]" \
    --region us-west-1
   ```

1. Redeploy your API for the changes to take effect.

------

# Troubleshoot issues with response streaming in API Gateway
<a name="response-streaming-troubleshoot"></a>

The following troubleshooting guidance might help resolve issues with your APIs that use response streaming.

## General troubleshooting
<a name="response-streaming-general-troubleshooting"></a>

You can use the [TestInvokeMethod](https://docs.aws.amazon.com/apigateway/latest/api/API_TestInvokeMethod.html) or the console's test tab to test your stream response. The following considerations might impact your use of test invoke for response streaming:
+ When you test your method, API Gateway buffers your streamed response payload. Once any of the following conditions have been met, API Gateway returns a one-time response containing the buffered payload:
  + The request is complete
  + 35 seconds have elapsed
  + More than 1 MB of response payload has been buffered
+ If more than 35 seconds elapse before your method returns an HTTP response status and all headers, then the response status returned in TestInvokeMethod is 0.
+ API Gateway doesn't produce any execution logs.

After you've deployed your API, you can test your stream response by using a curl command. We recommend that you use the `-i` option to include protocol response headers in the output. To see the response data as it arrives, use the curl option `--no-buffer`

## Troubleshoot cURL errors
<a name="response-streaming-troubleshoot-curl-error"></a>

If you're testing an integration and you receive the error `curl: (18) transfer closed with outstanding read data remaining`, make sure the timeout of your integration is long enough. If you're using a Lambda function, you need to update the response timeout of the Lambda function. For more information, see [Configure Lambda function timeout](https://docs.aws.amazon.com/lambda/latest/dg/configuration-timeout.html).

## Troubleshoot using access logging
<a name="response-streaming-troubleshoot-access-logging"></a>

You can use access logs for your REST API stage to log and troubleshoot your response stream. In addition to the existing variables, you can use the following access log variables:

`$context.integration.responseTransferMode`  
The response transfer mode of your integration. This can be either `BUFFERED` or `STREAMED`.

`$context.integration.timeToAllHeaders`  
The time between when API Gateway establishes the integration connection to when it receives all integration response headers from the client.

`$context.integration.timeToFirstContent`  
The time between when API Gateway establishes the integration connection to when it receives the first content bytes.

`$context.integration.latency` or `$context.integrationLatency`  
The time when API Gateway establishes the integration connection to when the integration response stream is complete.

The following figure shows how these access log variables represent different components of a response stream.

![\[Access log variables for response streaming in API Gateway\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/response-streaming-figure.png)


For more information about access logs, see [Set up CloudWatch logging for REST APIs in API Gateway](set-up-logging.md). You can also use X-Ray to monitor your response stream. For more information, see [Trace user requests to REST APIs using X-Ray in API Gateway](apigateway-xray.md).

# Private integrations for REST APIs in API Gateway
<a name="private-integration"></a>

Use a private integration to expose your HTTP/HTTPS resources within an Amazon VPC for access by clients outside of the VPC. This extends access to your private VPC resources beyond the VPC boundaries. You can control access to your API by using any of the [authorization methods](apigateway-control-access-to-api.md) that API Gateway supports.

To create a private integration, you must first create a VPC link. API Gateway supports VPC links V2 for REST APIs. VPC links V2 let you create private integrations that connect your REST API to Application Load Balancers without using an Network Load Balancer. Using an Application Load Balancer allows you to connect to Amazon ECSs container-based applications and many other backends. VPC links V1 are considered a legacy integration type. While they are supported by API Gateway, we recommend that you don't create new VPC links V1.

## Considerations
<a name="private-integrations-considerations"></a>

The following considerations might impact your use of private integrations:
+ All resources must be owned by the same AWS account. This includes the load balancer, VPC link and REST API.
+ By default, private integration traffic uses the HTTP protocol. To use HTTPS, specify an [https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri](https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri) that contains a secure server name, such as `https://example.com:443/test`.
+ In a private integration, API Gateway includes the [stage](set-up-stages.md) portion of the API endpoint in the request to your backend resources. For example, if you request the `test` stage of an API, API Gateway includes `test/path` in the request to your private integration. To remove the stage name from the request to your backend resources, use [parameter mapping](rest-api-parameter-mapping.md) to create an override for the `$context.requestOverride.path` variable.
+ Private integrations with AWS Cloud Map aren't supported.

**Topics**
+ [Considerations](#private-integrations-considerations)
+ [Set up VPC links V2 in API Gateway](apigateway-vpc-links-v2.md)
+ [Set up a private integration](set-up-private-integration.md)
+ [Private integration using VPC links V1 (legacy)](vpc-links-v1.md)

# Set up VPC links V2 in API Gateway
<a name="apigateway-vpc-links-v2"></a>

VPC links enable you to create private integrations that connect your API routes to private resources in a VPC, such as Application Load Balancers or Amazon ECS container-based applications. A private integration uses a VPC link V2 to encapsulate connections between API Gateway and targeted VPC resources. You can reuse VPC links across different resources and APIs.

When you create a VPC link, API Gateway creates and manages [elastic network interfaces](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html) for the VPC link V2 in your account. This process can take a few minutes. When a VPC link V2 is ready to use, its state transitions from `PENDING` to `AVAILABLE`. 

**Note**  
If no traffic is sent over the VPC link for 60 days, it becomes `INACTIVE`. When a VPC link is in an `INACTIVE` state, API Gateway deletes all of the VPC link’s network interfaces. This causes API requests that depend on the VPC link to fail. If API requests resume, API Gateway reprovisions network interfaces. It can take a few minutes to create the network interfaces and reactivate the VPC link. You can use the VPC link status to monitor the state of your VPC link.

## Create a VPC link V2 by using the AWS CLI
<a name="apigateway-vpc-links-v2-create"></a>

To create a VPC link V2, all resources involved must be owned by the same AWS account. The following [create-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-vpc-link.html) command creates a VPC link:

```
aws apigatewayv2 create-vpc-link --name MyVpcLink \
    --subnet-ids subnet-aaaa subnet-bbbb \
    --security-group-ids sg1234 sg5678
```

**Note**  
VPC links V2 are immutable. After you create a VPC link V2, you can’t change its subnets or security groups.

## Delete a VPC link V2 by using the AWS CLI
<a name="apigateway-vpc-links-v2-delete"></a>

The following [delete-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/delete-vpc-link.html) command deletes a VPC link.

```
aws apigatewayv2 delete-vpc-link --vpc-link-id abcd123
```

## Availability by Region
<a name="apigateway-vpc-links-v2-availability"></a>

VPC links V2 are supported in the following Regions and Availability Zones:

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-vpc-links-v2.html)

# Set up a private integration
<a name="set-up-private-integration"></a>

To create a private integration with an Application Load Balancer or Network Load Balancer, you create an HTTP proxy integration, specify the [VPC link V2](apigateway-vpc-links-v2.md) to use, and provide the ARN of an Network Load Balancer or an Application Load Balancer. By default, private integration traffic uses the HTTP protocol. To use HTTPS, specify an [https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri](https://docs.aws.amazon.com/apigateway/latest/api/API_PutIntegration.html#apigw-PutIntegration-request-uri) that contains a secure server name, such as `https://example.com:443/test`. For a complete tutorial on how to create a REST API with a private integration, see [Tutorial: Create a REST API with a private integration](getting-started-with-private-integration.md).

## Create a private integration
<a name="set-up-private-integration-create"></a>

The following procedure shows how to create a private integration that connects to a load balancer by using a VPC link V2.

------
#### [ AWS Management Console ]

For a tutorial on how to create a private integration see, [Tutorial: Create a REST API with a private integration](getting-started-with-private-integration.md).

------
#### [ AWS CLI ]

The following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/latest/api/API_PutIntegration.html) command creates a private integration that connects to a load balancer by using a VPC link V2:

```
aws apigateway put-integration \
    --rest-api-id abcdef123 \
    --resource-id aaa000 \
    --integration-target 'arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011' \
    --uri 'https://example.com:443/path' \
    --http-method GET \
    --type HTTP_PROXY \
    --integration-http-method GET \
    --connection-type VPC_LINK \
    --connection-id bbb111
```

Instead of directly providing the connection ID, you can use a stage variable instead. When you deploy your API to a stage, you set the VPC link V2 ID. The following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/latest/api/API_PutIntegration.html) command creates a private integration using a stage variable for the VPC link V2 ID:

```
aws apigateway put-integration \
    --rest-api-id abcdef123 \
    --resource-id aaa000 \
    --integration-target 'arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011' \
    --uri 'https://example.com:443/path' \
    --http-method GET \
    --type HTTP_PROXY \
    --integration-http-method GET \
    --connection-type VPC_LINK \
    --connection-id "\${stageVariables.vpcLinkV2Id}"
```

Make sure to double-quote the stage variable expression (\$1\$1stageVariables.vpcLinkV2Id\$1) and escape the \$1 character.

------
#### [ OpenAPI ]

You can set up an API with the private integration by importing the API's OpenAPI file. The settings are similar to the OpenAPI definitions of an API with HTTP integrations, with the following exceptions: 
+ You must explicitly set `connectionType` to `VPC_LINK`.
+ You must explicitly set `connectionId` to the ID of a `VpcLinkV2` or to a stage variable referencing the ID of a `VpcLinkV2`.
+ The `uri` parameter in the private integration points to an HTTP/HTTPS endpoint in the VPC, but is used instead to set up the integration request's `Host` header.
+ The `uri` parameter in the private integration with an HTTPS endpoint in the VPC is used to verify the stated domain name against the one in the certificate installed on the VPC endpoint.

 You can use a stage variable to reference the `VpcLinkV2` ID. Or you can assign the ID value directly to `connectionId`. 

The following JSON-formatted OpenAPI file shows an example of an API with a VPC link as referenced by a stage variable (`${stageVariables.vpcLinkIdV2}`):

```
{
  "swagger": "2.0",
  "info": {
    "version": "2017-11-17T04:40:23Z",
    "title": "MyApiWithVpcLinkV2"
  },
  "host": "abcdef123.execute-api.us-west-2.amazonaws.com",
  "basePath": "/test",
  "schemes": [
    "https"
  ],
  "paths": {
    "/": {
      "get": {
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "uri": "https://example.com:443/path",
          "passthroughBehavior": "when_no_match",
          "connectionType": "VPC_LINK",
          "connectionId": "${stageVariables.vpcLinkV2Id}",
          "integration-target": "arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011",
          "httpMethod": "GET",
          "type": "http_proxy"
        }
      }
    }
  },
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}
```

------

## Update a private integration
<a name="set-up-private-integration-update"></a>

The following example updates the VPC link V2 for a private integration.

------
#### [ AWS Management Console ]

**To update a private integration**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API with a private integration.

1. Choose the resource and method that uses a private integration.

1. On the **Integration request tab**, under the **Integration request settings**, choose **Edit**.

1. You can edit the setting of your private integration. If you are currently using a VPC link V1, you can change your VPC link to a VPC link V2.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

------
#### [ AWS CLI ]

The following [update-integration](https://docs.aws.amazon.com/cli/latest/reference/latest/api/API_PutIntegration.html) command updates a private integration to use a VPC link V2:

```
aws apigateway update-integration \
    --rest-api-id a1b2c3d4e5 \
    --resource-id a1b2c3 \
    --http-method GET \
    --patch-operations "[{\"op\":\"replace\",\"path\":\"/connectionId\",\"value\":\"pk0000\"}, {\"op\":\"replace\",\"path\":\"/uri\",\"value\":\"http://example.com\"}, {\"op\":\"replace\",\"path\":\"/integrationTarget\",\"value\":\"arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/app/myLoadBalancerName/1234567891011\"}]"
```

------

# Private integration using VPC links V1 (legacy)
<a name="vpc-links-v1"></a>

**Note**  
The following implementation of private integrations uses VPC links V1. VPC links V1 are legacy resources. We recommend that you use [VPC links V2 for REST APIs](apigateway-vpc-links-v2.md).

To create a private integration, you must first create a Network Load Balancer. Your Network Load Balancer must have a [listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-listeners.html) that routes requests to resources in your VPC. To improve the availability of your API, ensure that your Network Load Balancer routes traffic to resources in more than one Availability Zone in the AWS Region. Then, you create a VPC link that you use to connect your API and your Network Load Balancer. After you create a VPC link, you create private integrations to route traffic from your API to resources in your VPC through your VPC link and Network Load Balancer. The Network Load Balancer and API must be owned by the same AWS account.

**Topics**
+ [Set up a Network Load Balancer for API Gateway private integrations (legacy)](set-up-nlb-for-vpclink-using-console.md)
+ [Grant permissions for API Gateway to create a VPC link (legacy)](grant-permissions-to-create-vpclink.md)
+ [Set up an API Gateway API with private integrations using the AWS CLI (legacy)](set-up-api-with-vpclink-cli.md)
+ [API Gateway accounts used for private integrations (legacy)](set-up-api-with-vpclink-accounts.md)

# Set up a Network Load Balancer for API Gateway private integrations (legacy)
<a name="set-up-nlb-for-vpclink-using-console"></a>

**Note**  
The following implementation of private integrations uses VPC links V1. VPC links V1 are legacy resources. We recommend that you use [VPC links V2 for REST APIs](apigateway-vpc-links-v2.md).

 The following procedure outlines the steps to set up a Network Load Balancer (NLB) for API Gateway private integrations using the Amazon EC2 console and provides references for detailed instructions for each step. 

For each VPC you have resources in, you only need to configure one NLB and one VPCLink. The NLB supports multiple [listeners](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-listeners.html) and [target groups](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html) per NLB. You can configure each service as a specific listener on the NLB and use a single VPCLink to connect to the NLB. When creating the private integration in API Gateway you then define each service using the specific port that is assigned for each service. For more information, see [Tutorial: Create a REST API with a private integration](getting-started-with-private-integration.md). The Network Load Balancer and API must be owned by the same AWS account.

**To create a Network Load Balancer for private integration using the API Gateway console**

1. Sign in to the AWS Management Console and open the Amazon EC2 console at [https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/).

1. Set up a web server on an Amazon EC2 instance. For an example setup, see [Installing a LAMP Web Server on Amazon Linux 2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-lamp-amazon-linux-2.html). 

1. Create a Network Load Balancer, register the EC2 instance with a target group, and add the target group to a listener of the Network Load Balancer. For details, follow the instructions in [Getting Started with Network Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancer-getting-started.html). 

1. After the Network Load Balancer is created, do the following:

   1.  Note the ARN of the Network Load Balancer. You will need it to create a VPC link in API Gateway for integrating the API with the VPC resources behind the Network Load Balancer.

   1.  Turn off security group evaluation for PrivateLink.
      + To turn off security group evaluation for PrivateLink traffic using the console, you can choose the **Security** tab, and then **Edit**. In the **Security settings**, clear **Enforce inbound rules on PrivateLink traffic**.
      + Use the following [set-security-groups](https://docs.aws.amazon.com/cli/latest/reference/elbv2/set-security-groups.html) command to turn off security group evaluation for PrivateLink traffic:

        ```
        aws elbv2 set-security-groups --load-balancer-arn arn:aws:elasticloadbalancing:us-east-2:111122223333:loadbalancer/net/my-loadbalancer/abc12345 \
          --security-groups sg-123345a --enforce-security-group-inbound-rules-on-private-link-traffic off
        ```

**Note**  
Do not add any dependencies to API Gateway CIDRs as they are bound to change without notice.

# Grant permissions for API Gateway to create a VPC link (legacy)
<a name="grant-permissions-to-create-vpclink"></a>

**Note**  
The following implementation of private integrations uses VPC links V1. VPC links V1 are legacy resources. We recommend that you use [VPC links V2 for REST APIs](apigateway-vpc-links-v2.md).

For you or a user in your account to create and maintain a VPC link, you or the user must have permissions to create, delete, and view VPC endpoint service configurations, change VPC endpoint service permissions, and examine load balancers. To grant such permissions, use the following steps. 

**To grant permissions to create, update, and delete a VPC link**

1. Create an IAM policy similar to the following:

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "apigateway:POST",
                   "apigateway:GET",
                   "apigateway:PATCH",
                   "apigateway:DELETE"
               ],
               "Resource": [
                   "arn:aws:apigateway:us-east-1::/vpclinks",
                   "arn:aws:apigateway:us-east-1::/vpclinks/*"
               ]
           },
           {
               "Effect": "Allow",
               "Action": [
                   "elasticloadbalancing:DescribeLoadBalancers"
               ],
               "Resource": "*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "ec2:CreateVpcEndpointServiceConfiguration",
                   "ec2:DeleteVpcEndpointServiceConfigurations",
                   "ec2:DescribeVpcEndpointServiceConfigurations",
                   "ec2:ModifyVpcEndpointServicePermissions"
               ],
               "Resource": "*"
           }
       ]
   }
   ```

------

   If you want to enable tagging for your VPC link, make sure to allow tagging operations. For more information, see [Allow tagging operations](apigateway-tagging-iam-policy.md#allow-tagging).

1. Create or choose an IAM role and attach the preceding policy to the role.

1. Assign the IAM role to you or a user in your account who is creating VPC links.

# Set up an API Gateway API with private integrations using the AWS CLI (legacy)
<a name="set-up-api-with-vpclink-cli"></a>

**Note**  
The following implementation of private integrations uses VPC links V1. VPC links V1 are legacy resources. We recommend that you use [VPC links V2 for REST APIs](apigateway-vpc-links-v2.md).

The following tutorial shows how to use the AWS CLI to create a VPC link and a private integration. The following prerequisites are required:
+ You need an Network Load Balancer created and configured with your VPC source as the target. For more information, see [Set up a Network Load Balancer for API Gateway private integrations (legacy)](set-up-nlb-for-vpclink-using-console.md). This must be in the same AWS account as your API. You need the Network Load Balancer ARN to create your VPC link.
+ To create and manage a `VpcLink`, you need the permissions to create a `VpcLink` in your API. You don't need the permissions to use the `VpcLink`. For more information, see [Grant permissions for API Gateway to create a VPC link (legacy)](grant-permissions-to-create-vpclink.md).

**To set up an API with the private integration using AWS CLI**

1. Use the following [create-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-vpc-link.html) command to create a `VpcLink` targeting the specified Network Load Balancer:

   ```
   aws apigateway create-vpc-link \
       --name my-test-vpc-link \
       --target-arns arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/net/my-vpclink-test-nlb/1234567890abcdef
   ```

   The output of this command acknowledges the receipt of the request and shows the `PENDING` status for the `VpcLink` being created.

   ```
   {
       "status": "PENDING", 
       "targetArns": [
           "arn:aws:elasticloadbalancing:us-east-2:123456789012:loadbalancer/net/my-vpclink-test-nlb/1234567890abcdef"
       ], 
       "id": "gim7c3", 
       "name": "my-test-vpc-link"
   }
   ```

   It takes 2-4 minutes for API Gateway to finish creating the `VpcLink`. When the operation finishes successfully, the `status` is `AVAILABLE`. You can verify this by using the following [get-vpc-link](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-vpc-link.html) command:

   ```
   aws apigateway get-vpc-link --vpc-link-id gim7c3
   ```

   If the operation fails, you get a `FAILED` status, with the `statusMessage` containing the error message. For example, if you attempt to create a `VpcLink` with a Network Load Balancer that is already associated with a VPC endpoint, you get the following on the `statusMessage` property:

   ```
   "NLB is already associated with another VPC Endpoint Service"
   ```

   After the `VpcLink` is created successfully, you can create an API and integrate it with the VPC resource through the `VpcLink`. 

   Note the `id` value of the newly created `VpcLink`. In this example output, it's `gim7c3`. You need it to set up the private integration.

1. Use the following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command to create an API Gateway [https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource:

   ```
   aws apigateway create-rest-api --name 'My VPC Link Test'
   ```

   Note the `RestApi`'s `id` value and the `RestApi`'s `rootResourceId` value in the returned result. You need this value to perform further operations on the API. 

   Next, you create an API with only a `GET` method on the root resource (`/`) and integrate the method with the `VpcLink`.

1. Use the following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command to create the `GET /` method:

   ```
   aws apigateway put-method \
          --rest-api-id  abcdef123 \
          --resource-id skpp60rab7 \
          --http-method GET \
          --authorization-type "NONE"
   ```

   If you don't use the proxy integration with the `VpcLink`, you must also set up at least a method response of the `200` status code. You use the proxy integration here.

1. After you create the `GET /` method, you set up the integration. For a private integration, you use the `connection-id` parameter to provide the `VpcLink` ID. You can use either a stage variable or directly enter the `VpcLink` ID. The `uri` parameter is not used for routing requests to your endpoint, but is used for setting the `Host` header and for certificate validation. 

------
#### [ Use the VPC link ID ]

   Use the following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) command to use the `VpcLink` ID directly in the integration:

   ```
   aws apigateway put-integration \
       --rest-api-id abcdef123 \
       --resource-id skpp60rab7 \
       --uri 'http://my-vpclink-test-nlb-1234567890abcdef.us-east-2.amazonaws.com' \
       --http-method GET \
       --type HTTP_PROXY \
       --integration-http-method GET \
       --connection-type VPC_LINK \
       --connection-id gim7c3
   ```

------
#### [ Use a stage variable ]

   Use the following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) command to use a stage variable to reference the VPC link ID. When you deploy your API to a stage, you set the VPC link ID.

   ```
   aws apigateway put-integration \
       --rest-api-id abcdef123 \
       --resource-id skpp60rab7 \
       --uri 'http://my-vpclink-test-nlb-1234567890abcdef.us-east-2.amazonaws.com' \
       --http-method GET \
       --type HTTP_PROXY \
       --integration-http-method GET \
       --connection-type VPC_LINK \
       --connection-id "\${stageVariables.vpcLinkId}"
   ```

   Make sure to double-quote the stage variable expression (`${stageVariables.vpcLinkId}`) and escape the `$` character.

------

   At any point, you can also update the integration to change the `connection-id`. Use the following [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration.html) command to update your integration:

   ```
    aws apigateway update-integration \
       --rest-api-id abcdef123 \
       --resource-id skpp60rab7 \
       --http-method GET \
       --patch-operations '[{"op":"replace","path":"/connectionId","value":"${stageVariables.vpcLinkId}"}]'
   ```

   Make sure to use a stringified JSON list as the `patch-operations` parameter value.

   Because you used the private proxy integration, your API is now ready for deployment and for test runs.

1. If you used the stage variable to define your `connection-id`, you need to deploy your API to test it. Use the following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to deploy your API with a stage variable:

   ```
   aws apigateway create-deployment \
       --rest-api-id abcdef123 \
       --stage-name test \
       --variables vpcLinkId=gim7c3
   ```

   To update the stage variable with a different `VpcLink` ID, such as `asf9d7`, use the following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command:

   ```
   aws apigateway update-stage \
       --rest-api-id abcdef123 \
       --stage-name test \
       --patch-operations op=replace,path='/variables/vpcLinkId',value='asf9d7'
   ```

   When you hardcode the `connection-id` property with the `VpcLink` ID literal, you don't need to deploy your API to test it. Use the [test-invoke-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/test-invoke-method.html) command to test your API before it is deployed. 

1. Use the following command to invoke your API:

   ```
   curl -X GET https://abcdef123.execute-api.us-east-2.amazonaws.com/test
   ```

   Alternatively, you can enter your API's invoke-URL in a web browser to view the result.

# API Gateway accounts used for private integrations (legacy)
<a name="set-up-api-with-vpclink-accounts"></a>

The following region-specific API Gateway account IDs are automatically added to your VPC endpoint service as `AllowedPrincipals` when you create a `VpcLink`.


| **Region** | **Account ID** | 
| --- | --- | 
| us-east-1 | 392220576650 | 
| us-east-2 | 718770453195 | 
| us-west-1 | 968246515281 | 
| us-west-2 | 109351309407 | 
| ca-central-1 | 796887884028 | 
| eu-west-1 | 631144002099 | 
| eu-west-2 | 544388816663 | 
| eu-west-3 | 061510835048 | 
| eu-central-1 | 474240146802 | 
| eu-central-2 | 166639821150 | 
| eu-north-1 | 394634713161 | 
| eu-south-1 | 753362059629 | 
| eu-south-2 | 359345898052 | 
| ap-northeast-1 | 969236854626 | 
| ap-northeast-2 | 020402002396 | 
| ap-northeast-3 | 360671645888 | 
| ap-southeast-1 | 195145609632 | 
| ap-southeast-2 | 798376113853 | 
| ap-southeast-3 | 652364314486 | 
| ap-southeast-4 | 849137399833 | 
| ap-south-1 | 507069717855 | 
| ap-south-2 | 644042651268 | 
| ap-east-1 | 174803364771 | 
| sa-east-1 | 287228555773 | 
| me-south-1 | 855739686837 | 
| me-central-1 | 614065512851 | 

# Mock integrations for REST APIs in API Gateway
<a name="how-to-mock-integration"></a>

Amazon API Gateway supports mock integrations for API methods. This feature enables API developers to generate API responses from API Gateway directly, without the need for an integration backend. As an API developer, you can use this feature to unblock dependent teams that need to work with an API before the project development is complete. You can also use this feature to provision a landing page for your API, which can provide an overview of and navigation to your API. For an example of such a landing page, see the integration request and response of the GET method on the root resource of the example API discussed in [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md).

As an API developer, you decide how API Gateway responds to a mock integration request. For this, you configure the method's integration request and integration response to associate a response with a given status code. For a method with the mock integration to return a `200` response, configure the integration request body mapping template to return the following.

```
{"statusCode": 200}
```

Configure a `200` integration response to have the following body mapping template, for example:

```
{
    "statusCode": 200,
    "message": "Go ahead without me."
}
```

 Similarly, for the method to return, for example, a `500` error response, set up the integration request body mapping template to return the following.

```
{"statusCode": 500}
```

Set up a `500` integration response with, for example, the following mapping template: 

```
{
    "statusCode": 500,
    "message": "The invoked method is not supported on the API resource."
}
```

Alternatively, you can have a method of the mock integration return the default integration response without defining the integration request mapping template. The default integration response is the one with an undefined **HTTP status regex**. Make sure appropriate passthrough behaviors are set.

**Note**  
Mock integrations aren't intended to support large response templates. If you need them for your use case, you should consider using a Lambda integration instead.

Using an integration request mapping template, you can inject application logic to decide which mock integration response to return based on certain conditions. For example, you could use a `scope` query parameter on the incoming request to determine whether to return a successful response or an error response:

```
{
  #if( $input.params('scope') == "internal" )
    "statusCode": 200
  #else
    "statusCode": 500
  #end
}
```

This way, the method of the mock integration lets internal calls to go through while rejecting other types of calls with an error response. 



In this section, we describe how to use the API Gateway console to enable the mock integration for an API method.

**Topics**
+ [Enable mock integration using the API Gateway console](how-to-mock-integration-console.md)

# Enable mock integration using the API Gateway console
<a name="how-to-mock-integration-console"></a>

You must have a method available in API Gateway. Follow the instructions in [Tutorial: Create a REST API with an HTTP non-proxy integration](api-gateway-create-api-step-by-step.md).

1. Choose an API resource and choose **Create method**.

   To create the method, do the following:

   1. For **Method type**, select a method. 

   1. For **Integration type**, select **Mock**.

   1. Choose **Create method**. 

   1. On the **Method request** tab, for **Method request settings**, choose **Edit**.

   1. Choose **URL query string parameters**. Choose **Add query string** and for **Name**, enter **scope**. This query parameter determines if the caller is internal or otherwise.

   1. Choose **Save**.

1. On the **Method response** tab, choose **Create response**, and then do the following:

   1. For **HTTP Status**, enter **500**.

   1. Choose **Save**.

1. On the **Integration request** tab, for **Integration request settings**, choose **Edit**.

1. Choose **Mapping templates**, and then do the following:

   1. Choose **Add mapping template**.

   1. For **Content type**, enter **application/json**. 

   1. For **Template body**, enter the following:

      ```
      {
        #if( $input.params('scope') == "internal" )
          "statusCode": 200
        #else
          "statusCode": 500
        #end
      }
      ```

   1. Choose **Save**.

1. On the **Integration response** tab, for the **Default - Response** choose **Edit**.

1. Choose **Mapping templates**, and then do the following:

   1. For **Content type**, enter **application/json**. 

   1. For **Template body**, enter the following:

      ```
      {
          "statusCode": 200,
          "message": "Go ahead without me"
      }
      ```

   1. Choose **Save**.

1. Choose **Create response**.

   To create a 500 response, do the following:

   1. For **HTTP status regex**, enter **5\$1d\$12\$1**. 

   1. For **Method response status**, select **500**.

   1. Choose **Save**.

   1. For **5\$1d\$12\$1 - Response**, choose **Edit**. 

   1. Choose **Mapping templates**, and then choose **Add mapping template**.

   1. For **Content type**, enter **application/json**. 

   1. For **Template body**, enter the following:

      ```
      {
          "statusCode": 500,
          "message": "The invoked method is not supported on the API resource."
      }
      ```

   1. Choose **Save**.

1.  Choose the **Test** tab. You might need to choose the right arrow button to show the tab. To test your mock integration, do the following:

   1. Enter `scope=internal` under **Query strings**. Choose **Test**. The test result shows:

      ```
      Request: /?scope=internal
      Status: 200
      Latency: 26 ms
      Response Body
      
      {
        "statusCode": 200,
        "message": "Go ahead without me"
      }
      
      Response Headers
      
      {"Content-Type":"application/json"}
      ```

   1. Enter `scope=public` under `Query strings` or leave it blank. Choose **Test**. The test result shows:

      ```
      Request: /
      Status: 500
      Latency: 16 ms
      Response Body
      
      {
        "statusCode": 500,
        "message": "The invoked method is not supported on the API resource."
      }
      
      Response Headers
      
      {"Content-Type":"application/json"}
      ```

You can also return headers in a mock integration response by first adding a header to the method response and then setting up a header mapping in the integration response. In fact, this is how the API Gateway console enables CORS support by returning CORS required headers.

# Request validation for REST APIs in API Gateway
<a name="api-gateway-method-request-validation"></a>

 You can configure API Gateway to perform basic validation of an API request before proceeding with the integration request. When the validation fails, API Gateway immediately fails the request, returns a 400 error response to the caller, and publishes the validation results in CloudWatch Logs. This reduces unnecessary calls to the backend. More importantly, it lets you focus on the validation efforts specific to your application. You can validate a request body by verifying that required request parameters are valid and non-null or by specifying a model schema for more complicated data validation.

**Topics**
+ [Overview of basic request validation in API Gateway](#api-gateway-request-validation-basic-definitions)
+ [Data models for REST APIs](models-mappings-models.md)
+ [Set up basic request validation in API Gateway](api-gateway-request-validation-set-up.md)
+ [AWS CloudFormation template of a sample API with basic request validation](api-gateway-request-validation-sample-cloudformation.md)

## Overview of basic request validation in API Gateway
<a name="api-gateway-request-validation-basic-definitions"></a>

 API Gateway can perform the basic request validation, so that you can focus on app-specific validation in the backend. For validation, API Gateway verifies either or both of the following conditions: 
+ The required request parameters in the URI, query string, and headers of an incoming request are included and not blank. API Gateway only checks the existence of a parameter and doesn't check the type or format.
+  The applicable request payload adheres to the configured [JSON schema](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04) request of the method for a given content type. If no matching content type is found, request validation is not performed. To use the same model regardless of the content type, set the content type for your data model to `$default`.

To turn on validation, you specify validation rules in a [request validator](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html), add the validator to the API's [map of request validators](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html), and assign the validator to individual API methods. 

**Note**  
Request body validation and [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md) are two separate topics. When a request payload does not have a matching model schema, you can choose to passthrough or block the original payload. For more information, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md).

# Data models for REST APIs
<a name="models-mappings-models"></a>

In API Gateway, a model defines the data structure of a payload. In API Gateway, models are defined using the [JSON schema draft 4](https://tools.ietf.org/html/draft-zyp-json-schema-04). The following JSON object is sample data in the Pet Store example.

```
{
    "id": 1,
    "type": "dog",
    "price": 249.99
}
```

The data contains the `id`, `type`, and `price` of the pet. A model of this data allows you to:
+ Use basic request validation.
+ Create mapping templates for data transformation.
+ Create a user-defined data type (UDT) when you generate an SDK.

![\[Example JSON data model for PetStore API.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/how-to-validate-requests.png)


In this model:

1. The `$schema` object represents a valid JSON Schema version identifier. This schema is the JSON Schema draft v4.

1. The `title` object is a human-readable identifier for the model. This title is `PetStoreModel`.

1.  The `required` validation keyword requires `type`, and `price` for basic request validation.

1. The `properties` of the model are `id`, `type`, and `price`. Each object has properties that are described in the model.

1. The object `type` can have only the values `dog`, `cat`, or `fish`.

1. The object `price` is a number and is constrained with a `minimum` of 25 and a `maximum` of 500.

## PetStore model
<a name="PetStore-model-text"></a>

```
1 {
2 "$schema": "http://json-schema.org/draft-04/schema#",
3  "title": "PetStoreModel",
4  "type" : "object",
5  "required" : [ "price", "type" ],
6  "properties" : {
7    "id" : {
8      "type" : "integer"
9    },
10    "type" : {
11      "type" : "string",
12      "enum" : [ "dog", "cat", "fish" ]
13    },
14    "price" : {
15      "type" : "number",
16      "minimum" : 25.0,
17      "maximum" : 500.0
18    }
19  }
20 }
```

In this model:

1. On line 2, the `$schema` object represents a valid JSON Schema version identifier. This schema is the JSON Schema draft v4.

1. On line 3, the `title` object is a human-readable identifier for the model. This title is `PetStoreModel`.

1.  On line 5, the `required` validation keyword requires `type`, and `price` for basic request validation.

1.  On lines 6 -- 17, the `properties` of the model are `id`, `type`, and `price`. Each object has properties that are described in the model.

1. On line 12, the object `type` can have only the values `dog`, `cat`, or `fish`.

1. On lines 14 -- 17, the object `price` is a number and is constrained with a `minimum` of 25 and a `maximum` of 500.

## Creating more complex models
<a name="api-gateway-request-validation-model-more-complex"></a>

 You can use the `$ref` primitive to create reusable definitions for longer models. For example, you can create a definition called `Price` in the `definitions` section describing the `price` object. The value of `$ref` is the `Price` definition. 

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStoreModelReUsableRef",
  "required" : ["price", "type" ],
  "type" : "object",
  "properties" : {
    "id" : {
      "type" : "integer"
    },
    "type" : {
      "type" : "string",
      "enum" : [ "dog", "cat", "fish" ]
    },
    "price" : {
        "$ref": "#/definitions/Price"
    }
  },
  "definitions" : {
      "Price": {
        "type" : "number",
        "minimum" : 25.0,
        "maximum" : 500.0
            }
      }
}
```

You can also reference another model schema defined in an external model file. Set the value of the `$ref` property to the location of the model. In the following example, the `Price` model is defined in the `PetStorePrice` model in API `a1234`.

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStorePrice",
  "type": "number",
  "minimum": 25,
  "maximum": 500
}
```

The longer model can reference the `PetStorePrice` model.

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "PetStoreModelReusableRefAPI",
  "required" : [ "price", "type" ],
  "type" : "object",
  "properties" : {
    "id" : {
      "type" : "integer"
    },
    "type" : {
      "type" : "string",
      "enum" : [ "dog", "cat", "fish" ]
    },
    "price" : {
        "$ref": "https://apigateway.amazonaws.com/restapis/a1234/models/PetStorePrice"
    }
  }
}
```

## Using output data models
<a name="api-gateway-request-validation-output-model"></a>

If you transform your data, you can define a payload model in the integration response. A payload model can be used when you generate an SDK. For strongly typed languages, such as Java, Objective-C, or Swift, the object corresponds to a user-defined data type (UDT). API Gateway creates a UDT if you provide it with a data model when you generate an SDK. For more information about data transformations, see [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).

The following example is output data from an integration response.

```
{
[
  {
    "description" : "Item 1 is a dog.",
    "askingPrice" : 249.99
  },
  {
    "description" : "Item 2 is a cat.",
    "askingPrice" : 124.99
  },
  {
    "description" : "Item 3 is a fish.",
    "askingPrice" : 0.99
  }
]
}
```

The following example is a payload model that describes the output data.

```
{
"$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PetStoreOutputModel",
  "type" : "object",
  "required" : [ "description", "askingPrice" ],
  "properties" : {
    "description" : {
      "type" : "string"
    },
    "askingPrice" : {
      "type" : "number",
      "minimum" : 25.0,
      "maximum" : 500.0
    }
  }
}
```

With this model, you can call an SDK to retrieve the `description` and `askingPrice` property values by reading the `PetStoreOutputModel[i].description` and `PetStoreOutputModel[i].askingPrice` properties. If no model is provided, API Gateway uses the empty model to create a default UDT. 

## Next steps
<a name="api-gateway-request-validation-model-next-steps"></a>
+ This section provides resources that you can use to gain more knowledge about the concepts presented in this topic.

  You can follow the request validation tutorials:
  + [Set up request validation using the API Gateway console](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-in-console)
  +  [Set up basic request validation using the AWS CLI](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-cli)
  +  [Set up basic request validation using an OpenAPI definition](api-gateway-request-validation-set-up.md#api-gateway-request-validation-setup-importing-swagger)
+  For more information about data transformation and mapping templates, [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).

# Set up basic request validation in API Gateway
<a name="api-gateway-request-validation-set-up"></a>

 This section shows how to set up request validation for API Gateway using the console, AWS CLI, and an OpenAPI definition.

**Topics**
+ [Set up request validation using the API Gateway console](#api-gateway-request-validation-setup-in-console)
+ [Set up basic request validation using the AWS CLI](#api-gateway-request-validation-setup-cli)
+ [Set up basic request validation using an OpenAPI definition](#api-gateway-request-validation-setup-importing-swagger)

## Set up request validation using the API Gateway console
<a name="api-gateway-request-validation-setup-in-console"></a>

 You can use the API Gateway console to validate a request by selecting one of three validators for an API request: 
+ **Validate body**.
+ **Validate query string parameters and headers**.
+ **Validate body, query string parameters, and headers**.

 When you apply one of the validators on an API method, the API Gateway console adds the validator to the API's [RequestValidators](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html) map.

To follow this tutorial, you'll use an CloudFormation template to create an incomplete API Gateway API. This API has a `/validator` resource with `GET` and `POST` methods. Both methods are integrated with the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. You will configure two kinds of request validation:
+ In the `GET` method, you will configure request validation for URL query string parameters.
+ In the `POST` method, you will configure request validation for the request body.

 This will allow only certain API calls to pass through to the API. 

Download and unzip [the app creation template for CloudFormation](samples/request-validation-tutorial-console.zip). You'll use this template to create an incomplete API. You will finish the rest of the steps in the API Gateway console. 

**To create an CloudFormation stack**

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Choose **Create stack** and then choose **With new resources (standard)**.

1. For **Specify template**, choose **Upload a template file**.

1. Select the template that you downloaded.

1. Choose **Next**. 

1. For **Stack name**, enter **request-validation-tutorial-console** and then choose **Next**.

1. For **Configure stack options**, choose **Next**.

1. For **Capabilities**, acknowledge that CloudFormation can create IAM resources in your account.

1. Choose **Next**, and then choose **Submit**.

CloudFormation provisions the resources specified in the template. It can take a few minutes to finish provisioning your resources. When the status of your CloudFormation stack is **CREATE\$1COMPLETE**, you're ready to move on to the next step.

**To select your newly created API**

1. Select the newly created **request-validation-tutorial-console** stack.

1. Choose **Resources**.

1. Under **Physical ID**, choose your API. This link will direct you to the API Gateway console.

Before you modify the `GET` and `POST` methods, you must create a model.

**To create a model**

1. A model is required to use request validation on the body of an incoming request. To create a model, in the main navigation pane, choose **Models**.

1. Choose **Create model**.

1. For **Name**, enter **PetStoreModel**.

1. For **Content Type**, enter **application/json**. If no matching content type is found, request validation is not performed. To use the same model regardless of the content type, enter **\$1default**.

1. For **Description**, enter **My PetStore Model** as the model description.

1. For **Model schema**, paste the following model into the code editor, and choose **Create**. 

   ```
   {
     "type" : "object",
     "required" : [ "name", "price", "type" ],
     "properties" : {
       "id" : {
         "type" : "integer"
       },
       "type" : {
         "type" : "string",
         "enum" : [ "dog", "cat", "fish" ]
       },
       "name" : {
         "type" : "string"
       },
       "price" : {
         "type" : "number",
         "minimum" : 25.0,
         "maximum" : 500.0
       }
     }
   }
   ```

For more information about the model, see [Data models for REST APIs](models-mappings-models.md). 

**To configure request validation for a `GET` method**

1. In the main navigation pane, choose **Resources**, and then select the **GET** method. 

1. On the **Method request** tab, under **Method request settings**, choose **Edit**.

1. For **Request validator**, select **Validate query string parameters and headers**.

1. Under **URL query string parameters**, do the following: 

   1. Choose **Add query string**.

   1. For **Name**, enter **petType**.

   1. Turn on **Required**.

   1. Keep **Caching** turned off. 

1. Choose **Save**.

1. On the **Integration request** tab, under **Integration request settings**, choose **Edit**.

1. Under **URL query string parameters**, do the following: 

   1. Choose **Add query string**.

   1. For **Name**, enter **petType**.

   1. For **Mapped from**, enter **method.request.querystring.petType**. This maps the **petType** to the pet's type.

      For more information about data mapping, see [ the data mapping tutorial](set-up-data-transformations-in-api-gateway.md#mapping-example-console).

   1. Keep **Caching** turned off. 

1. Choose **Save**.

**To test request validation for the `GET` method**

1. Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. For **Query strings**, enter **petType=dog**, and then choose **Test**.

1. The method test will return `200 OK` and a list of dogs.

   For information about how to transform this output data, see the [data mapping tutorial.](set-up-data-transformations-in-api-gateway.md#mapping-example-console)

1. Remove **petType=dog** and choose **Test**. 

1.  The method test will return a `400` error with the following error message: 

   ```
   {
     "message": "Missing required request parameters: [petType]"
   }
   ```

**To configure request validation for the `POST` method**

1. In the main navigation pane, choose **Resources**, and then select the **POST** method. 

1. On the **Method request** tab, under **Method request settings**, choose **Edit**.

1. For **Request validator**, select **Validate body**.

1. Under **Request body**, choose **Add model**.

1. For **Content type**, enter **application/json**. If no matching content type is found, request validation is not performed. To use the same model regardless of the content type, enter `$default`.

    For **Model**, select **PetStoreModel**.

1. Choose **Save**.

**To test request validation for a `POST` method**

1. Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. For **Request body** paste the following into the code editor:

   ```
   {
     "id": 2,
     "name": "Bella",
     "type": "dog",
     "price": 400
   }
   ```

    Choose **Test**.

1. The method test will return `200 OK` and a success message. 

1. For **Request body** paste the following into the code editor:

   ```
   {
     "id": 2,
     "name": "Bella",
     "type": "dog",
     "price": 4000
   }
   ```

    Choose **Test**. 

1.  The method test will return a `400` error with the following error message:

   ```
   {
    "message": "Invalid request body"
   }
   ```

    At the bottom of the test logs, the reason for the invalid request body is returned. In this case, the price of the pet was outside the maximum specified in the model. 

**To delete an CloudFormation stack**

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Select your CloudFormation stack.

1. Choose **Delete** and then confirm your choice.

### Next steps
<a name="next-steps-request-validation-tutorial"></a>
+ For information about how to transform output data and perform more data mapping, see the [data mapping tutorial](set-up-data-transformations-in-api-gateway.md#mapping-example-console).
+ Follow the [ Set up basic request validation using the AWS CLI](#api-gateway-request-validation-setup-cli) tutorial, to do similar steps using the AWS CLI. 

## Set up basic request validation using the AWS CLI
<a name="api-gateway-request-validation-setup-cli"></a>

You can create a validator to set up request validation using the AWS CLI. To follow this tutorial, you'll use an CloudFormation template to create an incomplete API Gateway API. 

**Note**  
This is not the same CloudFormation template as the console tutorial.

 Using a pre-exposed `/validator`resource, you will create `GET` and `POST` methods. Both methods will be integrated with the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. You will configure the following two request validations:
+ On the `GET` method, you will create a `params-only` validator to validate URL query string parameters.
+ On the `POST` method, you will create a `body-only` validator to validate the request body.

 This will allow only certain API calls to pass through to the API. 

**To create an CloudFormation stack**

Download and unzip [the app creation template for CloudFormation](samples/request-validation-tutorial-cli.zip). 

To complete the following tutorial, you need the [AWS Command Line Interface (AWS CLI) version 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). 

For long commands, an escape character (`\`) is used to split a command over multiple lines.
**Note**  
In Windows, some Bash CLI commands that you commonly use (such as `zip`) are not supported by the operating system's built-in terminals. To get a Windows-integrated version of Ubuntu and Bash, [install the Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install). Example CLI commands in this guide use Linux formatting. Commands which include inline JSON documents must be reformatted if you are using the Windows CLI. 

1.  Use the following command to create the CloudFormation stack.

   ```
   aws cloudformation create-stack --stack-name request-validation-tutorial-cli --template-body file://request-validation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation provisions the resources specified in the template. It can take a few minutes to finish provisioning your resources. Use the following command to see the status of your CloudFormation stack.

   ```
   aws cloudformation describe-stacks --stack-name request-validation-tutorial-cli
   ```

1. When the status of your CloudFormation stack is `StackStatus: "CREATE_COMPLETE"`, use the following command to retrieve relevant output values for future steps.

   ```
    aws cloudformation describe-stacks --stack-name request-validation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   The output values are the following:
   + ApiId, which is the ID for the API. For this tutorial, the API ID is `abc123`.
   + ResourceId, which is the ID for the validator resource where the `GET` and `POST` methods are exposed. For this tutorial, the Resource ID is `efg456`

**To create the request validators and import a model**

1. A validator is required to use request validation with the AWS CLI. Use the following command to create a validator that validates only request parameters. 

   ```
   aws apigateway create-request-validator --rest-api-id abc123 \
         --no-validate-request-body \
         --validate-request-parameters \
         --name params-only
   ```

   Note the ID of the `params-only` validator.

1.  Use the following command to create a validator that validates only the request body. 

   ```
   aws apigateway create-request-validator --rest-api-id abc123 \
         --validate-request-body \
         --no-validate-request-parameters \
         --name body-only
   ```

   Note the ID of the `body-only` validator.

1.  A model is required to use request validation on the body of an incoming request. Use the following command to import a model.

   ```
   aws apigateway create-model --rest-api-id abc123 --name PetStoreModel --description 'My PetStore Model' --content-type 'application/json' --schema '{"type": "object", "required" : [ "name", "price", "type" ], "properties" : { "id" : {"type" : "integer"},"type" : {"type" : "string", "enum" : [ "dog", "cat", "fish" ]},"name" : { "type" : "string"},"price" : {"type" : "number","minimum" : 25.0, "maximum" : 500.0}}}}' 
   ```

   If no matching content type is found, request validation is not performed. To use the same model regardless of the content type, specify `$default` as the key.

**To create the `GET` and `POST` methods**

1. Use the following command to add the `GET` HTTP method on the `/validate` resource. This command creates the `GET`method, adds the `params-only` validator, and sets the query string `petType` as required. 

   ```
   aws apigateway put-method --rest-api-id abc123 \
          --resource-id efg456 \
          --http-method GET \
          --authorization-type "NONE" \
          --request-validator-id aaa111 \
          --request-parameters "method.request.querystring.petType=true"
   ```

   Use the following command to add the `POST` HTTP method on the `/validate` resource. This command creates the `POST`method, adds the `body-only` validator, and attaches the model to the body-only validator. 

   ```
   aws apigateway put-method --rest-api-id abc123 \
          --resource-id efg456 \
          --http-method POST \
          --authorization-type "NONE" \
          --request-validator-id bbb222 \
          --request-models 'application/json'=PetStoreModel
   ```

1.  Use the following command to set up the `200 OK` response of the `GET /validate` method. 

   ```
   aws apigateway put-method-response --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method GET \
               --status-code 200
   ```

    Use the following command to set up the `200 OK` response of the `POST /validate` method.

   ```
   aws apigateway put-method-response --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method POST \
               --status-code 200
   ```

1.  Use the following command to set up an `Integration` with a specified HTTP endpoint for the `GET /validation` method. 

   ```
   aws apigateway put-integration --rest-api-id abc123  \
               --resource-id efg456 \
               --http-method GET \
               --type HTTP \
               --integration-http-method GET \
               --request-parameters '{"integration.request.querystring.type" : "method.request.querystring.petType"}' \
               --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets'
   ```

    Use the following command to set up an `Integration` with a specified HTTP endpoint for the `POST /validation` method. 

   ```
   aws apigateway put-integration --rest-api-id abc123  \
                 --resource-id efg456 \
                 --http-method POST \
                 --type HTTP \
                 --integration-http-method GET \
                 --uri 'http://petstore-demo-endpoint.execute-api.com/petstore/pets'
   ```

1.  Use the following command to set up an integration response for the `GET /validation` method. 

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
                 --resource-id efg456\
                 --http-method GET \
                 --status-code 200 \
                 --selection-pattern ""
   ```

    Use the following command to set up an integration response for the `POST /validation` method.

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method POST \
               --status-code 200 \
               --selection-pattern ""
   ```

**To test the API**

1. To test the `GET` method, which will perform request validation for the query strings, use the following command:

   ```
   aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method GET \
               --path-with-query-string '/validate?petType=dog'
   ```

   The result will return a `200 OK` and list of dogs.

1. Use the following command to test without including the query string `petType`

   ```
   aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method GET
   ```

   The result will return a `400` error.

1. To test the `POST` method, which will perform request validation for the request body, use the following command:

   ```
    aws apigateway test-invoke-method --rest-api-id abc123 \
               --resource-id efg456 \
               --http-method POST \
               --body '{"id": 1, "name": "bella", "type": "dog", "price" : 400 }'
   ```

   The result will return a `200 OK` and a success message. 

1. Use the following command to test using an invalid body.

   ```
    aws apigateway test-invoke-method --rest-api-id abc123 \
                 --resource-id efg456 \
                 --http-method POST \
                 --body '{"id": 1, "name": "bella", "type": "dog", "price" : 1000 }'
   ```

   The result will return a `400` error, as the price of the dog is over the maximum price defined by the model.

**To delete an CloudFormation stack**
+ Use the following command to delete your CloudFormation resources.

  ```
  aws cloudformation delete-stack  --stack-name request-validation-tutorial-cli
  ```

## Set up basic request validation using an OpenAPI definition
<a name="api-gateway-request-validation-setup-importing-swagger"></a>

 You can declare a request validator at the API level by specifying a set of the [x-amazon-apigateway-request-validators.requestValidator object](api-gateway-swagger-extensions-request-validators.requestValidator.md) objects in the [x-amazon-apigateway-request-validators object](api-gateway-swagger-extensions-request-validators.md) map to select what part of the request will be validated. In the example OpenAPI definition, there are two validators: 
+ `all` validator which validates both the body, using the `RequestBodyModel` data model, and the parameters.

  The `RequestBodyModel` data model requires that the input JSON object contains the `name`, `type`, and `price` properties. The `name` property can be any string, `type` must be one of the specified enumeration fields (`["dog", "cat", "fish"]`), and `price` must range between 25 and 500. The `id` parameter is not required. 
+ `param-only` which validates only the parameters.

 To turn a request validator on all methods of an API, specify an [x-amazon-apigateway-request-validator property](api-gateway-swagger-extensions-request-validator.md) property at the API level of the OpenAPI definition. In the example OpenAPI definition, the `all` validator is used on all API methods, unless otherwise overridden. When using a model to validate the body, if no matching content type is found, request validation is not performed. To use the same model regardless of the content type, specify `$default` as the key.

To turn on a request validator on an individual method, specify the `x-amazon-apigateway-request-validator` property at the method level. In the example, OpenAPI definition, the `param-only` validator overwrites the `all` validator on the `GET` method.



To import the OpenAPI example into API Gateway, see the following instructions to [Import a Regional API into API Gateway](import-export-api-endpoints.md) or to [Import an edge-optimized API into API Gateway](import-edge-optimized-api.md).

------
#### [ OpenAPI 3.0 ]

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "ReqValidators Sample",
    "version" : "1.0.0"
  },
  "servers" : [ {
    "url" : "/{basePath}",
    "variables" : {
      "basePath" : {
        "default" : "/v1"
      }
    }
  } ],
  "paths" : {
    "/validation" : {
      "get" : {
        "parameters" : [ {
          "name" : "q1",
          "in" : "query",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "test-method-response-header" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ArrayOfError"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "params-only",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.type" : "method.request.querystring.q1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      },
      "post" : {
        "parameters" : [ {
          "name" : "h1",
          "in" : "header",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/RequestBodyModel"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "test-method-response-header" : {
                "schema" : {
                  "type" : "string"
                }
              }
            },
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ArrayOfError"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "all",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "POST",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.custom_h1" : "method.request.header.h1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "RequestBodyModel" : {
        "required" : [ "name", "price", "type" ],
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer"
          },
          "type" : {
            "type" : "string",
            "enum" : [ "dog", "cat", "fish" ]
          },
          "name" : {
            "type" : "string"
          },
          "price" : {
            "maximum" : 500.0,
            "minimum" : 25.0,
            "type" : "number"
          }
        }
      },
      "ArrayOfError" : {
        "type" : "array",
        "items" : {
          "$ref" : "#/components/schemas/Error"
        }
      },
      "Error" : {
        "type" : "object"
      }
    }
  },
  "x-amazon-apigateway-request-validators" : {
    "all" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : true
    },
    "params-only" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : false
    }
  }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger" : "2.0",
  "info" : {
    "version" : "1.0.0",
    "title" : "ReqValidators Sample"
  },
  "basePath" : "/v1",
  "schemes" : [ "https" ],
  "paths" : {
    "/validation" : {
      "get" : {
        "produces" : [ "application/json", "application/xml" ],
        "parameters" : [ {
          "name" : "q1",
          "in" : "query",
          "required" : true,
          "type" : "string"
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "schema" : {
              "$ref" : "#/definitions/ArrayOfError"
            },
            "headers" : {
              "test-method-response-header" : {
                "type" : "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "params-only",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.type" : "method.request.querystring.q1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      },
      "post" : {
        "consumes" : [ "application/json" ],
        "produces" : [ "application/json", "application/xml" ],
        "parameters" : [ {
          "name" : "h1",
          "in" : "header",
          "required" : true,
          "type" : "string"
        }, {
          "in" : "body",
          "name" : "RequestBodyModel",
          "required" : true,
          "schema" : {
            "$ref" : "#/definitions/RequestBodyModel"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "schema" : {
              "$ref" : "#/definitions/ArrayOfError"
            },
            "headers" : {
              "test-method-response-header" : {
                "type" : "string"
              }
            }
          }
        },
        "x-amazon-apigateway-request-validator" : "all",
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "POST",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "400",
              "responseParameters" : {
                "method.response.header.test-method-response-header" : "'static value'"
              },
              "responseTemplates" : {
                "application/xml" : "xml 400 response template",
                "application/json" : "json 400 response template"
              }
            },
            "2\\d{2}" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.custom_h1" : "method.request.header.h1"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "definitions" : {
    "RequestBodyModel" : {
      "type" : "object",
      "required" : [ "name", "price", "type" ],
      "properties" : {
        "id" : {
          "type" : "integer"
        },
        "type" : {
          "type" : "string",
          "enum" : [ "dog", "cat", "fish" ]
        },
        "name" : {
          "type" : "string"
        },
        "price" : {
          "type" : "number",
          "minimum" : 25.0,
          "maximum" : 500.0
        }
      }
    },
    "ArrayOfError" : {
      "type" : "array",
      "items" : {
        "$ref" : "#/definitions/Error"
      }
    },
    "Error" : {
      "type" : "object"
    }
  },
  "x-amazon-apigateway-request-validators" : {
    "all" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : true
    },
    "params-only" : {
      "validateRequestParameters" : true,
      "validateRequestBody" : false
    }
  }
}
```

------

# AWS CloudFormation template of a sample API with basic request validation
<a name="api-gateway-request-validation-sample-cloudformation"></a>

 The following CloudFormation example template definition defines a sample API with request validation enabled. The API is a subset of the [PetStore API](http://petstore-demo-endpoint.execute-api.com/petstore/pets). It exposes a `POST` method to add a pet to the `pets` collection and a `GET` method to query pets by a specified type. 

 There are two request validators declared:

**`GETValidator`**  
This validator is enabled on the `GET` method. It allows API Gateway to verify that the required query parameter (`q1`) is included and not blank in the incoming request. 

**`POSTValidator`**  
This validator is enabled on the `POST` method. It allows API Gateway to verify that payload request format adheres to the specified `RequestBodyModel` when the content type is `application/json` if no matching content type is found, request validation is not performed. To use the same model regardless of the content type, specify `$default`. `RequestBodyModel` contains an additional model, `RequestBodyModelId`, to define the pet ID.

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: ReqValidatorsSample
  RequestBodyModelId:
    Type: 'AWS::ApiGateway::Model'
    Properties:
      RestApiId: !Ref Api
      ContentType: application/json
      Description: Request body model for Pet ID.
      Schema:
        $schema: 'http://json-schema.org/draft-04/schema#'
        title: RequestBodyModelId
        properties:
            id:
              type: integer
  RequestBodyModel: 
    Type: 'AWS::ApiGateway::Model'
    Properties:
      RestApiId: !Ref Api
      ContentType: application/json
      Description: Request body model for Pet type, name, price, and ID.
      Schema:
        $schema: 'http://json-schema.org/draft-04/schema#'
        title: RequestBodyModel
        required:
          - price
          - name
          - type
        type: object
        properties:
            id:
              "$ref": !Sub 
                - 'https://apigateway.amazonaws.com/restapis/${Api}/models/${RequestBodyModelId}'
                - Api: !Ref Api
                  RequestBodyModelId: !Ref RequestBodyModelId
            price: 
              type: number
              minimum: 25
              maximum: 500
            name:
              type: string
            type:
              type: string
              enum:
                - "dog"
                - "cat"
                - "fish"
  GETValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: params-only
      RestApiId: !Ref Api
      ValidateRequestBody: False
      ValidateRequestParameters: True 
  POSTValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: body-only
      RestApiId: !Ref Api
      ValidateRequestBody: True
      ValidateRequestParameters: False
  ValidationResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'validation'
  ValidationMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref ValidationResource
      HttpMethod: GET
      AuthorizationType: NONE
      RequestValidatorId: !Ref GETValidator
      RequestParameters:
        method.request.querystring.q1: true
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ValidationMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref ValidationResource
      HttpMethod: POST
      AuthorizationType: NONE
      RequestValidatorId: !Ref POSTValidator
      RequestModels:
        application/json : !Ref RequestBodyModel 
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: POST
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - ValidationMethodGet
      - RequestBodyModel 
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiRootUrl:
    Description: Root Url of the API
    Value: !Sub 'https://${Api}.execute-api.${AWS::Region}.amazonaws.com/${StageName}'
```

# Data transformations for REST APIs in API Gateway
<a name="rest-api-data-transformations"></a>

**Note**  
This section explains features that you use with a non-proxy integration. However, we recommend that when possible, you use a proxy integration for your REST API. A proxy integration has a streamlined integration setup and can evolve with the backend without having to tear down the existing setup. For more information, see [Choose an API Gateway API integration type](api-gateway-api-integration-types.md).

If you use a non-proxy integration, you can use two features of API Gateway to transform your method request and your integration response. You might transform your method request if it takes a different payload format than the integration request payload. You might transform your integration response if it returns a different payload format than the format you need to return in the method response. For more information about the request lifecycle, see [Example resource for a REST API](rest-api-develop.md#rest-api-develop-example).

The following example shows a data transformation where for the header `"x-version:beta"`, the `x-version` header parameter is transformed into the `app-version` header parameter. The data transformation from `x-version` to `app-version` occurs in the integration request. That way, the integration endpoint receives the transformed header parameter value. When the integration endpoint returns a status code, the status code is transformed from `200` to `204` before the method response.

![\[Diagram of API Gateway data transformation\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/develop-non-proxy.png)


To create a data transformation, you can use the following features:

**Parameter mapping**  
In parameter mapping, you can modify integration request URL path parameters, URL query string parameters, or HTTP header values, but you can't modify the integration request payload. You can also modify HTTP response header values. Use parameter mapping to create static header values for cross origin resource sharing (CORS).   
You can use parameter mapping in your integration request for proxy and non-proxy integrations, but to use parameter mapping for an integration response, you need a non-proxy integration. Parameter mapping doesn't require any scripting in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html). For more information, see [Parameter mapping for REST APIs in API Gateway](rest-api-parameter-mapping.md).

**Mapping template transformations**  
In mapping template transformations, you use a mapping template to map URL path parameters, URL query string parameters, HTTP headers, and the integration request or integration response body. A *mapping template* is a script expressed in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) using [JSONPath expressions](https://goessner.net/articles/JsonPath/) and applied to the payload based on the `Content-type` header.  
With a mapping template, you can do the following:  
+ Select which data to send using integration with AWS services, such as Amazon DynamoDB or Lambda functions, or HTTP endpoints. For more information, see [Tutorial: Modify the integration request and response for integrations to AWS services](set-up-data-transformations-in-api-gateway.md).
+ Conditionally override an API's integration request and integration response parameters, create new header values, and override status codes. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).
You can also specify the behavior of your API when an integration request body has `Content-type` header with no matching mapping templates. This is called integration passthrough behavior. For more information, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md). 

## Choose between parameter mapping and mapping template transformations
<a name="rest-api-data-transformations-choose"></a>

We recommend that you use parameter mapping to transform your data when possible. If your API requires you to change the body, or requires you to perform conditional overrides and modifications based on the incoming integration request or integration response, and you can't use a proxy integration, use mapping template transformations.

# Parameter mapping for REST APIs in API Gateway
<a name="rest-api-parameter-mapping"></a>

**Note**  
If you are using an HTTP API, see [Transform API requests and responses for HTTP APIs in API Gateway](http-api-parameter-mapping.md).

In parameter mapping, you map request or response parameters. You can map parameters using parameter mapping expressions or static values. For a list of mapping expressions, see [Parameter mapping source reference for REST APIs in API Gateway](rest-api-parameter-mapping-sources.md). You can use parameter mapping in your integration request for proxy and non-proxy integrations, but to use parameter mapping for an integration response, you need a non-proxy integration.

For example, you can map the method request header parameter `puppies` to the integration request header parameter `DogsAge0`. Then, if a client sends the header `puppies:true` to your API, the integration request sends the request header `DogsAge0:true` to the integration endpoint. The following diagram shows the request lifecycle of this example.

![\[Diagram of API Gateway parameter mapping example for a request\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/parameter-mapping-example1.png)


To create this example using API Gateway, see [Example 1: Map a method request parameter to an integration request parameter](request-response-data-mappings.md#request-response-data-mappings-example-1).

 As another example, you can also map the integration response header parameter `kittens` to the method response header parameter `CatsAge0`. Then, if the integration endpoint returns `kittens:false`, the client receives the header `CatsAge0:false`. The following diagram shows the request lifecycle of this example.

![\[Diagram of API Gateway parameter mapping example for a response\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/parameter-mapping-example2.png)


**Topics**
+ [Parameter mapping examples for REST APIs in API Gateway](request-response-data-mappings.md)
+ [Parameter mapping source reference for REST APIs in API Gateway](rest-api-parameter-mapping-sources.md)

# Parameter mapping examples for REST APIs in API Gateway
<a name="request-response-data-mappings"></a>

The following examples show how to create parameter mapping expressions using the API Gateway console, OpenAPI, and CloudFormation templates. For an example of how to use parameter mapping to create the required CORS headers, see [CORS for REST APIs in API Gateway](how-to-cors.md). 

## Example 1: Map a method request parameter to an integration request parameter
<a name="request-response-data-mappings-example-1"></a>

The following example maps the method request header parameter `puppies` to the integration request header parameter `DogsAge0`. 

------
#### [ AWS Management Console ]

**To map the method request parameter**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose a method.

   Your method must have a non-proxy integration.

1. For **Method request settings**, choose **Edit**.

1. Choose **HTTP request headers**.

1. Choose **Add header**.

1. For **Name**, enter **puppies**.

1. Choose **Save**.

1. Choose the **Integration request** tab, and then for **Integration request settings**, choose **Edit**.

   The AWS Management Console automatically adds a parameter mapping from `method.request.header.puppies ` to `puppies` for you, but you need to change the **Name** to match the request header parameter that is expected by your integration endpoint.

1. For **Name**, enter **DogsAge0**.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

The following steps show you how to verify that your parameter mapping was successful.

**(Optional) Test your parameter mapping**

1. Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. For headers, enter **puppies:true**.

1. Choose **Test**.

1. In the **Logs**, the result should look like the following:

   ```
   Tue Feb 04 00:28:36 UTC 2025 : Method request headers: {puppies=true}
   Tue Feb 04 00:28:36 UTC 2025 : Method request body before transformations: 
   Tue Feb 04 00:28:36 UTC 2025 : Endpoint request URI: http://petstore-demo-endpoint.execute-api.com/petstore/pets
   Tue Feb 04 00:28:36 UTC 2025 : Endpoint request headers: {DogsAge0=true, x-amzn-apigateway-api-id=abcd1234, Accept=application/json, User-Agent=AmazonAPIGateway_aaaaaaa, X-Amzn-Trace-Id=Root=1-abcd-12344}
   ```

   The request header parameter has changed from `puppies` to `DogsAge0`.

------
#### [ CloudFormation ]

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body:
        openapi: 3.0.1
        info:
          title: ParameterMappingExample
          version: "2025-02-04T00:30:41Z"
        paths:
          /pets:
            get:
              parameters:
                - name: puppies
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.DogsAge0: method.request.header.puppies
                passthroughBehavior: when_no_match
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "ParameterMappingExample",
    "version" : "2025-02-04T00:30:41Z"
  },
  "paths" : {
    "/pets" : {
      "get" : {
        "parameters" : [ {
          "name" : "puppies",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.DogsAge0" : "method.request.header.puppies"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  }
}
```

------

## Example 2: Map multiple method request parameters to different integration request parameters
<a name="request-response-data-mappings-example-2"></a>

The following example maps the multi-value method request query string parameter `methodRequestQueryParam` to the integration request query string parameter `integrationQueryParam` and maps the method request header parameter `methodRequestHeaderParam` to the integration request path parameter `integrationPathParam`.

------
#### [ AWS Management Console ]

**To map the method request parameters**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose a method.

   Your method must have a non-proxy integration.

1. For **Method request settings**, choose **Edit**.

1. Choose **URL query string parameters**.

1. Choose **Add query string**.

1. For **Name**, enter **methodRequestQueryParam**.

1. Choose **HTTP request headers**.

1. Choose **Add header**.

1. For **Name**, enter **methodRequestHeaderParam**.

1. Choose **Save**.

1. Choose the **Integration request** tab, and then for **Integration request settings**, choose **Edit**.

1. Choose **URL path parameters**.

1. Choose **Add path parameter**.

1. For **Name**, enter **integrationPathParam**.

1. For **Mapped from**, enter **method.request.header.methodRequestHeaderParam**.

   This maps the method request header you specified in the method request to a new integration request path parameter.

1. Choose **URL query string parameters**.

1. Choose **Add query string**.

1. For **Name**, enter **integrationQueryParam**.

1. For **Mapped from**, enter **method.request.multivaluequerystring.methodRequestQueryParam**.

   This maps the multivalue query string parameter to a new single valued integration request query string parameter.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

------
#### [ CloudFormation ]

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

The following OpenAPI definition creates the following parameter mappings for an HTTP integration:
+ The method request's header, named `methodRequestHeaderParam`, into the integration request path parameter, named `integrationPathParam`
+ The multi-value method request query string, named `methodRequestQueryParam`, into the integration request query string, named `integrationQueryParam`

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: Parameter mapping example 2
          version: "2025-01-15T19:12:31Z"
        paths:
          /:
            post:
              parameters:
                - name: methodRequestQueryParam
                  in: query
                  schema:
                    type: string
                - name: methodRequestHeaderParam
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.querystring.integrationQueryParam: method.request.multivaluequerystring.methodRequestQueryParam
                  integration.request.path.integrationPathParam: method.request.header.methodRequestHeaderParam
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

The following OpenAPI definition creates the following parameter mappings for an HTTP integration:
+ The method request's header, named `methodRequestHeaderParam`, into the integration request path parameter, named `integrationPathParam`
+ The multi-value method request query string, named `methodRequestQueryParam`, into the integration request query string, named `integrationQueryParam`

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example 2",
    "version" : "2025-01-15T19:12:31Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "parameters" : [ {
          "name" : "methodRequestQueryParam",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "methodRequestHeaderParam",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.integrationQueryParam" : "method.request.multivaluequerystring.methodRequestQueryParam",
            "integration.request.path.integrationPathParam" : "method.request.header.methodRequestHeaderParam"
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000,
          "type" : "http"
        }
      }
    }
  }
}
```

------

## Example 3: Map fields from the JSON request body to integration request parameters
<a name="request-response-data-mappings-example-3"></a>

You can also map integration request parameters from fields in the JSON request body using a [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2). The following example maps the method request body to an integration request header named `body-header` and maps part of the request body, as expressed by a JSON expression to an integration request header named `pet-price`.

To test this example, provide an input that contains a price category, such as the following:

```
[ 
  { 
    "id": 1, 
    "type": "dog", 
    "price": 249.99 
  }
]
```

------
#### [ AWS Management Console ]

**To map the method request parameters**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose a `POST`, `PUT`, `PATCH`, or `ANY` method.

   Your method must have a non-proxy integration.

1. For **Integration request settings**, choose **Edit**.

1. Choose **URL request headers parameters**.

1. Choose **Add request header parameter**.

1. For **Name**, enter **body-header**.

1. For **Mapped from**, enter **method.request.body**.

   This maps the method request body to a new integration request header parameter.

1. Choose **Add request header parameter**.

1. For **Name**, enter **pet-price**.

1. For **Mapped from**, enter ** method.request.body[0].price**.

   This maps a part of the method request body to a new integration request header parameter.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

------
#### [ CloudFormation ]

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: Parameter mapping example 3
          version: "2025-01-15T19:19:14Z"
        paths:
          /:
            post:
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.pet-price: method.request.body[0].price
                  integration.request.header.body-header: method.request.body
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

The following OpenAPI definition map integration request parameters from fields in the JSON request body.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example 3",
    "version" : "2025-01-15T19:19:14Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.pet-price" : "method.request.body[0].price",
            "integration.request.header.body-header" : "method.request.body"
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000,
          "type" : "http"
        }
      }
    }
  }
}
```

------

## Example 4: Map the integration response to the method response
<a name="request-response-data-mappings-example-4"></a>

You can also map the integration response to the method response. The following example maps the integration response body to a method response header named `location`, maps the integration response header `x-app-id` to the method response header `id`, and maps the multi-valued integration response header `item` to the method response header `items`.

------
#### [ AWS Management Console ]

**To map the integration response**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose a method.

   Your method must have a non-proxy integration.

1. Choose the **Method response** tab, and then for **Response 200**, choose **Edit**.

1. For **Header name**, choose **Add header**.

1. Create three headers named **id**, **item**, and **location**.

1. Choose **Save**.

1. Choose the **Integration response** tab, and then for **Default - Response**, choose **Edit**.

1. Under **Header mappings**, enter the following.

   1. For **id**, enter **integration.response.header.x-app-id**

   1. For **item**, enter **integration.response.multivalueheader.item**

   1. For **location**, enter **integration.response.body.redirect.url**

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

------
#### [ CloudFormation ]

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body:
        openapi: 3.0.1
        info:
          title: Parameter mapping example
          version: "2025-01-15T19:21:35Z"
        paths:
          /:
            post:
              responses:
                "200":
                  description: 200 response
                  headers:
                    item:
                      schema:
                        type: string
                    location:
                      schema:
                        type: string
                    id:
                      schema:
                        type: string
              x-amazon-apigateway-integration:
                type: http
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                    responseParameters:
                      method.response.header.id: integration.response.header.x-app-id
                      method.response.header.location: integration.response.body.redirect.url
                      method.response.header.item: integration.response.multivalueheader.item
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

The following OpenAPI definition maps the integration response to the method response.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example",
    "version" : "2025-01-15T19:21:35Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "item" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "location" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "id" : {
                "schema" : {
                  "type" : "string"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "http",
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.id" : "integration.response.header.x-app-id",
                "method.response.header.location" : "integration.response.body.redirect.url",
                "method.response.header.item" : "integration.response.multivalueheader.item"
              }
            }
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000
        }
      }
    }
  }
}
```

------

# Parameter mapping source reference for REST APIs in API Gateway
<a name="rest-api-parameter-mapping-sources"></a>

When you create a parameter mapping, you specify the method request or integration response parameters to modify and you specify how to modify those parameters.

The following table shows the method request parameters that you can map, and the expression to create the mapping. In these expressions, *name* is the name of a method request parameter. For example, to map the request header parameter `puppies`, use the expression `method.request.header.puppies`. Your expression must match the regular expression `'^[a-zA-Z0-9._$-]+$]'`. You can use parameter mapping in your integration request for proxy and non-proxy integrations. 


| **Mapped data source** | **Mapping expression** | 
| --- | --- | 
| Method request path | method.request.path.name | 
| Method request query string | method.request.querystring.name | 
| Multi-value method request query string | method.request.multivaluequerystring.name | 
| Method request header | method.request.header.name | 
| Multi-value method request header | method.request.multivalueheader.name | 
| Method request body | method.request.body | 
| Method request body (JsonPath) | `method.request.body.JSONPath_EXPRESSION`. *JSONPath\$1EXPRESSION* is a JSONPath expression for a JSON field of the body of a request. For more information, see [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2).  | 
| Stage variables | stageVariables.name | 
| Context variables |  `context.name` The name must be one of the [supported context variables](api-gateway-mapping-template-reference.md#context-variable-reference). | 
| Static value | `'static_value'`. The *static\$1value* is a string literal and must be enclosed within a pair of single quotes. For example, `'https://www.example.com'`. | 

The following table shows the integration response parameters that you can map and the expression to create the mapping. In these expressions, *name* is the name of an integration response parameter. You can map method response headers from any integration response header or integration response body, \$1context variables, or static values. To use parameter mapping for an integration response, you need a non-proxy integration.


| Mapped data source | Mapping expression | 
| --- | --- | 
| Integration response header | integration.response.header.name | 
| Integration response header | integration.response.multivalueheader.name | 
| Integration response body | integration.response.body | 
| Integration response body (JsonPath) | `integration.response.body.JSONPath_EXPRESSION` *JSONPath\$1EXPRESSION* is a JSONPath expression for a JSON field of the body of a response. For more information, see [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2). | 
| Stage variable | stageVariables.name | 
| Context variable |  `context.name` The name must be one of the [supported context variables](api-gateway-mapping-template-reference.md#context-variable-reference). | 
| Static value | ` 'static_value'` The *static\$1value* is a string literal and must be enclosed within a pair of single quotes. For example, `'https://www.example.com'`. | 

# Mapping template transformations for REST APIs in API Gateway
<a name="models-mappings"></a>

A mapping template transformation uses a mapping template to modify your integration request or integration response. A *mapping template* is a script expressed in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) and applied to a payload using [JSONPath ](https://goessner.net/articles/JsonPath/) based on the `Content-type` header. You use mapping templates when you use mapping template transformations. This section describes conceptual information related to mapping templates.

The following diagram shows the request lifecycle for a `POST /pets` resource that has an integration with a PetStore integration endpoint. In this API, a user sends data about a pet and the integration endpoint returns the adoption fee associated with a pet. In this request lifecycle, mapping template transformations filter the request body to the integration endpoint and filter the response body from the integration endpoint.

![\[Example request lifecycle\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/mapping-template-transforms.png)


The following sections explain the request and response lifecycle.

## Method request and integration request
<a name="models-mappings-request"></a>

In the previous example, if this is the request body sent to the method request:

```
POST /pets
    HTTP/1.1
    Host:abcd1234.us-west-2.amazonaws.com
    Content-type: application/json
    
  {
    "id": 1,
    "type": "dog",
    "Age": 11,
  }
```

This request body is not in the correct format to be used by the integration endpoint, so API Gateway performs a mapping template transformation. API Gateway only performs a mapping template transformation because there is a mapping template defined for the Content-Type `application/json`. If you don't define a mapping template for the Content-Type, by default, API Gateway passes the body through the integration request to the integration endpoint. To modify this behavior, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md).

The following mapping template transforms the method request data in the integration request before it's sent to the integration endpoint:

```
#set($inputRoot = $input.path('$'))
  {
    "dogId" : "dog_"$elem.id,
    "Age": $inputRoot.Age
  }
```

1. The `$inputRoot` variable represents the root object in the original JSON data from the previous section. Directives begin with the `#` symbol.

1. The `dog` is a concatenation of the user's `id` and a string value.

1. `Age` is from the method request body.

Then, the following output is forwarded to the integration endpoint:

```
{
    "dogId" : "dog_1",
    "Age": 11
  }
```

## Integration response and method response
<a name="models-mappings-response"></a>

After the successful request to the integration endpoint, the endpoint sends a response to API Gateway's integration response. The following is the example output data from the integration endpoint:

```
{
    "dogId" : "dog_1",
    "adoptionFee": 19.95,
}
```

The method response expects a different payload than what is returned by the integration response. API Gateway performs a mapping template transformation. API Gateway only performs a mapping template transformation because there is a mapping template defined for the Content-Type `application/json`. If you don't define a mapping template for the Content-Type, by default, API Gateway passes the body through the integration response to the method response. To modify this behavior, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md).

```
#set($inputRoot = $input.path('$'))
  {
    "adoptionFee" : $inputRoot.adoptionFee,
  }
```

The following output is sent to the method response:

```
{"adoptionFee": 19.95}
```

This completes the example mapping template transformation. We recommend that when possible, instead of using mapping template transformations, you use a proxy integration to transform your data. For more information, see [Choose an API Gateway API integration type](api-gateway-api-integration-types.md).

# Method request behavior for payloads without mapping templates for REST APIs in API Gateway
<a name="integration-passthrough-behaviors"></a>

If your method request has a payload and you don't have a mapping template defined for the `Content-Type` header, you can choose to pass the client-supplied request payload through the integration request to the backend without transformation. The process is known as integration passthrough. 

 The actual passthrough behavior of an incoming request is determined by this setting. There are three options: 

**When no template matches the request Content-Type header**  
Choose this option if you want the method request body to pass through the integration request to the backend without transformation when the method request content type does not match any content types associated with the mapping templates.  
When calling the API Gateway API, you choose this option by setting `WHEN_NO_MATCH` as the `passthroughBehavior` property value on the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html).

**When there are no templates defined (recommended)**  
Choose this option if you want the method request body to pass through the integration request to the backend without transformation when no mapping template is defined in the integration request. If a template is defined when this option is selected, the method request with a payload and content type that doesn't match any defined mapping template will be rejected with an HTTP 415 Unsupported Media Type response.  
When calling the API Gateway API, you choose this option by setting `WHEN_NO_TEMPLATES` as the `passthroughBehavior` property value on the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html).

**Never**  
Choose this option if you do not want the method request body to pass through the integration request to the backend without transformation when no mapping template is defined in the integration request. If a template is defined when this option is selected, the method request of an unmapped content type will be rejected with an HTTP 415 Unsupported Media Type response.   
When calling the API Gateway API, you choose this option by setting `NEVER` as the `passthroughBehavior` property value on the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html).

 The following examples show the possible passthrough behaviors. 

Example 1: One mapping template is defined in the integration request for the `application/json` content type.


| Content-type | Passthrough option | Behavior | 
| --- | --- | --- | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1MATCH | The request payload is transformed using the template. | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1TEMPLATES | The request payload is transformed using the template. | 
| None API Gateway defaults to `application/json` | NEVER | The request payload is transformed using the template. | 
| application/json | WHEN\$1NO\$1MATCH | The request payload is transformed using the template. | 
| application/json | WHEN\$1NO\$1TEMPLATES | The request payload is transformed using the template. | 
| application/json | NEVER | The request payload is transformed using the template. | 
| application/xml | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/xml | WHEN\$1NO\$1TEMPLATES | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/xml | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 

Example 2: One mapping template is defined in the integration request for the `application/xml` content type.


| Content-type | Passthrough option | Behavior | 
| --- | --- | --- | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1TEMPLATES | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| None API Gateway defaults to `application/json` | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/json | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/json | WHEN\$1NO\$1TEMPLATES | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/json | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/xml | WHEN\$1NO\$1MATCH | The request payload is transformed using the template. | 
| application/xml | WHEN\$1NO\$1TEMPLATES | The request payload is transformed using the template. | 
| application/xml | NEVER | The request payload is transformed using the template. | 

Example 3: No mapping templates are defined in the integration request.


| Content-type | Passthrough option | Behavior | 
| --- | --- | --- | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1TEMPLATES | The request payload is not transformed and is sent to the backend as-is. | 
| None API Gateway defaults to `application/json` | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/json | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/json | WHEN\$1NO\$1TEMPLATES | The request payload is not transformed and is sent to the backend as-is. | 
| application/json | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/xml | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/xml | WHEN\$1NO\$1TEMPLATES | The request payload is not transformed and is sent to the backend as-is. | 
| application/xml | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 

# Additional mapping template example for REST APIs in API Gateway
<a name="example-photos"></a>

The following example shows a photo album API in API Gateway that uses mapping templates to transform integration request and integration response data. It also uses data models to define method request and integration response payloads. For more information about data models, see [Data models for REST APIs](models-mappings-models.md).

## Method request and integration request
<a name="example-photos-request"></a>

The following is a model that defines the method request body. This input model requires that the caller upload one photo page, and requires a minimum of 10 photos for each page. You can use this input model to generate an SDK or to use request validation for your API. While using request validation, if the method request body doesn't adhere to the data structure of the model, API Gateway fails the request. 

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosInputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "object",
      "required" : [
      "photo"
      ],
      "properties": {
        "page": { "type": "integer" },
        "pages": { "type": "string" },
        "perpage": { "type": "integer", "minimum" : 10 },
        "total": { "type": "string" },
        "photo": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "owner": { "type": "string" },
              "photographer_first_name" : {"type" : "string"},
              "photographer_last_name" : {"type" : "string"},
              "secret": { "type": "string" },
              "server": { "type": "string" },
              "farm": { "type": "integer" },
              "title": { "type": "string" },
              "ispublic": { "type": "boolean" },
              "isfriend": { "type": "boolean" },
              "isfamily": { "type": "boolean" }
            }
          }
        }
      }
    }
  }
}
```

The following is an example method request body that adheres to the data structure of the previous data model.

```
{
  "photos": {
    "page": 1,
    "pages": "1234",
    "perpage": 100,
    "total": "123398",
    "photo": [
      {
        "id": "12345678901",
        "owner": "23456789@A12",
        "photographer_first_name" : "Saanvi",
        "photographer_last_name" : "Sarkar",
        "secret": "abc123d456",
        "server": "1234",
        "farm": 1,
        "title": "Sample photo 1",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      },
      {
        "id": "23456789012",
        "owner": "34567890@B23",
        "photographer_first_name" : "Richard",
        "photographer_last_name" : "Roe",
        "secret": "bcd234e567",
        "server": "2345",
        "farm": 2,
        "title": "Sample photo 2",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      }
    ]
  }
}
```

In this example, if the previous method request body was submitted by the client, then this mapping template transforms the payload to match the format required by the integration endpoint.

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.ispublic,
      "isfriend": $elem.isfriend,
      "isfamily": $elem.isfamily
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

The following example is output data from the transformation:

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

This data is sent to the integration request, and then to the integration endpoint.

## Integration response and method response
<a name="photos-example-response"></a>

The following is an example output model for the photo data from the integration endpoint. You can use this model for a method response model, which is necessary when you generate a strongly typed SDK for the API. This causes the output to be cast into an appropriate class in Java or Objective-C.

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosOutputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "photographedBy": { "type": "string" },
          "title": { "type": "string" },
          "ispublic": { "type": "boolean" },
          "isfriend": { "type": "boolean" },
          "isfamily": { "type": "boolean" }
        }
      }
    }
  }
}
```

The integration endpoint might not respond with a response that adheres to the data structure of this model. For instance, the integration response might look like the following:

```
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    }		
  ]
}
```

The following example mapping template transforms the integration response data into the format expected by the method response:

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.public,
      "isfriend": $elem.friend,
      "isfamily": $elem.family
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

The following example is output data from the transformation:

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

This data is sent to the method response and then back to the client.

# Override your API's request and response parameters and status codes for REST APIs in API Gateway
<a name="apigateway-override-request-response-parameters"></a>

You can use mapping template transformations to override any type of request parameter, response header, or response status code. You use a mapping template to do the following:
+ Perform many-to-one parameter mappings
+ Override parameters after standard API Gateway mappings have been applied
+ Conditionally map parameters based on body content or other parameter values
+ Programmatically create new parameters
+ Override status codes returned by your integration endpoint

Overrides are final. An override may only be applied to each parameter once. If you try to override the same parameter multiple times, API Gateway returns a `5XX` response. If you must override the same parameter multiple times throughout the template, we recommend creating a variable and applying the override at the end of the template. The template is applied only after the entire template is parsed.

## Example 1: Override the status code based on the integration body
<a name="apigateway-override-request-response-examples"></a>

The following example use the [example API](api-gateway-create-api-from-example.md) to override the status code based on the integration response body.

------
#### [ AWS Management Console ]

**To override a status code based on the integration response body**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Create API**.

1. For **REST API**, choose **Build**.

1. For **API details**, choose **Example API**.

1. Choose **Create API**.

   API Gateway creates an example pet store API. To retrieve information about a pet, you use the API method request of `GET /pets/{petId}`, where `{petId}` is a path parameter corresponding to an ID number for a pet.

   In this example, you override the `GET` method's response code to `400` when an error condition is detected.

1. In the **Resources** tree, choose the `GET` method under `/{petId}`.

1. First, you test the current implementation of the API. 

   Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. For **petId**, enter **-1**, and then choose **Test**.

   The **Response body** indicates an out-of-range error:

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   In addition, the last line under **Logs** ends with: `Method completed with status: 200`.

   The integration was completed successfully, but there was an error. Now you'll override the status code based on the integration response.

1. On the **Integration response** tab, for the **Default - Response**, choose **Edit**.

1. Choose **Mapping templates**.

1. Choose **Add mapping template**.

1. For **Content type**, enter **application/json**.

1. For **Template body**, enter the following:

   ```
   #set($inputRoot = $input.path('$'))
   $input.json("$")
   #if($inputRoot.toString().contains("error"))
   #set($context.responseOverride.status = 400)
   #end
   ```

   This mapping template uses the `$context.responseOverride.status` variable to override the status code to `400` if the integration response contains the string `error`.

1. Choose **Save**.

1. Choose the **Test** tab.

1. For **petId**, enter **-1**.

1. In the results, the **Response Body** indicates an out-of-range error:

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   However, the last line under **Logs** now ends with: `Method completed with status: 400`.

------
#### [ CloudFormation ]

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 1
          description: Example pet store API.
          version: "2025-01-14T00:13:18Z"
        paths:
          /pets/{petId}:
            get:
              parameters:
                - name: petId
                  in: path
                  required: true
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}
                responses:
                  default:
                    statusCode: "200"
                    responseTemplates:
                      application/json: |-
                        #set($inputRoot = $input.path('$'))
                        $input.json("$")
                        #if($inputRoot.toString().contains("error"))
                        #set($context.responseOverride.status = 400)
                        #end
                requestParameters:
                  integration.request.path.petId: method.request.path.petId
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

The following OpenAPI definition creates the `GET pets/{petId}` resource and overrides the status code based on the integration body.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 1",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:13:18Z"
  },
  "paths" : {
    "/pets/{petId}" : {
      "get" : {
        "parameters" : [ {
          "name" : "petId",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseTemplates" : {
                "application/json" : "#set($inputRoot = $input.path('$'))\n$input.json(\"$\")\n#if($inputRoot.toString().contains(\"error\"))\n#set($context.responseOverride.status = 400)\n#end"
              }
            }
          },
          "requestParameters" : {
            "integration.request.path.petId" : "method.request.path.petId"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "Pet" : {
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer"
          },
          "type" : {
            "type" : "string"
          },
          "price" : {
            "type" : "number"
          }
        }
      }
    }
  }
}
```

------

## Example 2: Override the request header and create new headers
<a name="apigateway-override-request-response-examples-2"></a>

The following example uses the [example API](api-gateway-create-api-from-example.md) to override the request header and create new headers.

------
#### [ AWS Management Console ]

**To override a method's request header by creating a new header**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose the example API you created in the previous tutorial. The name of the API should be **PetStore**.

1. In the **Resources** tree, choose the `GET` method under `/pet`.

1. On the **Method request** tab, for **Method request settings**, choose **Edit**.

1. Choose **HTTP request headers**, and then choose **Add header**.

1. For **Name**, enter **header1**.

1. Choose **Add header**, and then create a second header called **header2**.

1. Choose **Save**.

   Now, you combine these headers into one header value using a mapping template.

1. On the **Integration request** tab, for **Integration request settings**, choose **Edit**.

1. For **Request body passthrough**, select **When there are no templates defined (recommended)**.

1. Choose **Mapping templates**, and then do the following:

   1. Choose **Add mapping template**.

   1. For **Content type**, enter **application/json**. 

   1. For **Template body**, enter the following:

      ```
      #set($header1Override = "pets")
      #set($header3Value = "$input.params('header1')$input.params('header2')")
      $input.json("$")
      #set($context.requestOverride.header.header3 = $header3Value)
      #set($context.requestOverride.header.header1 = $header1Override)
      #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
      ```

      This mapping template overrides `header1` with the string `pets` and creates a multi-value header called `$header3Value` that combines `header1` and `header2`.

1. Choose **Save**.

1. Choose the **Test** tab.

1. Under **Headers**, copy the following code:

   ```
   header1:header1Val
   header2:header2Val
   ```

1. Choose **Test**.

   In the **Logs**, you should see an entry that includes this text:

   ```
   Endpoint request headers: {header3=header1Valheader2Val, 
   header2=header2Val, header1=pets, x-amzn-apigateway-api-id=api-id,
   Accept=application/json, multivalueheader=pets,header1Valheader2Val}
   ```

------
#### [ CloudFormation ]

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 2
          description: Example pet store API.
          version: "2025-01-14T00:36:18Z"
        paths:
          /pets:
            get:
              parameters:
                - name: header2
                  in: header
                  schema:
                    type: string
                - name: page
                  in: query
                  schema:
                    type: string
                - name: type
                  in: query
                  schema:
                    type: string
                - name: header1
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.header1: method.request.header.header1
                  integration.request.header.header2: method.request.header.header2
                  integration.request.querystring.page: method.request.querystring.page
                  integration.request.querystring.type: method.request.querystring.type
                requestTemplates:
                  application/json: |-
                    #set($header1Override = "pets")
                    #set($header3Value = "$input.params('header1')$input.params('header2')")
                    $input.json("$")
                    #set($context.requestOverride.header.header3 = $header3Value)
                    #set($context.requestOverride.header.header1 = $header1Override)
                    #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

------
#### [ OpenAPI ]

 The following OpenAPI definition creates the `GET pets` resource and overrides the request header and create new headers.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 2",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:36:18Z"
  },
  "paths" : {
    "/pets" : {
      "get" : {
        "parameters" : [ {
          "name" : "header2",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "page",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "type",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "header1",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.header1" : "method.request.header.header1",
            "integration.request.header.header2" : "method.request.header.header2",
            "integration.request.querystring.page" : "method.request.querystring.page",
            "integration.request.querystring.type" : "method.request.querystring.type"
          },
          "requestTemplates" : {
            "application/json" : "#set($header1Override = \"pets\")\n#set($header3Value = \"$input.params('header1')$input.params('header2')\")\n$input.json(\"$\")\n#set($context.requestOverride.header.header3 = $header3Value)\n#set($context.requestOverride.header.header1 = $header1Override)\n#set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  }
}
```

------

To use a mapping template override, add one or more of the following `$context` variables. For a list of `$context` variables, see [Context variables for data transformations](api-gateway-mapping-template-reference.md#context-variable-reference).

# Tutorial: Modify the integration request and response for integrations to AWS services
<a name="set-up-data-transformations-in-api-gateway"></a>

The following tutorial shows how to use mapping template transformations to set up mapping templates to transform integration requests and responses using the console and AWS CLI.

**Topics**
+ [Set up data transformation using the API Gateway console](#mapping-example-console)
+ [Set up data transformation using the AWS CLI](#mapping-example-cli)
+ [Completed data transformation CloudFormation template](#api-gateway-data-transformations-full-cfn-stack)

## Set up data transformation using the API Gateway console
<a name="mapping-example-console"></a>

In this tutorial, you will create an incomplete API and DynamoDB table using the following .zip file [data-transformation-tutorial-console.zip](samples/data-transformation-tutorial-console.zip). This incomplete API has a `/pets` resource with `GET` and `POST` methods. 
+ The `GET` method will get data from the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. The output data will be transformed according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).
+ The `POST` method will allow the user to `POST` pet information to a Amazon DynamoDB table using a mapping template.

Download and unzip [the app creation template for CloudFormation](samples/data-transformation-tutorial-console.zip). You'll use this template to create a DynamoDB table to post pet information and an incomplete API. You will finish the rest of the steps in the API Gateway console. 

**To create an CloudFormation stack**

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Choose **Create stack** and then choose **With new resources (standard)**.

1. For **Specify template**, choose **Upload a template file**.

1. Select the template that you downloaded.

1. Choose **Next**. 

1. For **Stack name**, enter **data-transformation-tutorial-console** and then choose **Next**.

1. For **Configure stack options**, choose **Next**.

1. For **Capabilities**, acknowledge that CloudFormation can create IAM resources in your account.

1. Choose **Next**, and then choose **Submit**.

CloudFormation provisions the resources specified in the template. It can take a few minutes to finish provisioning your resources. When the status of your CloudFormation stack is **CREATE\$1COMPLETE**, you're ready to move on to the next step.

**To test the `GET` integration response**

1. On the **Resources** tab of the CloudFormation stack for **data-transformation-tutorial-console**, select the physical ID of your API.

1. In the main navigation pane, choose **Resources**, and then select the **GET** method. 

1. Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

   The output of the test will show the following: 

   ```
   [
     {
       "id": 1,
       "type": "dog",
       "price": 249.99
     },
     {
       "id": 2,
       "type": "cat",
       "price": 124.99
     },
     {
       "id": 3,
       "type": "fish",
       "price": 0.99
     }
   ]
   ```

   You will transform this output according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).

**To transform the `GET` integration response**

1. Choose the **Integration response** tab.

   Currently, there are no mapping templates defined, so the integration response will not be transformed. 

1. For **Default - Response**, choose **Edit**.

1. Choose **Mapping templates**, and then do the following:

   1. Choose **Add mapping template**.

   1. For **Content type**, enter **application/json**. 

   1. For **Template body**, enter the following:

      ```
      #set($inputRoot = $input.path('$'))
      [
      #foreach($elem in $inputRoot)
        {
          "description" : "Item $elem.id is a $elem.type.",
          "askingPrice" : $elem.price
        }#if($foreach.hasNext),#end
      
      #end
      ]
      ```

   Choose **Save**.

**To test the `GET` integration response**
+ Choose the **Test** tab, and then choose **Test**.

  The output of the test will show the transformed response. 

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**To transform input data from the `POST` method**

1. Choose the **POST** method.

1. Choose the **Integration request** tab, and then for **Integration request settings**, choose **Edit**.

   The CloudFormation template has populated some of the integration request fields. 
   +  The integration type is AWS service. 
   +  The AWS service is DynamoDB. 
   +  The HTTP method is `POST`. 
   +  The Action is `PutItem`. 
   +  The Execution role allowing API Gateway to put an item into the DynamoDB table is `data-transformation-tutorial-console-APIGatewayRole`. CloudFormation created this role to allow API Gateway to have the minimal permissions for interacting with DynamoDB. 

    The name of the DynamoDB table has not been specified. You will specify the name in the following steps. 

1. For **Request body passthrough**, select **Never**.

   This means that the API will reject data with Content-Types that do not have a mapping template.

1. Choose **Mapping templates**.

1. The **Content type** is set to `application/json`. This means a content types that are not application/json will be rejected by the API. For more information about the integration passthrough behaviors, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md)

1. Enter the following code into the text editor.

   ```
   {
       "TableName":"data-transformation-tutorial-console-ddb",
       "Item": {
           "id": {
               "N": $input.json("$.id")
           },
           "type": {
               "S": $input.json("$.type")
           },
           "price": {
               "N": $input.json("$.price")
           }
       }
   }
   ```

    This template specifies the table as `data-transformation-tutorial-console-ddb` and sets the items as `id`, `type`, and `price`. The items will come from the body of the `POST` method. You also can use a data model to help create a mapping template. For more information, see [Request validation for REST APIs in API Gateway](api-gateway-method-request-validation.md). 

1. Choose **Save** to save your mapping template. 

**To add a method and integration response from the `POST` method**

The CloudFormation created a blank method and integration response. You will edit this response to provide more information. For more information about how to edit responses, see [Parameter mapping examples for REST APIs in API Gateway](request-response-data-mappings.md).

1. On the **Integration response** tab, for **Default - Response**, choose **Edit**.

1. Choose **Mapping templates**, and then choose **Add mapping template**.

1. For **Content-type**, enter **application/json**.

1. In the code editor, enter the following output mapping template to send an output message:

   ```
   { "message" : "Your response was recorded at $context.requestTime" }
   ```

   For more information about context variables, see [Context variables for data transformations](api-gateway-mapping-template-reference.md#context-variable-reference).

1. Choose **Save** to save your mapping template. 

**Test the `POST` method**

Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. In the request body, enter the following example.

   ```
   {
             "id": "4",
             "type" : "dog",
             "price": "321"
   }
   ```

1. Choose **Test**.

   The output should show your success message.

    You can open the DynamoDB console at [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/) to verify that the example item is in your table. 

**To delete an CloudFormation stack**

1. Open the CloudFormation console at [https://console.aws.amazon.com/cloudformation](https://console.aws.amazon.com/cloudformation/).

1. Select your CloudFormation stack.

1. Choose **Delete** and then confirm your choice.

## Set up data transformation using the AWS CLI
<a name="mapping-example-cli"></a>

In this tutorial, you will create an incomplete API and DynamoDB table using the following .zip file [data-transformation-tutorial-cli.zip](samples/data-transformation-tutorial-cli.zip). This incomplete API has a `/pets` resource with a `GET` method integrated with the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. You will create a `POST` method to connect to a DynamoDB table and use mapping templates to input data into a DynamoDB table. 
+ You will transform the output data according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).
+ You will create a `POST` method to allow the user to `POST` pet information to a Amazon DynamoDB table using a mapping template.

**To create an CloudFormation stack**

Download and unzip [the app creation template for CloudFormation](samples/data-transformation-tutorial-cli.zip). 

To complete the following tutorial, you need the [AWS Command Line Interface (AWS CLI) version 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). 

For long commands, an escape character (`\`) is used to split a command over multiple lines.
**Note**  
In Windows, some Bash CLI commands that you commonly use (such as `zip`) are not supported by the operating system's built-in terminals. To get a Windows-integrated version of Ubuntu and Bash, [install the Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install). Example CLI commands in this guide use Linux formatting. Commands which include inline JSON documents must be reformatted if you are using the Windows CLI. 

1.  Use the following command to create the CloudFormation stack.

   ```
   aws cloudformation create-stack --stack-name data-transformation-tutorial-cli --template-body file://data-transformation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation provisions the resources specified in the template. It can take a few minutes to finish provisioning your resources. Use the following command to see the status of your CloudFormation stack.

   ```
   aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli
   ```

1. When the status of your CloudFormation stack is `StackStatus: "CREATE_COMPLETE"`, use the following command to retrieve relevant output values for future steps.

   ```
    aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   The output values are the following:
   + ApiRole, which is the role name that allows API Gateway to put items in the DynamoDB table. For this tutorial, the role name is `data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG`.
   + DDBTableName, which is the name of the DynamoDB table. For this tutorial, the table name is `data-transformation-tutorial-cli-ddb`
   + ResourceId, which is the ID for the pets resource where the `GET` and `POST` methods are exposed. For this tutorial, the Resource ID is `efg456`
   + ApiId, which is the ID for the API. For this tutorial, the API ID is `abc123`.

**To test the `GET` method before data transformation**
+ Use the following command to test the `GET` method. 

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
            --resource-id efg456 \
            --http-method GET
  ```

  The output of the test will show the following.

  ```
  [
    {
      "id": 1,
      "type": "dog",
      "price": 249.99
    },
    {
      "id": 2,
      "type": "cat",
      "price": 124.99
    },
    {
      "id": 3,
      "type": "fish",
      "price": 0.99
    }
  ]
  ```

  You will transform this output according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).

**To transform the `GET` integration response**
+ Use the following command to update the integration response for the `GET` method. Replace the *rest-api-id* and *resource-id* with your values.

  Use the following command to create the integration response.

  ```
  aws apigateway put-integration-response --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
    --status-code 200 \
    --selection-pattern "" \
    --response-templates '{"application/json": "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"}'
  ```

**To test the `GET` method**
+ Use the following command to test the `GET` method.

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
  ```

  The output of the test will show the transformed response. 

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**To create a `POST` method**

1. Use the following command to create a new method on the `/pets` resource.

   ```
   aws apigateway put-method --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --authorization-type "NONE" \
   ```

   This method will allow you to send pet information to the DynamoDB table that your created in the CloudFormation stack.

1.  Use the following command to create an AWS service integration on the `POST` method.

   ```
   aws apigateway put-integration --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --type AWS \
     --integration-http-method POST \
     --uri "arn:aws:apigateway:us-east-2:dynamodb:action/PutItem" \
     --credentials arn:aws:iam::111122223333:role/data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG \
     --request-templates '{"application/json":"{\"TableName\":\"data-transformation-tutorial-cli-ddb\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"}'
   ```

1.  Use the following command to create a method response for a successful call of the `POST` method. 

   ```
   aws apigateway put-method-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200
   ```

1. Use the following command to create an integration response for the successful call of the `POST` method.

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200 \
     --selection-pattern "" \
     --response-templates '{"application/json": "{\"message\": \"Your response was recorded at $context.requestTime\"}"}'
   ```

**To test the `POST` method**
+ Use the following command to test the `POST` method.

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method POST \
    --body '{\"id\": \"4\", \"type\": \"dog\", \"price\": \"321\"}'
  ```

  The output will show the successful message.

**To delete an CloudFormation stack**
+ Use the following command to delete your CloudFormation resources.

  ```
  aws cloudformation delete-stack  --stack-name data-transformation-tutorial-cli
  ```

## Completed data transformation CloudFormation template
<a name="api-gateway-data-transformations-full-cfn-stack"></a>

The following example is a completed CloudFormation template, which creates an API and a DynamoDB table with a `/pets` resource with `GET` and `POST` methods. 
+ The `GET` method will get data from the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. The output data will be transformed according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).
+ The `POST` method will allow the user to `POST` pet information to a DynamoDB table using a mapping template.

### Example CloudFormation template
<a name="mapping-template-cfn-example"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: A completed Amazon API Gateway REST API that uses non-proxy integration to POST to an Amazon DynamoDB table and non-proxy integration to GET transformed pets data.
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  DynamoDBTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: !Sub data-transformation-tutorial-complete
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: N
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  APIGatewayRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17		 	 	 
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
      Policies:
        - PolicyName: APIGatewayDynamoDBPolicy
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - 'dynamodb:PutItem'
                Resource: !GetAtt DynamoDBTable.Arn
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: data-transformation-complete-api
      ApiKeySourceType: HEADER
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: HTTP
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
        PassthroughBehavior: WHEN_NO_TEMPLATES
        IntegrationResponses:
          - StatusCode: '200'
            ResponseTemplates:
              application/json: "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"
      MethodResponses:
        - StatusCode: '200'
  PetsMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: POST
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: POST
        Uri: arn:aws:apigateway:us-west-1:dynamodb:action/PutItem
        PassthroughBehavior: NEVER
        RequestTemplates: 
          application/json: "{\"TableName\":\"data-transformation-tutorial-complete\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: "{\"message\": \"Your response was recorded at $context.requestTime\"}"
      MethodResponses:
        - StatusCode: '200'

  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiId:
    Description: API ID for CLI commands
    Value: !Ref Api
  ResourceId:
    Description: /pets resource ID for CLI commands
    Value: !Ref PetsResource
  ApiRole:
    Description: Role ID to allow API Gateway to put and scan items in DynamoDB table
    Value: !Ref APIGatewayRole
  DDBTableName:
    Description: DynamoDB table name
    Value: !Ref DynamoDBTable
```

# Examples using variables for mapping template transformations for API Gateway
<a name="api-gateway-mapping-variable-examples"></a>

The following examples show how to use `$context`, `input`, and `util` variables in mapping templates. You can use a mock integration or a Lambda non-proxy integration that returns the input event back to API Gateway. For a list of all supported variables for data transformations, see [Variables for data transformations for API Gateway](api-gateway-mapping-template-reference.md).

## Example 1: Pass multiple `$context` variables to the integration endpoint
<a name="context-variables-template-example"></a>

The following example shows a mapping template that maps incoming `$context` variables to backend variables with slightly different names in an integration request payload:

```
{
    "stage" : "$context.stage",
    "request_id" : "$context.requestId",
    "api_id" : "$context.apiId",
    "resource_path" : "$context.resourcePath",
    "resource_id" : "$context.resourceId",
    "http_method" : "$context.httpMethod",
    "source_ip" : "$context.identity.sourceIp",
    "user-agent" : "$context.identity.userAgent",
    "account_id" : "$context.identity.accountId",
    "api_key" : "$context.identity.apiKey",
    "caller" : "$context.identity.caller",
    "user" : "$context.identity.user",
    "user_arn" : "$context.identity.userArn"
}
```

The output of this mapping template should look like the following:

```
{
  stage: 'prod',
  request_id: 'abcdefg-000-000-0000-abcdefg',
  api_id: 'abcd1234',
  resource_path: '/',
  resource_id: 'efg567',
  http_method: 'GET',
  source_ip: '192.0.2.1',
  user-agent: 'curl/7.84.0',
  account_id: '111122223333',
  api_key: 'MyTestKey',
  caller: 'ABCD-0000-12345',
  user: 'ABCD-0000-12345',
  user_arn: 'arn:aws:sts::111122223333:assumed-role/Admin/carlos-salazar'
}
```

One of the variables is an API key. This example assumes that the method requires an API key.

## Example 2: Pass all request parameters to the integration endpoint via a JSON payload
<a name="input-examples-mapping-templates"></a>

The following example passes all request parameters, including `path`, `querystring`, and `header` parameters, through to the integration endpoint via a JSON payload:

```
#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}
```

If a request has the following input parameters:
+ A path parameter named `myparam`
+ Query string parameters `querystring1=value1,value2`
+ Headers `"header1" : "value1"`.

The output of this mapping template should look like the following:

```
{"params":{"path":{"example2":"myparamm"},"querystring":{"querystring1":"value1,value2"},"header":{"header1":"value1"}}}
```

## Example 3: Pass a subsection of a method request to the integration endpoint
<a name="input-example-json-mapping-template"></a>

 The following example uses the input parameter `name` to retrieve only the `name` parameter and the input parameter `input.json('$')` to retrieve the entire body of the method request:

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$') 
}
```

For a request that includes the query string parameters `name=Bella&type=dog` and the following body:

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

The output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body" : {"Price":"249.99","Age":"6"}
}
```

This mapping template removes the query string parameter `type=dog`.

 If the JSON input contains unescaped characters that cannot be parsed by JavaScript, API Gateway might return a 400 response. Apply `$util.escapeJavaScript($input.json('$'))` to ensure the JSON input can be parsed properly. 

The previous example with `$util.escapeJavaScript($input.json('$'))` applied is as follows:

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$'))"
}
```

In this case, the output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body": {"Price":"249.99","Age":"6"}
}
```

## Example 4: Use JSONPath expression to pass a subsection of a method request to the integration endpoint
<a name="input-example-inputs-mapping-template"></a>

The following example uses the JSONPath expressions to retrieve only the input parameter `name` and the `Age` from the request body:

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$.Age')  
}
```

For a request that includes the query string parameters `name=Bella&type=dog` and the following body:

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

The output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body" : "6"
}
```

This mapping template removes the query string parameter `type=dog` and the `Price` field from the body.

 If a method request payload contains unescaped characters that cannot be parsed by JavaScript, API Gateway might return a `400` response. Apply `$util.escapeJavaScript()` to ensure the JSON input can be parsed properly.

The previous example with `$util.escapeJavaScript($input.json('$.Age'))` applied is as follows:

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$.Age'))" 
}
```

In this case, the output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body": "\"6\""
}
```

## Example 5: Use a JSONPath expression to pass information about a method request to the integration endpoint
<a name="input-example-request-and-response"></a>

The following example uses `$input.params()`, `$input.path()`, and `$input.json()` to send information about a method request to the integration endpoint. This mapping template uses the `size()` method to provide the number of elements in a list.

```
{
    "id" : "$input.params('id')",
    "count" : "$input.path('$.things').size()",
    "things" : $input.json('$.things')
}
```

For a request that includes the path parameter `123` and the following body:

```
{
      "things": {
            "1": {},
            "2": {},
            "3": {}
      }
}
```

The output of this mapping template should look like the following:

```
{"id":"123","count":"3","things":{"1":{},"2":{},"3":{}}}
```

 If a method request payload contains unescaped characters that cannot be parsed by JavaScript, API Gateway might return a `400` response. Apply `$util.escapeJavaScript()` to ensure the JSON input can be parsed properly.

The previous example with `$util.escapeJavaScript($input.json('$.things'))` applied is as follows:

```
{
     "id" : "$input.params('id')",
     "count" : "$input.path('$.things').size()",
     "things" : "$util.escapeJavaScript($input.json('$.things'))"
}
```

The output of this mapping template should look like the following:

```
{"id":"123","count":"3","things":"{\"1\":{},\"2\":{},\"3\":{}}"}
```

# Variables for data transformations for API Gateway
<a name="api-gateway-mapping-template-reference"></a>

When you create a parameter mapping, you can use context variables as your data source. When you create mapping template transformations, you can use context variables, input, and util variables in scripts you write in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html). For example mapping templates that use these reference variables, see [Examples using variables for mapping template transformations for API Gateway](api-gateway-mapping-variable-examples.md).

For a list of reference variables for access logging, see [Variables for access logging for API Gateway](api-gateway-variables-for-access-logging.md).

## Context variables for data transformations
<a name="context-variable-reference"></a>

You can use the following case-sensitive `$context` variables for data transformations.


| Parameter | Description | 
| --- | --- | 
| \$1context.accountId |  The API owner's AWS account ID.  | 
| \$1context.apiId |  The identifier API Gateway assigns to your API.  | 
| \$1context.authorizer.claims.property |  A property of the claims returned from the Amazon Cognito user pool after the method caller is successfully authenticated. For more information, see [Control access to REST APIs using Amazon Cognito user pools as an authorizer](apigateway-integrate-with-cognito.md).  Calling `$context.authorizer.claims` returns null.   | 
| \$1context.authorizer.principalId |  The principal user identification associated with the token sent by the client and returned from an API Gateway Lambda authorizer (formerly known as a custom authorizer). For more information, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).  | 
| \$1context.authorizer.property |  The stringified value of the specified key-value pair of the `context` map returned from an API Gateway Lambda authorizer function. For example, if the authorizer returns the following `context` map:  <pre>"context" : {<br />  "key": "value",<br />  "numKey": 1,<br />  "boolKey": true<br />}</pre> Calling `$context.authorizer.key` returns the `"value"` string, calling `$context.authorizer.numKey` returns the `"1"` string, and calling `$context.authorizer.boolKey` returns the `"true"` string. For *property*, the only supported special character is the underscore `(_)` character. For more information, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).  | 
| \$1context.awsEndpointRequestId |  The AWS endpoint's request ID.  | 
| \$1context.deploymentId | The ID of the API deployment. | 
| \$1context.domainName |  The full domain name used to invoke the API. This should be the same as the incoming `Host` header.  | 
| \$1context.domainPrefix |  The first label of the `$context.domainName`.  | 
| \$1context.error.message |  A string containing an API Gateway error message. This variable can only be used for simple variable substitution in a [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) body-mapping template, which is not processed by the Velocity Template Language engine, and in access logging. For more information, see [Monitor WebSocket API execution with CloudWatch metrics](apigateway-websocket-api-logging.md) and [Setting up gateway responses to customize error responses](api-gateway-gatewayResponse-definition.md#customize-gateway-responses).  | 
| \$1context.error.messageString | The quoted value of \$1context.error.message, namely "\$1context.error.message". | 
| \$1context.error.responseType |  A [type](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseType) of [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html). This variable can only be used for simple variable substitution in a [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) body-mapping template, which is not processed by the Velocity Template Language engine, and in access logging. For more information, see [Monitor WebSocket API execution with CloudWatch metrics](apigateway-websocket-api-logging.md) and [Setting up gateway responses to customize error responses](api-gateway-gatewayResponse-definition.md#customize-gateway-responses).  | 
| \$1context.error.validationErrorString |  A string containing a detailed validation error message.  | 
| \$1context.extendedRequestId | The extended ID that API Gateway generates and assigns to the API request. The extended request ID contains useful information for debugging and troubleshooting. | 
| \$1context.httpMethod |  The HTTP method used. Valid values include: `DELETE`, `GET`, `HEAD`, `OPTIONS`, `PATCH`, `POST`, and `PUT`.  | 
| \$1context.identity.accountId |  The AWS account ID associated with the request.  | 
| \$1context.identity.apiKey |  For API methods that require an API key, this variable is the API key associated with the method request. For methods that don't require an API key, this variable is null. For more information, see [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md).  | 
| \$1context.identity.apiKeyId | The API key ID associated with an API request that requires an API key. | 
| \$1context.identity.caller |  The principal identifier of the caller that signed the request. Supported for resources that use IAM authorization.  | 
| \$1context.identity.cognitoAuthenticationProvider |  A comma-separated list of all the Amazon Cognito authentication providers used by the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  For example, for an identity from an Amazon Cognito user pool, `cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` For information about the available Amazon Cognito authentication providers, see [Using Federated Identities](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) in the *Amazon Cognito Developer Guide*. | 
| \$1context.identity.cognitoAuthenticationType |  The Amazon Cognito authentication type of the caller making the request. Available only if the request was signed with Amazon Cognito credentials. Possible values include `authenticated` for authenticated identities and `unauthenticated` for unauthenticated identities. | 
| \$1context.identity.cognitoIdentityId |  The Amazon Cognito identity ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.cognitoIdentityPoolId |  The Amazon Cognito identity pool ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.principalOrgId |  The [AWS organization ID](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html).  | 
| \$1context.identity.sourceIp |  The source IP address of the immediate TCP connection making the request to the API Gateway endpoint.  | 
| \$1context.identity.clientCert.clientCertPem |  The PEM-encoded client certificate that the client presented during mutual TLS authentication. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.subjectDN |  The distinguished name of the subject of the certificate that a client presents. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.issuerDN |  The distinguished name of the issuer of the certificate that a client presents. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.serialNumber |  The serial number of the certificate. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.validity.notBefore |  The date before which the certificate is invalid. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.validity.notAfter |  The date after which the certificate is invalid. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
|  \$1context.identity.vpcId | The VPC ID of the VPC making the request to the API Gateway endpoint. | 
|  \$1context.identity.vpceId |  The VPC endpoint ID of the VPC endpoint making the request to the API Gateway endpoint. Present only when you have a private API.  | 
| \$1context.identity.user |  The principal identifier of the user that will be authorized against resource access. Supported for resources that use IAM authorization.  | 
| \$1context.identity.userAgent |  The [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) header of the API caller.  | 
| \$1context.identity.userArn |  The Amazon Resource Name (ARN) of the effective user identified after authentication. For more information, see [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html).  | 
| \$1context.isCanaryRequest |  Returns `true` if the request was directed to the canary and `false` if the request was not directed to the canary. Present only when you have a canary enabled. | 
| \$1context.path | The request path. For example, for a non-proxy request URL of https://\$1rest-api-id\$1.execute-api.\$1region\$1.amazonaws.com/\$1stage\$1/root/child, the \$1context.path value is /\$1stage\$1/root/child.  | 
| \$1context.protocol | The request protocol, for example, HTTP/1.1.  API Gateway APIs can accept HTTP/2 requests, but API Gateway sends requests to backend integrations using HTTP/1.1. As a result, the request protocol is logged as HTTP/1.1 even if a client sends a request that uses HTTP/2.   | 
| \$1context.requestId |  An ID for the request. Clients can override this request ID. Use `$context.extendedRequestId` for a unique request ID that API Gateway generates.  | 
| \$1context.requestOverride.header.header\$1name |  The request header override. If this parameter is defined, it contains the headers to be used instead of the **HTTP Headers** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.requestOverride.path.path\$1name |  The request path override. If this parameter is defined, it contains the request path to be used instead of the **URL Path Parameters** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.requestOverride.querystring.querystring\$1name |  The request query string override. If this parameter is defined, it contains the request query strings to be used instead of the **URL Query String Parameters** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.responseOverride.header.header\$1name | The response header override. If this parameter is defined, it contains the header to be returned instead of the Response header that is defined as the Default mapping in the Integration Response pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md). | 
| \$1context.responseOverride.status | The response status code override. If this parameter is defined, it contains the status code to be returned instead of the Method response status that is defined as the Default mapping in the Integration Response pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md). | 
| \$1context.requestTime | The [CLF](https://httpd.apache.org/docs/current/logs.html#common)-formatted request time (dd/MMM/yyyy:HH:mm:ss \$1-hhmm). | 
| \$1context.requestTimeEpoch | The [Epoch](https://en.wikipedia.org/wiki/Unix_time)-formatted request time, in milliseconds. | 
| \$1context.resourceId |  The identifier that API Gateway assigns to your resource.  | 
| \$1context.resourcePath |  The path to your resource. For example, for the non-proxy request URI of `https://{rest-api-id}.execute-api.{region}.amazonaws.com/{stage}/root/child`, The `$context.resourcePath` value is `/root/child`. For more information, see [Tutorial: Create a REST API with an HTTP non-proxy integration](api-gateway-create-api-step-by-step.md).   | 
| \$1context.stage |  The deployment stage of the API request (for example, `Beta` or `Prod`).  | 
| \$1context.wafResponseCode |  The response received from [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html): `WAF_ALLOW` or `WAF_BLOCK`. Will not be set if the stage is not associated with a web ACL. For more information, see [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md).  | 
| \$1context.webaclArn |  The complete ARN of the web ACL that is used to decide whether to allow or block the request. Will not be set if the stage is not associated with a web ACL. For more information, see [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md).  | 

## Input variables
<a name="input-variable-reference"></a>

You can use the following case-sensitive `$input` variables to refer to the method request payload and method request parameters. The following functions are available:


| Variable and function | Description | 
| --- | --- | 
| \$1input.body |  Returns the raw request payload as a string. You can use `$input.body` to preserve entire floating point numbers, such as `10.00`. | 
| \$1input.json(x) | This function evaluates a JSONPath expression and returns the results as a JSON string. For example, `$input.json('$.pets')` returns a JSON string representing the `pets` structure. For more information about JSONPath, see [JSONPath](https://goessner.net/articles/JsonPath/) or [JSONPath for Java](https://github.com/json-path/JsonPath). | 
| \$1input.params() |  Returns a map of all the request parameters. We recommend that you use `$util.escapeJavaScript` to sanitize the result to avoid a potential injection attack. For full control of request sanitization, use a proxy integration without a template and handle request sanitization in your integration. | 
| \$1input.params(x) | Returns the value of a method request parameter from the path, query string, or header value (searched in that order), given a parameter name string `x`. We recommend that you use `$util.escapeJavaScript` to sanitize the parameter to avoid a potential injection attack. For full control of parameter sanitization, use a proxy integration without a template and handle request sanitization in your integration. | 
| \$1input.path(x) | Takes a JSONPath expression string (`x`) and returns a JSON object representation of the result. This allows you to access and manipulate elements of the payload natively in [Apache Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html). For example, if the expression `$input.path('$.pets')` returns an object like this: <pre>[<br />  { <br />    "id": 1, <br />    "type": "dog", <br />    "price": 249.99 <br />  }, <br />  { <br />    "id": 2, <br />    "type": "cat", <br />    "price": 124.99 <br />  }, <br />  { <br />    "id": 3, <br />    "type": "fish", <br />    "price": 0.99 <br />  } <br />]</pre> `$input.path('$.pets').size()` would return `"3"`. For more information about JSONPath, see [JSONPath](https://goessner.net/articles/JsonPath/) or [JSONPath for Java](https://github.com/json-path/JsonPath). | 

## Stage variables
<a name="stagevariables-template-reference"></a>

You can use the following stage variables as placeholders for ARNs and URLs in method integrations. For more information, see [Use stage variables for a REST API in API Gateway](stage-variables.md).


| Syntax | Description | 
| --- | --- | 
| \$1stageVariables.variable\$1name, \$1stageVariables['variable\$1name'], or \$1\$1stageVariables['variable\$1name']\$1  |  *variable\$1name* represents a stage variable name.  | 

## Util variables
<a name="util-template-reference"></a>

You can use the following case-sensitive `$util` variables to use utility functions for mapping templates. Unless otherwise specified, the default character set is UTF-8.


| Function | Description | 
| --- | --- | 
| \$1util.escapeJavaScript() |  Escapes the characters in a string using JavaScript string rules.  This function will turn any regular single quotes (`'`) into escaped ones (`\'`). However, the escaped single quotes are not valid in JSON. Thus, when the output from this function is used in a JSON property, you must turn any escaped single quotes (`\'`) back to regular single quotes (`'`). This is shown in the following example:  <pre> "input" : "$util.escapeJavaScript(data).replaceAll("\\'","'")"</pre>   | 
| \$1util.parseJson() |   Takes "stringified" JSON and returns an object representation of the result. You can use the result from this function to access and manipulate elements of the payload natively in Apache Velocity Template Language (VTL). For example, if you have the following payload:  <pre>{"errorMessage":"{\"key1\":\"var1\",\"key2\":{\"arr\":[1,2,3]}}"}</pre>  and use the following mapping template  <pre>#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))<br />{<br />   "errorMessageObjKey2ArrVal" : $errorMessageObj.key2.arr[0]<br />}<br /></pre> You will get the following output: <pre>{<br />   "errorMessageObjKey2ArrVal" : 1<br />}<br /></pre>  | 
| \$1util.urlEncode() | Converts a string into "application/x-www-form-urlencoded" format. | 
| \$1util.urlDecode() | Decodes an "application/x-www-form-urlencoded" string. | 
| \$1util.base64Encode() | Encodes the data into a base64-encoded string. | 
| \$1util.base64Decode() | Decodes the data from a base64-encoded string. | 

# Gateway responses for REST APIs in API Gateway
<a name="api-gateway-gatewayResponse-definition"></a>

 A gateway response is identified by a response type that is defined by API Gateway. The response consists of an HTTP status code, a set of additional headers that are specified by parameter mappings, and a payload that is generated by a non-[VTL](https://velocity.apache.org/engine/devel/vtl-reference.html) mapping template. 

 In the API Gateway REST API, a gateway response is represented by the [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html). In OpenAPI, a `GatewayResponse` instance is described by the [x-amazon-apigateway-gateway-responses.gatewayResponse](api-gateway-swagger-extensions-gateway-responses.gatewayResponse.md) extension. 

To enable a gateway response, you set up a gateway response for a [supported response type](supported-gateway-response-types.md) at the API level. Whenever API Gateway returns a response of this type, the header mappings and payload mapping templates defined in the gateway response are applied to return the mapped results to the API caller. 

 In the following section, we show how to set up gateway responses by using the API Gateway console and the API Gateway REST API. 

## Setting up gateway responses to customize error responses
<a name="customize-gateway-responses"></a>

If API Gateway fails to process an incoming request, it returns to the client an error response without forwarding the request to the integration backend. By default, the error response contains a short descriptive error message. For example, if you attempt to call an operation on an undefined API resource, you receive an error response with the `{ "message": "Missing Authentication Token" }` message. If you are new to API Gateway, you may find it difficult to understand what actually went wrong. 

 For some of the error responses, API Gateway allows customization by API developers to return the responses in different formats. For the `Missing Authentication Token` example, you can add a hint to the original response payload with the possible cause, as in this example: `{"message":"Missing Authentication Token", "hint":"The HTTP method or resources may not be supported."}`. 

 When your API mediates between an external exchange and the AWS Cloud, you use VTL mapping templates for integration request or integration response to map the payload from one format to another. However, the VTL mapping templates work only for valid requests with successful responses. 

For invalid requests, API Gateway bypasses the integration altogether and returns an error response. You must use the customization to render the error responses in an exchange-compliant format. Here, the customization is rendered in a non-VTL mapping template supporting only simple variable substitutions. 

 Generalizing the API Gateway-generated error response to any responses generated by API Gateway, we refer to them as *gateway responses*. This distinguishes API Gateway-generated responses from the integration responses. A gateway response mapping template can access `$context` variable values and `$stageVariables` property values, as well as method request parameters, in the form of `method.request.param-position.param-name`. 

For more information about `$context` variables, see [Context variables for data transformations](api-gateway-mapping-template-reference.md#context-variable-reference). For more information about `$stageVariables`, see [Stage variables](api-gateway-mapping-template-reference.md#stagevariables-template-reference). For more information about method request parameters, see [Input variables](api-gateway-mapping-template-reference.md#input-variable-reference).

**Topics**
+ [Setting up gateway responses to customize error responses](#customize-gateway-responses)
+ [Set up a gateway response for a REST API using the API Gateway console](set-up-gateway-response-using-the-console.md)
+ [Set up a gateway response using the API Gateway REST API](set-up-gateway-response-using-the-api.md)
+ [Set up gateway response customization in OpenAPI](set-up-gateway-responses-in-swagger.md)
+ [Gateway response types for API Gateway](supported-gateway-response-types.md)

# Set up a gateway response for a REST API using the API Gateway console
<a name="set-up-gateway-response-using-the-console"></a>

The following example shows how to set up a gateway response for a REST API using the API Gateway console 

**To customize a gateway response using the API Gateway console**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the main navigation pane, choose **Gateway responses**.

1. Choose a response type, and then choose **Edit**. In this walkthrough, we use **Missing authentication token** as an example. 

1. You can change the API Gateway-generated **Status code** to return a different status code that meets your API's requirements. In this example, the customization changes the status code from the default (`403`) to `404` because this error message occurs when a client calls an unsupported or invalid resource that can be thought of as not found.

1. To return custom headers, choose **Add response header** under **Response headers**. For illustration purposes, we add the following custom headers: 

   ```
   Access-Control-Allow-Origin:'a.b.c'
   x-request-id:method.request.header.x-amzn-RequestId
   x-request-path:method.request.path.petId
   x-request-query:method.request.querystring.q
   ```

   In the preceding header mappings, a static domain name (`'a.b.c'`) is mapped to the `Allow-Control-Allow-Origin` header to allow CORS access to the API; the input request header of `x-amzn-RequestId` is mapped to `request-id` in the response; the `petId` path variable of the incoming request is mapped to the `request-path` header in the response; and the `q` query parameter of the original request is mapped to the `request-query` header of the response.

1. Under **Response templates**, keep `application/json` for **Content Type** and enter the following body mapping template in the **Template body** editor:

   ```
   {
        "message":"$context.error.messageString",
        "type": "$context.error.responseType",
        "statusCode": "'404'",
        "stage": "$context.stage",
        "resourcePath": "$context.resourcePath",
        "stageVariables.a": "$stageVariables.a"
   }
   ```

   This example shows how to map `$context` and `$stageVariables` properties to properties of the gateway response body.

1. Choose **Save changes**.

1. Deploy the API to a new or existing stage.

Test your gateway response by calling the following CURL command, assuming the corresponding API method's invoke URL is `https://o81lxisefl.execute-api.us-east-1.amazonaws.com/custErr/pets/{petId}`:

```
curl -v -H 'x-amzn-RequestId:123344566' https://o81lxisefl.execute-api.us-east-1.amazonaws.com/custErr/pets/5/type?q=1
```

Because the extra query string parameter `q=1` isn't compatible with the API, an error is returned from the specified gateway response. You should get a gateway response similar to the following:

```
> GET /custErr/pets/5?q=1 HTTP/1.1
Host: o81lxisefl.execute-api.us-east-1.amazonaws.com
User-Agent: curl/7.51.0
Accept: */*
 
HTTP/1.1 404 Not Found
Content-Type: application/json
Content-Length: 334
Connection: keep-alive
Date: Tue, 02 May 2017 03:15:47 GMT
x-amzn-RequestId: 123344566
Access-Control-Allow-Origin: a.b.c
x-amzn-ErrorType: MissingAuthenticationTokenException
header-1: static
x-request-query: 1
x-request-path: 5
X-Cache: Error from cloudfront
Via: 1.1 441811a054e8d055b893175754efd0c3.cloudfront.net (CloudFront)
X-Amz-Cf-Id: nNDR-fX4csbRoAgtQJ16u0rTDz9FZWT-Mk93KgoxnfzDlTUh3flmzA==
 
{
     "message":"Missing Authentication Token",
     "type": MISSING_AUTHENTICATION_TOKEN,
     "statusCode": '404',
     "stage": custErr,
     "resourcePath": /pets/{petId},
     "stageVariables.a": a
}
```

The preceding example assumes that the API backend is [Pet Store](http://petstore-demo-endpoint.execute-api.com/petstore/pets) and the API has a stage variable, `a`, defined.

# Set up a gateway response using the API Gateway REST API
<a name="set-up-gateway-response-using-the-api"></a>

 Before customizing a gateway response using the API Gateway REST API, you must have already created an API and have obtained its identifier. To retrieve the API identifier, you can follow [restapi:gateway-responses](https://docs.aws.amazon.com/apigateway/latest/api/API_GetGatewayResponses.html) link relation and examine the result. 

**To customize a gateway response using the API Gateway REST API**

1. To overwrite an entire [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) instance, call the [gatewayresponse:put](https://docs.aws.amazon.com/apigateway/latest/api/API_PutGatewayResponse.html) action. Specify a desired [responseType](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseType) in the URL path parameter, and supply in the request payload the [statusCode](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#statusCode), [responseParameters](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseParameters), and [responseTemplates](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseTemplates) mappings.

1. To update part of a `GatewayResponse` instance, call the [gatewayresponse:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateGatewayResponse.html) action. Specify a desired `responseType` in the URL path parameter, and supply in the request payload the individual `GatewayResponse` properties you want—for example, the `responseParameters` or the `responseTemplates` mapping.

# Set up gateway response customization in OpenAPI
<a name="set-up-gateway-responses-in-swagger"></a>

 You can use the `x-amazon-apigateway-gateway-responses` extension at the API root level to customize gateway responses in OpenAPI. The following OpenAPI definition shows an example for customizing the [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) of the `MISSING_AUTHENTICATION_TOKEN` type. 

```
  "x-amazon-apigateway-gateway-responses": {
    "MISSING_AUTHENTICATION_TOKEN": {
      "statusCode": 404,
      "responseParameters": {
        "gatewayresponse.header.x-request-path": "method.input.params.petId",
        "gatewayresponse.header.x-request-query": "method.input.params.q",
        "gatewayresponse.header.Access-Control-Allow-Origin": "'a.b.c'",
        "gatewayresponse.header.x-request-header": "method.input.params.Accept"
      },
      "responseTemplates": {
        "application/json": "{\n     \"message\": $context.error.messageString,\n     \"type\":  \"$context.error.responseType\",\n     \"stage\":  \"$context.stage\",\n     \"resourcePath\":  \"$context.resourcePath\",\n     \"stageVariables.a\":  \"$stageVariables.a\",\n     \"statusCode\": \"'404'\"\n}"
      }
    }
```

In this example, the customization changes the status code from the default (`403`) to `404`. It also adds to the gateway response four header parameters and one body mapping template for the `application/json` media type.

# Gateway response types for API Gateway
<a name="supported-gateway-response-types"></a>

 API Gateway exposes the following gateway responses for customization by API developers. 


| Gateway response type | Default status code | Description | 
| --- | --- | --- | 
| ACCESS\$1DENIED | 403 | The gateway response for authorization failure—for example, when access is denied by a custom or Amazon Cognito authorizer. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| API\$1CONFIGURATION\$1ERROR | 500 | The gateway response for an invalid API configuration—including when an invalid endpoint address is submitted, when base64 decoding fails on binary data when binary support is enacted, or when integration response mapping can't match any template and no default template is configured. If the response type is unspecified, this response defaults to the `DEFAULT_5XX` type. | 
| AUTHORIZER\$1CONFIGURATION\$1ERROR | 500 | The gateway response for failing to connect to a custom or Amazon Cognito authorizer. If the response type is unspecified, this response defaults to the `DEFAULT_5XX` type. | 
| AUTHORIZER\$1FAILURE | 500 | The gateway response when a custom or Amazon Cognito authorizer failed to authenticate the caller. If the response type is unspecified, this response defaults to the `DEFAULT_5XX` type. | 
| BAD\$1REQUEST\$1PARAMETERS | 400 | The gateway response when the request parameter cannot be validated according to an enabled request validator. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| BAD\$1REQUEST\$1BODY | 400 | The gateway response when the request body cannot be validated according to an enabled request validator. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| DEFAULT\$14XX |  Null | The default gateway response for an unspecified response type with the status code of `4XX`. Changing the status code of this fallback gateway response changes the status codes of all other `4XX` responses to the new value. Resetting this status code to null reverts the status codes of all other `4XX` responses to their original values.  [AWS WAF custom responses](https://docs.aws.amazon.com/waf/latest/developerguide/waf-custom-request-response.html) take precedence over custom gateway responses.   | 
| DEFAULT\$15XX | Null | The default gateway response for an unspecified response type with a status code of `5XX`. Changing the status code of this fallback gateway response changes the status codes of all other `5XX` responses to the new value. Resetting this status code to null reverts the status codes of all other `5XX` responses to their original values. | 
| EXPIRED\$1TOKEN | 403 | The gateway response for an AWS authentication token expired error. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| INTEGRATION\$1FAILURE | 504 | The gateway response for an integration failed error. If the response type is unspecified, this response defaults to the `DEFAULT_5XX` type. | 
| INTEGRATION\$1TIMEOUT | 504 | The gateway response for an integration timed out error. If the response type is unspecified, this response defaults to the `DEFAULT_5XX` type. | 
| INVALID\$1API\$1KEY | 403 | The gateway response for an invalid API key submitted for a method requiring an API key. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type.  | 
| INVALID\$1SIGNATURE | 403 | The gateway response for an invalid AWS signature error. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| MISSING\$1AUTHENTICATION\$1TOKEN | 403 | The gateway response for a missing authentication token error, including the cases when the client attempts to invoke an unsupported API method or resource. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| QUOTA\$1EXCEEDED | 429 | The gateway response for the usage plan quota exceeded error. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| REQUEST\$1TOO\$1LARGE | 413 | The gateway response for the request too large error. If the response type is unspecified, this response defaults to: `HTTP content length exceeded 10485760 bytes`. | 
| RESOURCE\$1NOT\$1FOUND | 404 | The gateway response when API Gateway cannot find the specified resource after an API request passes authentication and authorization, except for API key authentication and authorization. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| THROTTLED | 429 | The gateway response when usage plan-, method-, stage-, or account-level throttling limits exceeded. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| UNAUTHORIZED | 401 | The gateway response when the custom or Amazon Cognito authorizer failed to authenticate the caller. | 
| UNSUPPORTED\$1MEDIA\$1TYPE | 415 | The gateway response when a payload is of an unsupported media type, if strict passthrough behavior is enabled. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type. | 
| WAF\$1FILTERED | 403 | The gateway response when a request is blocked by AWS WAF. If the response type is unspecified, this response defaults to the `DEFAULT_4XX` type.  [AWS WAF custom responses](https://docs.aws.amazon.com/waf/latest/developerguide/waf-custom-request-response.html) take precedence over custom gateway responses.   | 

# CORS for REST APIs in API Gateway
<a name="how-to-cors"></a>

[Cross-origin resource sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) is a browser security feature that restricts cross-origin HTTP requests that are initiated from scripts running in the browser. For more information, see [What is CORS?](https://aws.amazon.com/what-is/cross-origin-resource-sharing/).

## Determining whether to enable CORS support
<a name="apigateway-cors-request-types"></a>

A *cross-origin* HTTP request is one that is made to:
+ A different *domain* (for example, from `example.com` to `amazondomains.com`)
+ A different *subdomain* (for example, from `example.com` to `petstore.example.com`)
+ A different *port* (for example, from `example.com` to `example.com:10777`)
+ A different *protocol* (for example, from `https://example.com` to `http://example.com`)

 If you cannot access your API and receive an error message that contains `Cross-Origin Request Blocked`, you might need to enable CORS.

Cross-origin HTTP requests can be divided into two types: *simple* requests and *non-simple* requests.

## Enabling CORS for a simple request
<a name="apigateway-cors-simple-request"></a>

An HTTP request is *simple* if all of the following conditions are true:
+ It is issued against an API resource that allows only `GET`, `HEAD`, and `POST` requests.
+ If it is a `POST` method request, it must include an `Origin` header.
+ The request payload content type is `text/plain`, `multipart/form-data`, or `application/x-www-form-urlencoded`.
+ The request does not contain custom headers.
+ Any additional requirements that are listed in the [Mozilla CORS documentation for simple requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests).

For simple cross-origin `POST` method requests, the response from your resource needs to include the header `Access-Control-Allow-Origin: '*'` or `Access-Control-Allow-Origin:'origin'`.

All other cross-origin HTTP requests are *non-simple* requests.

## Enabling CORS for a non-simple request
<a name="apigateway-enable-cors-non-simple"></a>

If your API's resources receive non-simple requests, you must enable additional CORS support depending on your integration type.

### Enabling CORS for non-proxy integrations
<a name="apigateway-enable-cors-mock"></a>

For these integrations, the [CORS protocol](https://fetch.spec.whatwg.org/#http-cors-protocol) requires the browser to send a preflight request to the server and wait for approval (or a request for credentials) from the server before sending the actual request. You must configure your API to send an appropriate response to the preflight request. 

 To create a preflight response: 

1. Create an `OPTIONS` method with a mock integration.

1. Add the following response headers to the 200 method response:
   + `Access-Control-Allow-Headers`
   + `Access-Control-Allow-Methods`
   + `Access-Control-Allow-Origin`

1. Set the integration passthrough behavior to `NEVER`. In this case, the method request of an unmapped content type will be rejected with an HTTP 415 Unsupported Media Type response. For more information, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md).

1. Enter values for the response headers. To allow all origins, all methods, and common headers, use the following header values:
   + `Access-Control-Allow-Headers: 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'`
   + `Access-Control-Allow-Methods: 'DELETE,GET,HEAD,OPTIONS,PUT,POST,PATCH'`
   + `Access-Control-Allow-Origin: '*'`

After creating the preflight request, you must return the `Access-Control-Allow-Origin: '*'` or `Access-Control-Allow-Origin:'origin'` header for all CORS-enabled methods for at least all 200 responses.

### Enabling CORS for non-proxy integrations using the AWS Management Console
<a name="apigateway-enable-cors-mock-console"></a>

You can use the AWS Management Console to enable CORS. API Gateway creates an `OPTIONS` method and adds the `Access-Control-Allow-Origin` header to your existing method integration responses. This doesn’t always work, and sometimes you need to manually modify the integration response to return the `Access-Control-Allow-Origin` header for all CORS-enabled methods for at least all 200 responses.

If you have binary media types set to `*/*` for your API, when API Gateway creates an `OPTIONS` method, change the `contentHandling` to `CONVERT_TO_TEXT`.

The following [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration.html) command changes the `contentHandling` to `CONVERT_TO_TEXT` for an integration request: 

```
aws apigateway update-integration \
  --rest-api-id abc123 \
  --resource-id aaa111 \
  --http-method OPTIONS \
  --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
```

The following [update-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration-response.html) command changes the `contentHandling` to `CONVERT_TO_TEXT` for an integration response:

```
aws apigateway update-integration-response \
  --rest-api-id abc123 \
  --resource-id aaa111 \
  --http-method OPTIONS \
  --status-code 200 \
  --patch-operations op='replace',path='/contentHandling',value='CONVERT_TO_TEXT'
```

## Enabling CORS support for proxy integrations
<a name="apigateway-enable-cors-proxy"></a>

For a Lambda proxy integration or HTTP proxy integration, your backend is responsible for returning the `Access-Control-Allow-Origin`, `Access-Control-Allow-Methods`, and `Access-Control-Allow-Headers` headers, because a proxy integration doesn't return an integration response. 

The following example Lambda functions return the required CORS headers:

------
#### [ Node.js ]

```
export const handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Headers" : "Content-Type",
            "Access-Control-Allow-Origin": "https://www.example.com",
            "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
        },
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
```

------
#### [ Python 3 ]

```
import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Origin': 'https://www.example.com',
            'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
        },
        'body': json.dumps('Hello from Lambda!')
    }
```

------

**Topics**
+ [Determining whether to enable CORS support](#apigateway-cors-request-types)
+ [Enabling CORS for a simple request](#apigateway-cors-simple-request)
+ [Enabling CORS for a non-simple request](#apigateway-enable-cors-non-simple)
+ [Enabling CORS support for proxy integrations](#apigateway-enable-cors-proxy)
+ [Enable CORS on a resource using the API Gateway console](how-to-cors-console.md)
+ [Enable CORS on a resource using the API Gateway import API](enable-cors-for-resource-using-swagger-importer-tool.md)
+ [Test CORS for an API Gateway API](apigateway-test-cors.md)

# Enable CORS on a resource using the API Gateway console
<a name="how-to-cors-console"></a>

You can use the API Gateway console to enable CORS support for one or all methods on a REST API resource that you have created. After you enable COR support, set the integration passthrough behavior to `NEVER`. In this case, the method request of an unmapped content type will be rejected with an HTTP 415 Unsupported Media Type response. For more information, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md)

**Important**  
Resources can contain child resources. Enabling CORS support for a resource and its methods does not recursively enable it for child resources and their methods.

**To enable CORS support on a REST API resource**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose an API. 

1. Choose a resource under **Resources**.

1. In the **Resource details** section, choose **Enable CORS**.

      
![\[In the Resources pane, choose Enable CORS.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/amazon-api-gateway-new-console-enable-cors.png)

1.  In the **Enable CORS** box, do the following: 

   1. (Optional) If you created a custom gateway response and want to enable CORS support for a response, select a gateway response.

   1. Select each method to enable CORS support. The `OPTION` method must have CORS enabled. 

      If you enable CORS support for an `ANY` method, CORS is enabled for all methods.

   1.  In the **Access-Control-Allow-Headers** input field, enter a static string of a comma-separated list of headers that the client must submit in the actual request of the resource. Use the console-provided header list of `'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'` or specify your own headers. 

   1. Use the console-provided value of `'*'` as the **Access-Control-Allow-Origin** header value to allow access requests from all origins, or specify an origin to be permitted to access the resource. 

   1. Choose **Save**.  
![\[Choose which headers are allowed\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/amazon-api-gateway-new-console-enable-cors-resources.png)
**Important**  
 When applying the above instructions to the `ANY` method in a proxy integration, any applicable CORS headers will not be set. Instead, your backend must return the applicable CORS headers, such as `Access-Control-Allow-Origin`. 

After CORS is enabled on the `GET` method, an `OPTIONS` method is added to the resource, if it is not already there. The `200` response of the `OPTIONS` method is automatically configured to return the three `Access-Control-Allow-*` headers to fulfill preflight handshakes. In addition, the actual (`GET`) method is also configured by default to return the `Access-Control-Allow-Origin` header in its 200 response as well. For other types of responses, you will need to manually configure them to return `Access-Control-Allow-Origin'` header with '\$1' or specific origins, if you do not want to return the `Cross-origin access` error.

After you enable CORS support on your resource, you must deploy or redeploy the API for the new settings to take effect. For more information, see [Create a deployment](set-up-deployments.md#create-deployment).

**Note**  
If you cannot enable CORS support on your resource after following the procedure, we recommend that you compare your CORS configuration to the example API `/pets` resource. To learn how to create the example API, see [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md).

# Enable CORS on a resource using the API Gateway import API
<a name="enable-cors-for-resource-using-swagger-importer-tool"></a>

If you are using the [API Gateway Import API](api-gateway-import-api.md), you can set up CORS support using an OpenAPI file. You must first define an `OPTIONS` method in your resource that returns the required headers.

**Note**  
Web browsers expect Access-Control-Allow-Headers, and Access-Control-Allow-Origin headers to be set up in each API method that accepts CORS requests. In addition, some browsers first make an HTTP request to an `OPTIONS` method in the same resource, and then expect to receive the same headers.

## Example `Options` method
<a name="enable-cors-for-resource-using-swagger-importer-tool-options"></a>

The following example creates an `OPTIONS` method for a mock integration.

------
#### [ OpenAPI 3.0 ]

```
/users:
  options:
    summary: CORS support
    description: |
      Enable CORS by returning correct headers
    tags:
    - CORS
    responses:
      200:
        description: Default response for CORS method
        headers:
          Access-Control-Allow-Origin:
            schema:
              type: "string"
          Access-Control-Allow-Methods:
            schema:
              type: "string"
          Access-Control-Allow-Headers:
            schema:
              type: "string"
        content: {}
    x-amazon-apigateway-integration:
      type: mock
      requestTemplates:
        application/json: "{\"statusCode\": 200}"
      passthroughBehavior: "never"
      responses:
        default:
          statusCode: "200"
          responseParameters:
            method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
            method.response.header.Access-Control-Allow-Methods: "'*'"
            method.response.header.Access-Control-Allow-Origin: "'*'"
```

------
#### [ OpenAPI 2.0 ]

```
/users: 
   options:
      summary: CORS support
      description: |
        Enable CORS by returning correct headers
      consumes:
        - "application/json"
      produces:
        - "application/json"
      tags:
        - CORS
      x-amazon-apigateway-integration:
        type: mock
        requestTemplates: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        responses:
          "default":
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Methods : "'*'"
              method.response.header.Access-Control-Allow-Origin : "'*'"
      responses:
        200:
          description: Default response for CORS method
          headers:
            Access-Control-Allow-Headers:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Origin:
              type: "string"
```

------

Once you have configured the `OPTIONS` method for your resource, you can add the required headers to the other methods in the same resource that need to accept CORS requests.

1. Declare the **Access-Control-Allow-Origin** and **Headers** to the response types.

------
#### [ OpenAPI 3.0 ]

   ```
       responses:
         200:
           description: Default response for CORS method
           headers:
             Access-Control-Allow-Origin:
               schema:
                 type: "string"
             Access-Control-Allow-Methods:
               schema:
                 type: "string"
             Access-Control-Allow-Headers:
               schema:
                 type: "string"
           content: {}
   ```

------
#### [ OpenAPI 2.0 ]

   ```
       responses:
           200:
             description: Default response for CORS method
             headers:
               Access-Control-Allow-Headers:
                 type: "string"
               Access-Control-Allow-Methods:
                 type: "string"
               Access-Control-Allow-Origin:
                 type: "string"
   ```

------

1. In the `x-amazon-apigateway-integration` tag, set up the mapping for those headers to your static values:

------
#### [ OpenAPI 3.0 ]

   ```
       responses:
           default:
             statusCode: "200"
             responseParameters:
               method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
               method.response.header.Access-Control-Allow-Methods: "'*'"
               method.response.header.Access-Control-Allow-Origin: "'*'"
             responseTemplates:
               application/json: |
                 {}
   ```

------
#### [ OpenAPI 2.0 ]

   ```
       responses:
             "default":
               statusCode: "200"
               responseParameters:
                 method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
                 method.response.header.Access-Control-Allow-Methods : "'*'"
                 method.response.header.Access-Control-Allow-Origin : "'*'"
   ```

------

## Example API
<a name="enable-cors-for-resource-using-swagger-importer-tool-complete-example"></a>

The following example creates a complete API with an `OPTIONS` method and a `GET` method with an `HTTP` integration.

------
#### [ OpenAPI 3.0 ]

```
openapi: "3.0.1"
info:
  title: "cors-api"
  description: "cors-api"
  version: "2024-01-16T18:36:01Z"
servers:
- url: "/{basePath}"
  variables:
    basePath:
      default: "/test"
paths:
  /:
    get:
      operationId: "GetPet"
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: "string"
          content: {}
      x-amazon-apigateway-integration:
        httpMethod: "GET"
        uri: "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets"
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Origin: "'*'"
        passthroughBehavior: "never"
        type: "http"
    options:
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: "string"
            Access-Control-Allow-Methods:
              schema:
                type: "string"
            Access-Control-Allow-Headers:
              schema:
                type: "string"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Empty"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        type: "mock"
components:
  schemas:
    Empty:
      type: "object"
```

------
#### [  OpenAPI 2.0  ]

```
swagger: "2.0"
info:
  description: "cors-api"
  version: "2024-01-16T18:36:01Z"
  title: "cors-api"
basePath: "/test"
schemes:
- "https"
paths:
  /:
    get:
      operationId: "GetPet"
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
      x-amazon-apigateway-integration:
        httpMethod: "GET"
        uri: "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets"
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Origin: "'*'"
        passthroughBehavior: "never"
        type: "http"
    options:
      consumes:
      - "application/json"
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Headers:
              type: "string"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        passthroughBehavior: "never"
        type: "mock"
definitions:
  Empty:
    type: "object"
```

------

# Test CORS for an API Gateway API
<a name="apigateway-test-cors"></a>

You can test your API's CORS configuration by invoking your API, and checking the CORS headers in the response. The following `curl` command sends an OPTIONS request to a deployed API. 

```
curl -v -X OPTIONS https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}
```

```
< HTTP/1.1 200 OK
< Date: Tue, 19 May 2020 00:55:22 GMT
< Content-Type: application/json
< Content-Length: 0
< Connection: keep-alive
< x-amzn-RequestId: a1b2c3d4-5678-90ab-cdef-abc123
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token
< x-amz-apigw-id: Abcd=
< Access-Control-Allow-Methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
```

The `Access-Control-Allow-Origin`, `Access-Control-Allow-Headers`, and `Access-Control-Allow-Methods` headers in the response show that the API supports CORS. For more information, see [CORS for REST APIs in API Gateway](how-to-cors.md).

# Binary media types for REST APIs in API Gateway
<a name="api-gateway-payload-encodings"></a>

In API Gateway, the API request and response have a text or binary payload. A text payload is a `UTF-8`-encoded JSON string. A binary payload is anything other than a text payload. The binary payload can be, for example, a JPEG file, a GZip file, or an XML file. The API configuration required to support binary media depends on whether your API uses proxy or non-proxy integrations. 

If you use a proxy integration with payload response streaming, you don't need to configure your binary media types. For more information, see [Stream the integration response for your proxy integrations in API Gateway](response-transfer-mode.md).

## AWS Lambda proxy integrations
<a name="api-gateway-payload-encodings-proxy"></a>

To handle binary payloads for AWS Lambda proxy integrations, you must base64-encode your function's response. You must also configure the [binaryMediaTypes](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apigw-Type-RestApi-binaryMediaTypes) for your API. Your API's `binaryMediaTypes` configuration is a list of content types that your API treats as binary data. Example binary media types include `image/png` or `application/octet-stream`. You can use the wildcard character (`*`) to cover multiple media types.

API Gateway uses the first `Accept` header from clients to determine if a response should return binary media. To return binary media when you can't control the order of `Accept` header values, such as requests from a browser, set your API's binary media types to `*/*`.

For example code, see [Return binary media from a Lambda proxy integration in API Gateway](lambda-proxy-binary-media.md).

If you use a Lambda proxy integration with payload response streaming, you don't need to configure your binary media types. For more information, see [Set up a Lambda proxy integration with payload response streaming in API Gateway](response-transfer-mode-lambda.md).

## Non-proxy integrations
<a name="api-gateway-payload-encodings-non-proxy"></a>

To handle binary payloads for non-proxy integrations, you add the media types to the [binaryMediaTypes](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#apigw-Type-RestApi-binaryMediaTypes) list of the `RestApi` resource. Your API's `binaryMediaTypes` configuration is a list of content types that your API treats as binary data. Alternatively, you can set the [contentHandling](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html#contentHandling) properties on the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) and the [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) resources. The `contentHandling` value can be `CONVERT_TO_BINARY`, `CONVERT_TO_TEXT`, or undefined. 

**Note**  
For `MOCK` or private integrations, setting the `contentHandling` properties isn't supported in the AWS Management Console. You must use the AWS CLI, CloudFormation, or an SDK to set the `contentHandling` properties.

Depending on the `contentHandling` value, and whether the `Content-Type` header of the response or the `Accept` header of the incoming request matches an entry in the `binaryMediaTypes` list, API Gateway can encode the raw binary bytes as a base64-encoded string, decode a base64-encoded string back to its raw bytes, or pass the body through without modification. 

You must configure the API as follows to support binary payloads for your API in API Gateway: 
+ Add the desired binary media types to the `binaryMediaTypes` list on the [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource. If this property and the `contentHandling` property are not defined, the payloads are handled as UTF-8 encoded JSON strings.
+ Address the `contentHandling` property of the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource. 
  + To have the request payload converted from a base64-encoded string to its binary blob, set the property to `CONVERT_TO_BINARY`.
  + To have the request payload converted from a binary blob to a base64-encoded string, set the property to `CONVERT_TO_TEXT`.
  + To pass the payload through without modification, leave the property undefined. To pass a binary payload through without modification, you must also ensure that the `Content-Type` matches one of the `binaryMediaTypes` entries, and that [passthrough behaviors](integration-passthrough-behaviors.md) are enabled for the API. 
+ Set the `contentHandling` property of the [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) resource. The `contentHandling` property, `Accept` header in client requests, and your API's `binaryMediaTypes` combined determine how API Gateway handles content type conversions. For details, see [Content type conversions in API Gateway](api-gateway-payload-encodings-workflow.md). 

**Important**  
When a request contains multiple media types in its `Accept` header, API Gateway honors only the first `Accept` media type. If you can't control the order of the `Accept` media types and the media type of your binary content isn't the first in the list, add the first `Accept` media type in the `binaryMediaTypes` list of your API. API Gateway handles all content types in this list as binary.   
For example, to send a JPEG file using an `<img>` element in a browser, the browser might send `Accept:image/webp,image/*,*/*;q=0.8` in a request. By adding `image/webp` to the `binaryMediaTypes` list, the endpoint receives the JPEG file as binary. 

For detailed information about how API Gateway handles the text and binary payloads, see [Content type conversions in API Gateway](api-gateway-payload-encodings-workflow.md).

# Content type conversions in API Gateway
<a name="api-gateway-payload-encodings-workflow"></a>

 The combination of your API's `binaryMediaTypes`, the headers in client requests, and the integration `contentHandling` property determine how API Gateway encodes payloads.

The following table shows how API Gateway converts the request payload for specific configurations of a request's `Content-Type` header, the `binaryMediaTypes` list of a [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource, and the `contentHandling` property value of the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) resource.


| Method request payload | Request `Content-Type` header | `binaryMediaTypes` | `contentHandling` | Integration request payload | 
| --- | --- | --- | --- | --- | 
| Text data | Any data type | Undefined | Undefined | UTF8-encoded string | 
| Text data | Any data type | Undefined | CONVERT\$1TO\$1BINARY | Base64-decoded binary blob | 
| Text data | Any data type | Undefined | CONVERT\$1TO\$1TEXT | UTF8-encoded string | 
| Text data | A text data type | Set with matching media types | Undefined | Text data | 
| Text data | A text data type | Set with matching media types | CONVERT\$1TO\$1BINARY | Base64-decoded binary blob | 
| Text data | A text data type | Set with matching media types | CONVERT\$1TO\$1TEXT | Text data | 
| Binary data | A binary data type | Set with matching media types | Undefined | Binary data | 
| Binary data | A binary data type | Set with matching media types | CONVERT\$1TO\$1BINARY | Binary data | 
| Binary data | A binary data type | Set with matching media types | CONVERT\$1TO\$1TEXT | Base64-encoded string | 

The following table shows how API Gateway converts the response payload for specific configurations of a request's `Accept` header, the `binaryMediaTypes` list of a [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource, and the `contentHandling` property value of the [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) resource.

**Important**  
 When a request contains multiple media types in its `Accept` header, API Gateway honors only the first `Accept` media type. If you can't control the order of the `Accept` media types and the media type of your binary content isn't the first in the list, add the first `Accept` media type in the `binaryMediaTypes` list of your API. API Gateway handles all content types in this list as binary.   
For example, to send a JPEG file using an `<img>` element in a browser, the browser might send `Accept:image/webp,image/*,*/*;q=0.8` in a request. By adding `image/webp` to the `binaryMediaTypes` list, the endpoint receives the JPEG file as binary. 


| Integration response payload | Request `Accept` header | `binaryMediaTypes` | `contentHandling` | Method response payload | 
| --- | --- | --- | --- | --- | 
| Text or binary data | A text type | Undefined | Undefined | UTF8-encoded string | 
| Text or binary data | A text type | Undefined | CONVERT\$1TO\$1BINARY | Base64-decoded blob | 
| Text or binary data | A text type | Undefined | CONVERT\$1TO\$1TEXT | UTF8-encoded string | 
| Text data | A text type | Set with matching media types | Undefined | Text data | 
| Text data | A text type | Set with matching media types | CONVERT\$1TO\$1BINARY | Base64-decoded blob | 
| Text data | A text type | Set with matching media types | CONVERT\$1TO\$1TEXT | UTF8-encoded string | 
| Text data | A binary type | Set with matching media types | Undefined | Base64-decoded blob | 
| Text data | A binary type | Set with matching media types | CONVERT\$1TO\$1BINARY | Base64-decoded blob | 
| Text data | A binary type | Set with matching media types | CONVERT\$1TO\$1TEXT | UTF8-encoded string | 
| Binary data | A text type | Set with matching media types | Undefined | Base64-encoded string | 
| Binary data | A text type | Set with matching media types | CONVERT\$1TO\$1BINARY | Binary data | 
| Binary data | A text type | Set with matching media types | CONVERT\$1TO\$1TEXT | Base64-encoded string | 
| Binary data | A binary type | Set with matching media types | Undefined | Binary data | 
| Binary data | A binary type | Set with matching media types | CONVERT\$1TO\$1BINARY | Binary data | 
| Binary data | A binary type | Set with matching media types | CONVERT\$1TO\$1TEXT | Base64-encoded string | 

When converting a text payload to a binary blob, API Gateway assumes that the text data is a base64-encoded string and outputs the binary data as a base64-decoded blob. If the conversion fails, it returns a `500` response, which indicates an API configuration error. You don't provide a mapping template for such a conversion, although you must enable the [passthrough behaviors](integration-passthrough-behaviors.md) on the API.

When converting a binary payload to a text string, API Gateway always applies a base64 encoding on the binary data. You can define a mapping template for such a payload, but can only access the base64-encoded string in the mapping template through `$input.body`, as shown in the following excerpt of an example mapping template. 

```
{   
    "data": "$input.body"
}
```

To have the binary payload passed through without modification, you must enable the [passthrough behaviors](integration-passthrough-behaviors.md) on the API. 

# Enabling binary support using the API Gateway console
<a name="api-gateway-payload-encodings-configure-with-console"></a>

The section explains how to enable binary support using the API Gateway console. As an example, we use an API that is integrated with Amazon S3. We focus on the tasks to set the supported media types and to specify how the payload should be handled. For detailed information on how to create an API integrated with Amazon S3, see [Tutorial: Create a REST API as an Amazon S3 proxy](integrating-api-with-aws-services-s3.md).

**To enable binary support by using the API Gateway console**

1. Set binary media types for the API:

   1. Create a new API or choose an existing API. For this example, we name the API `FileMan`.

   1. Under the selected API in the primary navigation panel, choose **API settings**.

   1. In the **API settings** pane, choose **Manage media types** in the **Binary Media Types** section.

   1. Choose **Add binary media type**.

   1. Enter a required media type, for example, **image/png**, in the input text field. If needed, repeat this step to add more media types. To support all binary media types, specify `*/*`.

   1. Choose **Save changes**.

1. Set how message payloads are handled for the API method:

   1. Create a new or choose an existing resource in the API. For this example, we use the `/{folder}/{item}` resource.

   1. Create a new or choose an existing method on the resource. As an example, we use the `GET /{folder}/{item}` method integrated with the `Object GET` action in Amazon S3. 

   1. For **Content handling**, choose an option. 

         
![\[Set up the GET method in the API Gateway console.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/binary-support-content-handling-on-method-new-console.png)

      Choose **Passthrough** if you don't want to convert the body when the client and backend accepts the same binary format. Choose **Convert to text** to convert the binary body to a base64-encoded string when, for example, the backend requires that a binary request payload is passed in as a JSON property. And choose **Convert to binary** when the client submits a base64-encoded string and the backend requires the original binary format, or when the endpoint returns a base64-encoded string and the client accepts only the binary output.

   1. For **Request body passthrough**, choose **When there are no templates defined (recommended)** to enable the passthrough behavior on the request body.

      You could also choose **Never**. This means that the API will reject data with content-types that do not have a mapping template.

   1. Preserve the incoming request's `Accept` header in the integration request. You should do this if you've set `contentHandling` to `passthrough` and want to override that setting at runtime.

         
![\[Keep the Accept header in the integration request.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/binary-support-preserve-incoming-accept-header-new-console.png)

   1. For conversion to text, define a mapping template to put the base64-encoded binary data into the required format.

      An example of a mapping template to convert to text is the following:

      ```
      {
        "operation": "thumbnail",
        "base64Image": "$input.body"
      }
      ```

      The format of this mapping template depends on the endpoint requirements of the input.

   1. Choose **Save**.

# Enabling binary support using the API Gateway REST API
<a name="api-gateway-payload-encodings-configure-with-control-service-api"></a>

The following tasks show how to enable binary support using the API Gateway REST API calls.

**Topics**
+ [Add and update supported binary media types to an API](#api-gateway-payload-encodings-setup-with-api-set-encodings-map)
+ [Configure request payload conversions](#api-gateway-payload-encodings-setup-with-api-set-integration-request-encoding)
+ [Configure response payload conversions](#api-gateway-payload-encodings-setup-with-api-set-integration-response-encoding)
+ [Convert binary data to text data](#api-gateway-payload-encodings-convert-binary-to-string)
+ [Convert text data to a binary payload](#api-gateway-payload-encodings-convert-string-to-binary)
+ [Pass through a binary payload](#api-gateway-payload-encodings-pass-binary-as-is)

## Add and update supported binary media types to an API
<a name="api-gateway-payload-encodings-setup-with-api-set-encodings-map"></a>

To enable API Gateway to support a new binary media type, you must add the binary media type to the `binaryMediaTypes` list of the `RestApi` resource. For example, to have API Gateway handle JPEG images, submit a `PATCH` request to the `RestApi` resource: 

```
PATCH /restapis/<restapi_id>

{
  "patchOperations" : [ {
    "op" : "add",
    "path" : "/binaryMediaTypes/image~1jpeg"
  } 
 ]
}
```

The MIME type specification of `image/jpeg` that is part of the `path` property value is escaped as `image~1jpeg`.

To update the supported binary media types, replace or remove the media type from the `binaryMediaTypes` list of the `RestApi` resource. For example, to change binary support from JPEG files to raw bytes, submit a `PATCH` request to the `RestApi` resource, as follows: 

```
PATCH /restapis/<restapi_id>

{
  "patchOperations" : [{
    "op" : "replace",
    "path" : "/binaryMediaTypes/image~1jpeg",
    "value" : "application/octet-stream"
  },
  {
    "op" : "remove",
    "path" : "/binaryMediaTypes/image~1jpeg"
  }]
}
```

## Configure request payload conversions
<a name="api-gateway-payload-encodings-setup-with-api-set-integration-request-encoding"></a>

If the endpoint requires a binary input, set the `contentHandling` property of the `Integration` resource to `CONVERT_TO_BINARY`. To do so, submit a `PATCH` request, as follows: 

```
PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration

{
  "patchOperations" : [ {
    "op" : "replace",
    "path" : "/contentHandling",
    "value" : "CONVERT_TO_BINARY"
  }]
}
```

## Configure response payload conversions
<a name="api-gateway-payload-encodings-setup-with-api-set-integration-response-encoding"></a>

If the client accepts the result as a binary blob instead of a base64-encoded payload returned from the endpoint, set the `contentHandling` property of the `IntegrationResponse` resource to `CONVERT_TO_BINARY`. To do this, submit a `PATCH` request, as follows:

```
PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration/responses/<status_code>

{
  "patchOperations" : [ {
    "op" : "replace",
    "path" : "/contentHandling",
    "value" : "CONVERT_TO_BINARY"
  }]
}
```

## Convert binary data to text data
<a name="api-gateway-payload-encodings-convert-binary-to-string"></a>

To send binary data as a JSON property of the input to AWS Lambda or Kinesis through API Gateway, do the following: 

1. Enable the binary payload support of the API by adding the new binary media type of `application/octet-stream` to the API's `binaryMediaTypes` list. 

   ```
   PATCH /restapis/<restapi_id>
   
   {
     "patchOperations" : [ {
       "op" : "add",
       "path" : "/binaryMediaTypes/application~1octet-stream"
     } 
    ]
   }
   ```

1. Set `CONVERT_TO_TEXT` on the `contentHandling` property of the `Integration` resource and provide a mapping template to assign the base64-encoded string of the binary data to a JSON property. In the following example, the JSON property is `body` and `$input.body` holds the base64-encoded string.

   ```
   PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration
   
   {
     "patchOperations" : [
       {
         "op" : "replace",
         "path" : "/contentHandling",
         "value" : "CONVERT_TO_TEXT"
       },
       {
         "op" : "add",
         "path" : "/requestTemplates/application~1octet-stream",
         "value" : "{\"body\": \"$input.body\"}"
       }
     ]
   }
   ```

## Convert text data to a binary payload
<a name="api-gateway-payload-encodings-convert-string-to-binary"></a>

Suppose a Lambda function returns an image file as a base64-encoded string. To pass this binary output to the client through API Gateway, do the following: 

1. Update the API's `binaryMediaTypes` list by adding the binary media type of `application/octet-stream`, if it is not already in the list. 

   ```
   PATCH /restapis/<restapi_id>
   
   {
     "patchOperations" : [ {
       "op" : "add",
       "path" : "/binaryMediaTypes/application~1octet-stream",
     }]
   }
   ```

1.  Set the `contentHandling` property on the `Integration` resource to `CONVERT_TO_BINARY`. Do not define a mapping template. If you don't define a mapping template, API Gateway invokes the passthrough template to return the base64-decoded binary blob as the image file to the client. 

   ```
   PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration/responses/<status_code>
   
   {
     "patchOperations" : [
       {
         "op" : "replace",
         "path" : "/contentHandling",
         "value" : "CONVERT_TO_BINARY"
       }
     ]
   }
   ```

## Pass through a binary payload
<a name="api-gateway-payload-encodings-pass-binary-as-is"></a>

 To store an image in an Amazon S3 bucket using API Gateway, do the following: 

1. Update the API's `binaryMediaTypes` list by adding the binary media type of `application/octet-stream`, if it isn't already in the list. 

   ```
   PATCH /restapis/<restapi_id>
   
   {
     "patchOperations" : [ {
       "op" : "add",
       "path" : "/binaryMediaTypes/application~1octet-stream"
     }
    ]
   }
   ```

1. On the `contentHandling` property of the `Integration` resource, set `CONVERT_TO_BINARY`. Set `WHEN_NO_MATCH` as the `passthroughBehavior` property value without defining a mapping template. This enables API Gateway to invoke the passthrough template. 

   ```
   PATCH /restapis/<restapi_id>/resources/<resource_id>/methods/<http_method>/integration
   
   {
     "patchOperations" : [
       {
         "op" : "replace",
         "path" : "/contentHandling",
         "value" : "CONVERT_TO_BINARY"
       },
       {
         "op" : "replace",
         "path" : "/passthroughBehaviors",
         "value" : "WHEN_NO_MATCH"
       }
     ]
   }
   ```

# Import and export content encodings for API Gateway
<a name="api-gateway-payload-encodings-import-and-export"></a>

 To import the `binaryMediaTypes` list on a [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html), use the following API Gateway extension to the API's OpenAPI definition file. The extension is also used to export the API settings.
+ [x-amazon-apigateway-binary-media-types property](api-gateway-swagger-extensions-binary-media-types.md)

To import and export the `contentHandling` property value on an `Integration` or `IntegrationResponse` resource, use the following API Gateway extensions to the OpenAPI definitions:
+ [x-amazon-apigateway-integration object](api-gateway-swagger-extensions-integration.md)
+ [x-amazon-apigateway-integration.response object](api-gateway-swagger-extensions-integration-response.md)

# Return binary media from a Lambda proxy integration in API Gateway
<a name="lambda-proxy-binary-media"></a>

To return binary media from an [AWS Lambda proxy integration](set-up-lambda-proxy-integrations.md), base64 encode the response from your Lambda function. You must also [configure your API's binary media types](api-gateway-payload-encodings-configure-with-console.md). When you configure your API's binary media types, your API treats that content type as binary data. The payload size limit is 10 MB.

**Note**  
To use a web browser to invoke an API with this example integration, set your API's binary media types to `*/*`. API Gateway uses the first `Accept` header from clients to determine if a response should return binary media. To return binary media when you can't control the order of `Accept` header values, such as requests from a browser, set your API's binary media types to `*/*` (for all content types).

The following example Lambda function can return a binary image from Amazon S3 or text to clients. The function's response includes a `Content-Type` header to indicate to the client the type of data that it returns. The function conditionally sets the `isBase64Encoded` property in its response, depending on the type of data that it returns.

------
#### [ Node.js ]

```
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3"

const client = new S3Client({region: 'us-east-2'});

export const handler = async (event) => {

  var randomint = function(max) {
    return Math.floor(Math.random() * max);
  }
  var number = randomint(2);
  if (number == 1){ 
    const input = {
      "Bucket" : "bucket-name",
      "Key" : "image.png"
      }
    try {
      const command = new GetObjectCommand(input)
      const response = await client.send(command);
      var str = await response.Body.transformToByteArray();
    } catch (err) {
      console.error(err);
    }
    const base64body = Buffer.from(str).toString('base64');
    return {
      'headers': { "Content-Type": "image/png" },
      'statusCode': 200,
      'body': base64body,
      'isBase64Encoded': true
      }
    } else {
        return {
        'headers': { "Content-Type": "text/html" },
        'statusCode': 200,
        'body': "<h1>This is text</h1>",
        }
    }
}
```

------
#### [ Python ]

```
import base64
import boto3
import json
import random

s3 = boto3.client('s3')

def lambda_handler(event, context):
    number = random.randint(0,1)
    if number == 1:
        response = s3.get_object(
            Bucket='bucket-name',
            Key='image.png',
        )
        image = response['Body'].read()
        return {
            'headers': { "Content-Type": "image/png" },
            'statusCode': 200,
            'body': base64.b64encode(image).decode('utf-8'),
            'isBase64Encoded': True
        }
    else:
        return {
            'headers': { "Content-type": "text/html" },
            'statusCode': 200,
            'body': "<h1>This is text</h1>",
        }
```

------

To learn more about binary media types, see [Binary media types for REST APIs in API Gateway](api-gateway-payload-encodings.md).

# Access binary files in Amazon S3 through an API Gateway API
<a name="api-gateway-content-encodings-examples-image-s3"></a>

The following examples show the OpenAPI file used to access images in Amazon S3, how to download an image from Amazon S3, and how to upload an image to Amazon S3. 

**Topics**
+ [OpenAPI file of a sample API to access images in Amazon S3](#api-gateway-content-encodings-example-image-s3-swagger-file)
+ [Download an image from Amazon S3](#api-gateway-content-encodings-example-download-image-from-s3)
+ [Upload an image to Amazon S3](#api-gateway-content-encodings-example-upload-image-to-s3)

## OpenAPI file of a sample API to access images in Amazon S3
<a name="api-gateway-content-encodings-example-image-s3-swagger-file"></a>

The following OpenAPI file shows a sample API that illustrates downloading an image file from Amazon S3 and uploading an image file to Amazon S3. This API exposes the `GET /s3?key={file-name}` and `PUT /s3?key={file-name}` methods for downloading and uploading a specified image file. The `GET` method returns the image file as a base64-encoded string as part of a JSON output, following the supplied mapping template, in a 200 OK response. The `PUT` method takes a raw binary blob as input and returns a 200 OK response with an empty payload.

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-10-21T17:26:28Z",
      "title": "ApiName"
   },
   "paths": {
      "/s3": {
         "get": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200"
                  }
               },
               "requestParameters": {
                  "integration.request.path.key": "method.request.querystring.key"
               },
               "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "GET",
               "type": "aws"
            }
         },
         "put": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     },
                     "application/octet-stream": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200"
                  }
               },
               "requestParameters": {
                  "integration.request.path.key": "method.request.querystring.key"
               },
               "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "PUT",
               "type": "aws",
               "contentHandling": "CONVERT_TO_BINARY"
            }
         }
      }
   },
   "x-amazon-apigateway-binary-media-types": [
      "application/octet-stream",
      "image/jpeg"
   ],
   "servers": [
      {
         "url": "https://abcdefghi.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/v1"
            }
         }
      }
   ],
   "components": {
      "schemas": {
         "Empty": {
            "type": "object",
            "title": "Empty Schema"
         }
      }
   }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-10-21T17:26:28Z",
    "title": "ApiName"
  },
  "host": "abcdefghi.execute-api.us-east-1.amazonaws.com",
  "basePath": "/v1",
  "schemes": [
    "https"
  ],
  "paths": {
    "/s3": {
      "get": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200"            }
          },
          "requestParameters": {
            "integration.request.path.key": "method.request.querystring.key"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "GET",
          "type": "aws"
        }
      },
      "put": {
        "produces": [
          "application/json", "application/octet-stream"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200"
            }
          },
          "requestParameters": {
            "integration.request.path.key": "method.request.querystring.key"
          },
          "uri": "arn:aws:apigateway:us-west-2:s3:path/{key}",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "PUT",
          "type": "aws",
          "contentHandling" : "CONVERT_TO_BINARY"
        }
      }
    }
  },
  "x-amazon-apigateway-binary-media-types" : ["application/octet-stream", "image/jpeg"],
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}
```

------

## Download an image from Amazon S3
<a name="api-gateway-content-encodings-example-download-image-from-s3"></a>

To download an image file (`image.jpg`) as a binary blob from Amazon S3:

```
GET /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/octet-stream
```

The successful response looks like this:

```
200 OK HTTP/1.1

[raw bytes]
```

The raw bytes are returned because the `Accept` header is set to a binary media type of `application/octet-stream` and binary support is enabled for the API. 

Alternatively, to download an image file (`image.jpg`) as a base64-encoded string (formatted as a JSON property) from Amazon S3, add a response template to the 200 integration response, as shown in the following bold-faced OpenAPI definition block:

```
        "x-amazon-apigateway-integration": {
          "credentials": "arn:aws:iam::123456789012:role/binarySupportRole",
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "{\n   \"image\": \"$input.body\"\n}"
              }
            }
          },
```

The request to download the image file looks like the following:

```
GET /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json
```

The successful response looks like the following:

```
200 OK HTTP/1.1

{
  "image": "W3JhdyBieXRlc10="
}
```

## Upload an image to Amazon S3
<a name="api-gateway-content-encodings-example-upload-image-to-s3"></a>

To upload an image file (`image.jpg`) as a binary blob to Amazon S3:

```
PUT /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/octet-stream
Accept: application/json

[raw bytes]
```

The successful response looks like the following:

```
200 OK HTTP/1.1        
```

To upload an image file (`image.jpg`) as a base64-encoded string to Amazon S3:

```
PUT /v1/s3?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json

W3JhdyBieXRlc10=
```

The input payload must be a base64-encoded string because the `Content-Type` header value is set to `application/json`. The successful response looks like the following:

```
200 OK HTTP/1.1
```

# Access binary files in Lambda using an API Gateway API
<a name="api-gateway-content-encodings-examples-image-lambda"></a>

The following OpenAPI example demonstrates how to access a binary file in AWS Lambda through an API Gateway API. This API exposes the `GET /lambda?key={file-name}` and the `PUT /lambda?key={file-name}` methods for downloading and uploading a specified image file. The `GET` method returns the image file as a base64-encoded string as part of a JSON output, following the supplied mapping template, in a 200 OK response. The `PUT` method takes a raw binary blob as input and returns a 200 OK response with an empty payload.

You create the Lambda function that your API calls, and it must return a base64-encoded string with the `Content-Type` header of `application/json`. 

**Topics**
+ [OpenAPI file of a sample API to access images in Lambda](#api-gateway-content-encodings-example-image-lambda-swagger-file)
+ [Download an image from Lambda](#api-gateway-content-encodings-example-download-image-from-lambda)
+ [Upload an image to Lambda](#api-gateway-content-encodings-example-upload-image-to-lambda)

## OpenAPI file of a sample API to access images in Lambda
<a name="api-gateway-content-encodings-example-image-lambda-swagger-file"></a>

The following OpenAPI file shows an example API that illustrates downloading an image file from Lambda and uploading an image file to Lambda.

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-10-21T17:26:28Z",
      "title": "ApiName"
   },
   "paths": {
      "/lambda": {
         "get": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
               "type": "AWS",
               "credentials": "arn:aws:iam::123456789012:role/Lambda",
               "httpMethod": "POST",
               "requestTemplates": {
                  "application/json": "{\n   \"imageKey\": \"$input.params('key')\"\n}"
               },
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200",
                     "responseTemplates": {
                        "application/json": "{\n   \"image\": \"$input.body\"\n}"
                     }
                  }
               }
            }
         },
         "put": {
            "parameters": [
               {
                  "name": "key",
                  "in": "query",
                  "required": false,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     },
                     "application/octet-stream": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               },
               "500": {
                  "description": "500 response"
               }
            },
            "x-amazon-apigateway-integration": {
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
               "type": "AWS",
               "credentials": "arn:aws:iam::123456789012:role/Lambda",
               "httpMethod": "POST",
               "contentHandling": "CONVERT_TO_TEXT",
               "requestTemplates": {
                  "application/json": "{\n   \"imageKey\": \"$input.params('key')\", \"image\": \"$input.body\"\n}"
               },
               "responses": {
                  "default": {
                     "statusCode": "500"
                  },
                  "2\\d{2}": {
                     "statusCode": "200"
                  }
               }
            }
         }
      }
   },
   "x-amazon-apigateway-binary-media-types": [
      "application/octet-stream",
      "image/jpeg"
   ],
   "servers": [
      {
         "url": "https://abcdefghi.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/v1"
            }
         }
      }
   ],
   "components": {
      "schemas": {
         "Empty": {
            "type": "object",
            "title": "Empty Schema"
         }
      }
   }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-10-21T17:26:28Z",
    "title": "ApiName"
  },
  "host": "abcdefghi.execute-api.us-east-1.amazonaws.com",
  "basePath": "/v1",
  "schemes": [
    "https"
  ],
  "paths": {
    "/lambda": {
      "get": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
          "type": "AWS",
          "credentials": "arn:aws:iam::123456789012:role/Lambda",
          "httpMethod": "POST",
          "requestTemplates": {
            "application/json": "{\n   \"imageKey\": \"$input.params('key')\"\n}"
          },
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "{\n   \"image\": \"$input.body\"\n}"
              }
            }
          }
        }
      },
      "put": {
        "produces": [
          "application/json", "application/octet-stream"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          },
          "500": {
            "description": "500 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:image/invocations",
          "type": "AWS",
          "credentials": "arn:aws:iam::123456789012:role/Lambda",
          "httpMethod": "POST",
          "contentHandling" : "CONVERT_TO_TEXT",
          "requestTemplates": {
            "application/json": "{\n   \"imageKey\": \"$input.params('key')\", \"image\": \"$input.body\"\n}"
          },
          "responses": {
            "default": {
              "statusCode": "500"
            },
            "2\\d{2}": {
              "statusCode": "200"
            }
          }
        }
      }
    }
  },
  "x-amazon-apigateway-binary-media-types" : ["application/octet-stream", "image/jpeg"],
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  }
}
```

------

## Download an image from Lambda
<a name="api-gateway-content-encodings-example-download-image-from-lambda"></a>

To download an image file (`image.jpg`) as a binary blob from Lambda:

```
GET /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/octet-stream
```

The successful response looks like the following:

```
200 OK HTTP/1.1

[raw bytes]
```

To download an image file (`image.jpg`) as a base64-encoded string (formatted as a JSON property) from Lambda:

```
GET /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json
```

The successful response looks like the following:

```
200 OK HTTP/1.1

{
  "image": "W3JhdyBieXRlc10="
}
```

## Upload an image to Lambda
<a name="api-gateway-content-encodings-example-upload-image-to-lambda"></a>

To upload an image file (`image.jpg`) as a binary blob to Lambda:

```
PUT /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/octet-stream
Accept: application/json

[raw bytes]
```

The successful response looks like the following:

```
200 OK            
```

To upload an image file (`image.jpg`) as a base64-encoded string to Lambda:

```
PUT /v1/lambda?key=image.jpg HTTP/1.1
Host: abcdefghi.execute-api.us-east-1.amazonaws.com
Content-Type: application/json
Accept: application/json

W3JhdyBieXRlc10=
```

The successful response looks like the following:

```
200 OK           
```

# Invoke REST APIs in API Gateway
<a name="how-to-call-api"></a>

To call a deployed API, clients submit requests to the URL for the API Gateway component service for API execution, known as `execute-api`.

The base URL for REST APIs is in the following format: 

```
https://api-id.execute-api.region.amazonaws.com/stage/
```

where *api-id* is the API identifier, *region* is the AWS Region, and *stage* is the stage name of the API deployment. 

**Important**  
Before you can invoke an API, you must deploy it in API Gateway. For instructions on deploying an API, see [Deploy REST APIs in API Gateway](how-to-deploy-api.md). 

**Topics**
+ [Obtaining an API's invoke URL](#apigateway-how-to-call-rest-api)
+ [Invoking an API](#apigateway-call-api)
+ [Use the API Gateway console to test a REST API method](how-to-test-method.md)
+ [Use a Java SDK generated by API Gateway for a REST API](how-to-call-apigateway-generated-java-sdk.md)
+ [Use an Android SDK generated by API Gateway for a REST API](how-to-generate-sdk-android.md)
+ [Use a JavaScript SDK generated by API Gateway for a REST API](how-to-generate-sdk-javascript.md)
+ [Use a Ruby SDK generated by API Gateway for a REST API](how-to-call-sdk-ruby.md)
+ [Use iOS SDK generated by API Gateway for a REST API in Objective-C or Swift](how-to-generate-sdk-ios.md)

## Obtaining an API's invoke URL
<a name="apigateway-how-to-call-rest-api"></a>

You can use the console, the AWS CLI, or an exported OpenAPI definition to obtain an API's invoke URL.

### Obtaining an API's invoke URL using the console
<a name="apigateway-obtain-url-console"></a>

The following procedure shows how to obtain an API's invoke URL in the REST API console.

**To obtain an API's invoke URL using the REST API console**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a deployed API.

1. From the main navigation pane, choose **Stage**.

1. Under **Stage details**, choose the copy icon to copy your API's invoke URL.

   This URL is for the root resource of your API.  
![\[After you create your REST API, the console shows your API's invoke URL.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/getting-started-rest-invoke-url.png)

1. To obtain an API's invoke URL for another resource in your API, expand the stage under the secondary navigation pane, and then choose a method.

1. Choose the copy icon to copy your API's resource-level invoke URL.  
![\[The resource-level URL for your REST API is under the secondary navigation pane of the stage.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/resource-level-invoke-url.png)

#### Obtaining an API's invoke URL using the AWS CLI
<a name="apigateway-obtain-url-cli"></a>

The following procedure shows how to obtain an API's invoke URL using the AWS CLI.

**To obtain an API's invoke URL using the AWS CLI**

1. Use the following command to obtain the `rest-api-id`. This command returns all `rest-api-id` values in your Region. For more information, see [get-rest-apis](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-rest-apis.html).

   ```
   aws apigateway get-rest-apis
   ```

1. Replace the example `rest-api-id` with your `rest-api-id`, replace the example *\$1stage-name\$1* with your *\$1stage-name\$1*, and replace the *\$1region\$1*, with your Region.

   ```
   https://{restapi_id}.execute-api.{region}.amazonaws.com/{stage_name}/
   ```

##### Obtaining an API's invoke URL using the exported OpenAPI definition file of the API
<a name="apigateway-obtain-url-openapi"></a>

You can also construct the root URL by combining the `host` and `basePath` fields of an exported OpenAPI definition file of the API. For instructions on how to export your API, see [Export a REST API from API Gateway](api-gateway-export-api.md).

## Invoking an API
<a name="apigateway-call-api"></a>

You can call your deployed API using the browser, curl, or other applications, like [Postman](https://www.postman.com/).

Additionally, you can use the API Gateway console to test an API call. Test uses the API Gateway's `TestInvoke` feature, which allows API testing before the API is deployed. For more information, see [Use the API Gateway console to test a REST API method](how-to-test-method.md).

**Note**  
Query string parameter values in an invocation URL cannot contain `%%`.

### Invoking an API using a web browser
<a name="apigateway-call-api-brower"></a>

If your API permits anonymous access, you can use any web browser to invoke any `GET` method. Enter the complete invocation URL in the browser's address bar.

For other methods or any authentication-required calls, you must specify a payload or sign the requests. You can handle these in a script behind an HTML page or in a client application using one of the AWS SDKs.

#### Invoking an API using curl
<a name="apigateway-call-api-curl"></a>

You can use a tool like [curl](https://curl.se/) in your terminal to call your API. The following example curl command invokes the GET method on the `getUsers` resource of the `prod` stage of an API.

------
#### [ Linux or Macintosh ]

```
curl -X GET 'https://b123abcde4.execute-api.us-west-2.amazonaws.com/prod/getUsers'
```

------
#### [ Windows ]

```
curl -X GET "https://b123abcde4.execute-api.us-west-2.amazonaws.com/prod/getUsers"
```

------

# Use the API Gateway console to test a REST API method
<a name="how-to-test-method"></a>

Use the API Gateway console to test a REST API method.

**Topics**
+ [Prerequisites](#how-to-test-method-prerequisites)
+ [Test a method with the API Gateway console](#how-to-test-method-console)

## Prerequisites
<a name="how-to-test-method-prerequisites"></a>
+ You must specify the settings for the methods you want to test. Follow the instructions in [Methods for REST APIs in API Gateway](how-to-method-settings.md).

## Test a method with the API Gateway console
<a name="how-to-test-method-console"></a>

**Important**  
Testing methods with the API Gateway console might result in changes to resources that cannot be undone. Testing a method with the API Gateway console is the same as calling the method outside of the API Gateway console. For example, if you use the API Gateway console to call a method that deletes an API's resources, if the method call is successful, the API's resources will be deleted.

**To test a method**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the **Resources** pane, choose the method you want to test.

1. Choose the **Test** tab. You might need to choose the right arrow button to show the tab.  
![\[Use the test tab to test your API. It is next to the method response tab.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-gateway-test-new-console.png)

    Enter values in any of the displayed boxes (such as **Query strings**, **Headers**, and **Request body**). The console includes these values in the method request in default application/json form.

   For additional options you might need to specify, contact the API owner.

1. Choose **Test**. The following information will be displayed:
   + **Request** is the resource's path that was called for the method.
   + **Status** is the response's HTTP status code.
   + **Latency (ms)** is the time between the receipt of the request from the caller and the returned response.
   + **Response body** is the HTTP response body.
   + **Response headers** are the HTTP response headers.
**Tip**  
Depending on the mapping, the HTTP status code, response body, and response headers might be different from those sent from the Lambda function, HTTP proxy, or AWS service proxy.
   + **Logs** are the simulated Amazon CloudWatch Logs entries that would have been written if this method were called outside of the API Gateway console.
**Note**  
Although the CloudWatch Logs entries are simulated, the results of the method call are real.

 In addition to using the API Gateway console, you can use AWS CLI or an AWS SDK for API Gateway to test invoking a method. To do so using AWS CLI, see [test-invoke-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/test-invoke-method.html). 

# Use a Java SDK generated by API Gateway for a REST API
<a name="how-to-call-apigateway-generated-java-sdk"></a>

In this section, we outline the steps to use a Java SDK generated by API Gateway for a REST API, by using the [Simple Calculator](simple-calc-lambda-api-swagger-definition.md) API as an example. Before proceeding, you must complete the steps in [Generate SDKs for REST APIs in API Gateway](how-to-generate-sdk.md). 

**To install and use a Java SDK generated by API Gateway**

1. Extract the contents of the API Gateway-generated .zip file that you downloaded earlier.

1. Download and install [Apache Maven](https://maven.apache.org/) (must be version 3.5 or later).

1. Download and install [JDK 8](https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html).

1. Set the `JAVA_HOME` environment variable.

1.  Go to the unzipped SDK folder where the pom.xml file is located. This folder is `generated-code` by default. Run the **mvn install** command to install the compiled artifact files to your local Maven repository. This creates a `target` folder containing the compiled SDK library. 

1.  Type the following command in an empty directory to create a client project stub to call the API using the installed SDK library. 

   ```
   mvn -B archetype:generate \
       -DarchetypeGroupdId=org.apache.maven.archetypes \
       -DgroupId=examples.aws.apig.simpleCalc.sdk.app \
       -DartifactId=SimpleCalc-sdkClient
   ```
**Note**  
 The separator `\` in the preceding command is included for readability. The whole command should be on a single line without the separator. 

    This command creates an application stub. The application stub contains a `pom.xml` file and an `src` folder under the project's root directory (*SimpleCalc-sdkClient* in the preceding command). Initially, there are two source files: `src/main/java/{package-path}/App.java` and `src/test/java/{package-path}/AppTest.java`. In this example, *\$1package-path\$1* is `examples/aws/apig/simpleCalc/sdk/app`. This package path is derived from the `DarchetypeGroupdId` value. You can use the `App.java` file as a template for your client application, and you can add others in the same folder if needed. You can use the `AppTest.java` file as a unit test template for your application, and you can add other test code files to the same test folder as needed. 

1. Update the package dependencies in the generated `pom.xml` file to the following, substituting your project's `groupId`, `artifactId`, `version`, and `name` properties, if necessary:

   ```
   <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <groupId>examples.aws.apig.simpleCalc.sdk.app</groupId>
     <artifactId>SimpleCalc-sdkClient</artifactId>
     <packaging>jar</packaging>
     <version>1.0-SNAPSHOT</version>
     <name>SimpleCalc-sdkClient</name>
     <url>http://maven.apache.org</url>
   
      <dependencies>
         <dependency>
             <groupId>com.amazonaws</groupId>
             <artifactId>aws-java-sdk-core</artifactId>
             <version>1.11.94</version>
         </dependency>
         <dependency>
             <groupId>my-apig-api-examples</groupId>
             <artifactId>simple-calc-sdk</artifactId>
             <version>1.0.0</version>
         </dependency>
         
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>
         <scope>test</scope>
       </dependency>
   
       <dependency>
           <groupId>commons-io</groupId>
           <artifactId>commons-io</artifactId>
           <version>2.5</version>
       </dependency>    
     </dependencies>
   
     <build>
       <plugins>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>3.5.1</version>
           <configuration>
             <source>1.8</source>
             <target>1.8</target>
           </configuration>
         </plugin>
       </plugins>
     </build>
   </project>
   ```
**Note**  
 When a newer version of dependent artifact of `aws-java-sdk-core` is incompatible with the version specified above (`1.11.94`), you must update the `<version>` tag to the new version.

1.  Next, we show how to call the API using the SDK by calling the `getABOp(GetABOpRequest req)`, `getApiRoot(GetApiRootRequest req)`, and `postApiRoot(PostApiRootRequest req)` methods of the SDK. These methods correspond to the `GET /{a}/{b}/{op}`, `GET /?a={x}&b={y}&op={operator}`, and `POST /` methods, with a payload of `{"a": x, "b": y, "op": "operator"}` API requests, respectively. 

    Update the `App.java` file as follows: 

   ```
   package examples.aws.apig.simpleCalc.sdk.app;
   
   import java.io.IOException;
   
   import com.amazonaws.opensdk.config.ConnectionConfiguration;
   import com.amazonaws.opensdk.config.TimeoutConfiguration;
   
   import examples.aws.apig.simpleCalc.sdk.*;
   import examples.aws.apig.simpleCalc.sdk.model.*;
   import examples.aws.apig.simpleCalc.sdk.SimpleCalcSdk.*;
   
   public class App 
   {
       SimpleCalcSdk sdkClient;
   
       public App() {
           initSdk();
       }
   
       // The configuration settings are for illustration purposes and may not be a recommended best practice.
       private void initSdk() {
           sdkClient = SimpleCalcSdk.builder()
                 .connectionConfiguration(
                     new ConnectionConfiguration()
                           .maxConnections(100)
                           .connectionMaxIdleMillis(1000))
                 .timeoutConfiguration(
                     new TimeoutConfiguration()
                           .httpRequestTimeout(3000)
                           .totalExecutionTimeout(10000)
                           .socketTimeout(2000))
           .build();
   
       }
       // Calling shutdown is not necessary unless you want to exert explicit control of this resource.
       public void shutdown() {
           sdkClient.shutdown();
       }
        
       // GetABOpResult getABOp(GetABOpRequest getABOpRequest)
       public Output getResultWithPathParameters(String x, String y, String operator) {
       	operator = operator.equals("+") ? "add" : operator;
       	operator = operator.equals("/") ? "div" : operator; 
   
           GetABOpResult abopResult = sdkClient.getABOp(new GetABOpRequest().a(x).b(y).op(operator));
           return abopResult.getResult().getOutput();
       }
   
       public Output getResultWithQueryParameters(String a, String b, String op) {
           GetApiRootResult rootResult = sdkClient.getApiRoot(new GetApiRootRequest().a(a).b(b).op(op));
           return rootResult.getResult().getOutput();
       }
   
       public Output getResultByPostInputBody(Double x, Double y, String o) {
       	PostApiRootResult postResult = sdkClient.postApiRoot(
       		new PostApiRootRequest().input(new Input().a(x).b(y).op(o)));
       	return postResult.getResult().getOutput();
       }
   
       public static void main( String[] args )
       {
           System.out.println( "Simple calc" );
           // to begin
           App calc = new App();
           
           // call the SimpleCalc API
           Output res = calc.getResultWithPathParameters("1", "2", "-");
           System.out.printf("GET /1/2/-: %s\n", res.getC());
   
           // Use the type query parameter
           res = calc.getResultWithQueryParameters("1", "2", "+");
           System.out.printf("GET /?a=1&b=2&op=+: %s\n", res.getC());
   
           // Call POST with an Input body.
           res = calc.getResultByPostInputBody(1.0, 2.0, "*");
           System.out.printf("PUT /\n\n{\"a\":1, \"b\":2,\"op\":\"*\"}\n %s\n", res.getC());
   
           
       }
   }
   ```

    In the preceding example, the configuration settings used to instantiate the SDK client are for illustration purposes and are not necessarily recommended best practice. Also, calling `sdkClient.shutdown()` is optional, especially if you need precise control on when to free up resources. 

 We have shown the essential patterns to call an API using a Java SDK. You can extend the instructions to calling other API methods. 

# Use an Android SDK generated by API Gateway for a REST API
<a name="how-to-generate-sdk-android"></a>

In this section, we will outline the steps to use an Android SDK generated by API Gateway for a REST API. Before proceeding further, you must have already completed the steps in [Generate SDKs for REST APIs in API Gateway](how-to-generate-sdk.md).

**Note**  
 The generated SDK is not compatible with Android 4.4 and earlier. For more information, see [Amazon API Gateway important notes](api-gateway-known-issues.md). 

**To install and use an Android SDK generated by API Gateway**

1. Extract the contents of the API Gateway-generated .zip file that you downloaded earlier.

1. Download and install [Apache Maven](https://maven.apache.org/) (preferably version 3.x).

1. Download and install [JDK 8](https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html).

1. Set the `JAVA_HOME` environment variable.

1. Run the **mvn install** command to install the compiled artifact files to your local Maven repository. This creates a `target` folder containing the compiled SDK library.

1. Copy the SDK file (the name of which is derived from the **Artifact Id** and **Artifact Version** you specified when generating the SDK, e.g., `simple-calcsdk-1.0.0.jar`) from the `target` folder, along with all of the other libraries from the `target/lib` folder, into your project's `lib` folder.

   If you use Android Studio, create a `libs` folder under your client app module and copy the required .jar file into this folder. Verify that the dependencies section in the module's gradle file contains the following.

   ```
       compile fileTree(include: ['*.jar'], dir: 'libs')
       compile fileTree(include: ['*.jar'], dir: 'app/libs')
   ```

   Make sure no duplicated .jar files are declared.

1. Use the `ApiClientFactory` class to initialize the API Gateway-generated SDK. For example:

   ```
   ApiClientFactory factory = new ApiClientFactory();
   
   // Create an instance of your SDK. Here, 'SimpleCalcClient.java' is the compiled java class for the SDK generated by API Gateway. 
   final SimpleCalcClient client = factory.build(SimpleCalcClient.class);
   
   // Invoke a method: 
   //   For the 'GET /?a=1&b=2&op=+' method exposed by the API, you can invoke it by calling the following SDK method:
   
   Result output = client.rootGet("1", "2", "+");
   
   //     where the Result class of the SDK corresponds to the Result model of the API.
   //
   
   //   For the 'GET /{a}/{b}/{op}'  method exposed by the API, you can call the following SDK method to invoke the request,
   
   Result output = client.aBOpGet(a, b, c);
   
   //     where a, b, c can be "1", "2", "add", respectively.
   
   //   For the following API method:
   //        POST /
   //        host: ...
   //        Content-Type: application/json
   //    
   //        { "a": 1, "b": 2, "op": "+" }
   // you can call invoke it by calling the rootPost method of the SDK as follows:
   Input body = new Input();
   input.a=1;
   input.b=2;
   input.op="+";
   Result output = client.rootPost(body);
   
   //      where the Input class of the SDK corresponds to the Input model of the API.
   
   // Parse the result:
   //     If the 'Result' object is { "a": 1, "b": 2, "op": "add", "c":3"}, you retrieve the result 'c') as 
   
   String result=output.c;
   ```

1. To use an Amazon Cognito credentials provider to authorize calls to your API, use the `ApiClientFactory` class to pass a set of AWS credentials by using the SDK generated by API Gateway, as shown in the following example.

   ```
   // Use CognitoCachingCredentialsProvider to provide AWS credentials
   // for the ApiClientFactory
   AWSCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
           context,          // activity context
           "identityPoolId", // Cognito identity pool id
           Regions.US_EAST_1 // region of Cognito identity pool
   );
   
   ApiClientFactory factory = new ApiClientFactory()
     .credentialsProvider(credentialsProvider);
   ```

1. To set an API key by using the API Gateway- generated SDK, use code similar to the following.

   ```
   ApiClientFactory factory = new ApiClientFactory()
     .apiKey("YOUR_API_KEY");
   ```

# Use a JavaScript SDK generated by API Gateway for a REST API
<a name="how-to-generate-sdk-javascript"></a>

The following procedure shows how to use a JavaScript SDK generated by API Gateway.

**Note**  
These instructions assume you have already completed the instructions in [Generate SDKs for REST APIs in API Gateway](how-to-generate-sdk.md).

**Important**  
If your API only has ANY methods defined, the generated SDK package will not contain an `apigClient.js` file, and you will need to define the ANY methods yourself.

**To install, initiate and call a JavaScript SDK generated by API Gateway for a REST API**

1. Extract the contents of the API Gateway-generated .zip file you downloaded earlier.

1. Enable cross-origin resource sharing (CORS) for all of the methods the SDK generated by API Gateway will call. For instructions, see [CORS for REST APIs in API Gateway](how-to-cors.md).

1. In your web page, include references to the following scripts.

   ```
   <script type="text/javascript" src="lib/axios/dist/axios.standalone.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/rollups/hmac-sha256.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/rollups/sha256.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/components/hmac.js"></script>
   <script type="text/javascript" src="lib/CryptoJS/components/enc-base64.js"></script>
   <script type="text/javascript" src="lib/url-template/url-template.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/sigV4Client.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/apiGatewayClient.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/simpleHttpClient.js"></script>
   <script type="text/javascript" src="lib/apiGatewayCore/utils.js"></script>
   <script type="text/javascript" src="apigClient.js"></script>
   ```

1. In your code, initialize the SDK generated by API Gateway by using code similar to the following.

   ```
   var apigClient = apigClientFactory.newClient();
   ```

   To initialize the SDK generated by API Gateway with AWS credentials, use code similar to the following. If you use AWS credentials, all requests to the API will be signed. 

   ```
   var apigClient = apigClientFactory.newClient({
     accessKey: 'ACCESS_KEY',
     secretKey: 'SECRET_KEY',
   });
   ```

   To use an API key with the SDK generated by API Gateway, pass the API key as a parameter to the `Factory` object by using code similar to the following. If you use an API key, it is specified as part of the `x-api-key` header and all requests to the API will be signed. This means you must set the appropriate CORS Accept headers for each request.

   ```
   var apigClient = apigClientFactory.newClient({
     apiKey: 'API_KEY'
   });
   ```

   

1. Call the API methods in API Gateway by using code similar to the following. Each call returns a promise with a success and failure callbacks.

   ```
   var params = {
     // This is where any modeled request parameters should be added.
     // The key is the parameter name, as it is defined in the API in API Gateway.
     param0: '',
     param1: ''
   };
   
   var body = {
     // This is where you define the body of the request,
   };
   
   var additionalParams = {
     // If there are any unmodeled query parameters or headers that must be
     //   sent with the request, add them here.
     headers: {
       param0: '',
       param1: ''
     },
     queryParams: {
       param0: '',
       param1: ''
     }
   };
   
   apigClient.methodName(params, body, additionalParams)
       .then(function(result){
         // Add success callback code here.
       }).catch( function(result){
         // Add error callback code here.
       });
   ```

   Here, the *methodName* is constructed from the method request's resource path and the HTTP verb. For the SimpleCalc API, the SDK methods for the API methods of 

   ```
   1. GET /?a=...&b=...&op=...
   2. POST /
   
      { "a": ..., "b": ..., "op": ...}
   3. GET /{a}/{b}/{op}
   ```

   the corresponding SDK methods are as follows:

   ```
   1. rootGet(params);      // where params={"a": ..., "b": ..., "op": ...} is resolved to the query parameters
   2. rootPost(null, body); // where body={"a": ..., "b": ..., "op": ...}
   3. aBOpGet(params);      // where params={"a": ..., "b": ..., "op": ...} is resolved to the path parameters
   ```

   

# Use a Ruby SDK generated by API Gateway for a REST API
<a name="how-to-call-sdk-ruby"></a>

The following procedure shows how to use a Ruby SDK generated by API Gateway.

**Note**  
These instructions assume you already completed the instructions in [Generate SDKs for REST APIs in API Gateway](how-to-generate-sdk.md).

**To install, instantiate, and call a Ruby SDK generated by API Gateway for a REST API**

1. Unzip the downloaded Ruby SDK file. The generated SDK source is shown as follows.  
![\[Unzip the downloaded Ruby SDK file into a Ruby module\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/ruby-gem-of-generated-sdk-for-simplecalc.png)

   

1.  Build a Ruby Gem from the generated SDK source, using the following shell commands in a terminal window:

   ```
   # change to /simplecalc-sdk directory
   cd simplecalc-sdk
   
   # build the generated gem
   gem build simplecalc-sdk.gemspec
   ```

   After this, **simplecalc-sdk-1.0.0.gem** becomes available.

1.  Install the gem:

   ```
   gem install simplecalc-sdk-1.0.0.gem
   ```

1.  Create a client application. Instantiate and initialize the Ruby SDK client in the app:

   ```
   require 'simplecalc-sdk'
   client = SimpleCalc::Client.new(
       http_wire_trace: true,
       retry_limit: 5,
       http_read_timeout: 50
   )
   ```

   If the API has authorization of the `AWS_IAM` type is configured, you can include the caller's AWS credentials by supplying `accessKey` and `secretKey` during the initialization:

   ```
   require 'pet-sdk'
   client = Pet::Client.new(
       http_wire_trace: true,
       retry_limit: 5,
       http_read_timeout: 50,
       access_key_id: 'ACCESS_KEY',
       secret_access_key: 'SECRET_KEY'
   )
   ```

1.  Make API calls through the SDK in the app. 
**Tip**  
 If you are not familiar with the SDK method call conventions, you can review the `client.rb` file in the generated SDK `lib` folder. The folder contains documentation of each supported API method call.

   To discover supported operations:

   ```
   # to show supported operations:
   puts client.operation_names
   ```

   This results in the following display, corresponding to the API methods of `GET /?a={.}&b={.}&op={.}`, `GET /{a}/{b}/{op}`, and `POST /`, plus a payload of the `{a:"…", b:"…", op:"…"}` format, respectively:

   ```
   [:get_api_root, :get_ab_op, :post_api_root]
   ```

   To invoke the `GET /?a=1&b=2&op=+` API method, call the following the Ruby SDK method:

   ```
   resp = client.get_api_root({a:"1", b:"2", op:"+"})
   ```

   To invoke the `POST /` API method with a payload of `{a: "1", b: "2", "op": "+"}`, call the following Ruby SDK method:

   ```
   resp = client.post_api_root(input: {a:"1", b:"2", op:"+"})
   ```

   To invoke the `GET /1/2/+` API method, call the following Ruby SDK method:

   ```
   resp = client.get_ab_op({a:"1", b:"2", op:"+"})
   ```

   The successful SDK method calls return the following response:

   ```
   resp : {
       result: {
           input: {
               a: 1,
               b: 2,
               op: "+"
           },
           output: {
               c: 3
           }
       }
   }
   ```

# Use iOS SDK generated by API Gateway for a REST API in Objective-C or Swift
<a name="how-to-generate-sdk-ios"></a>

In this tutorial, we will show how to use an iOS SDK generated by API Gateway for a REST API in an Objective-C or Swift app to call the underlying API. We will use the [SimpleCalc API](simple-calc-lambda-api.md) as an example to illustrate the following topics:
+ How to install the required AWS Mobile SDK components into your Xcode project
+ How to create the API client object before calling the API's methods
+ How to call the API methods through the corresponding SDK methods on the API client object
+ How to prepare a method input and parse its result using the corresponding model classes of the SDK

**Topics**
+ [Use generated iOS SDK (Objective-C) to call API](#how-to-use-sdk-ios-objc)
+ [Use generated iOS SDK (Swift) to call API](#how-to-generate-sdk-ios-swift)

## Use generated iOS SDK (Objective-C) to call API
<a name="how-to-use-sdk-ios-objc"></a>

Before beginning the following procedure, you must complete the steps in [Generate SDKs for REST APIs in API Gateway](how-to-generate-sdk.md) for iOS in Objective-C and download the .zip file of the generated SDK.

### Install the AWS mobile SDK and an iOS SDK generated by API Gateway in an Objective-C project
<a name="use-sdk-ios-objc-install-sdk"></a>

The following procedure describes how to install the SDK.

**To install and use an iOS SDK generated by API Gateway in Objective-C**

1. Extract the contents of the API Gateway-generated .zip file you downloaded earlier. Using the [SimpleCalc API](simple-calc-lambda-api.md), you may want to rename the unzipped SDK folder to something like **sdk\$1objc\$1simple\$1calc**. In this SDK folder there is a `README.md` file and a `Podfile` file. The `README.md` file contains the instructions to install and use the SDK. This tutorial provides details about these instructions. The installation leverages [CocoaPods](https://cocoapods.org) to import required API Gateway libraries and other dependent AWS Mobile SDK components. You must update the `Podfile` to import the SDKs into your app's Xcode project. The unarchived SDK folder also contains a `generated-src` folder that contains the source code of the generated SDK of your API.

1. Launch Xcode and create a new iOS Objective-C project. Make a note of the project's target. You will need to set it in the `Podfile`.

      
![\[Find the target in Xcode.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/use-sdk-in-ios-objc-project-find-target.png)

1. To import the AWS Mobile SDK for iOS into the Xcode project by using CocoaPods, do the following:

   1. Install CocoaPods by running the following command in a terminal window:

      ```
      sudo gem install cocoapods
      pod setup
      ```

   1. Copy the `Podfile` file from the extracted SDK folder into the same directory containing your Xcode project file. Replace the following block:

      ```
      target '<YourXcodeTarget>' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      with your project's target name: 

      ```
      target 'app_objc_simple_calc' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      If your Xcode project already contains a file named `Podfile`, add the following line of code to it:

      ```
      pod 'AWSAPIGateway', '~> 2.4.7'
      ```

   1. Open a terminal window and run the following command:

      ```
      pod install
      ```

      This installs the API Gateway component and other dependent AWS Mobile SDK components.

   1. Close the Xcode project and then open the `.xcworkspace` file to relaunch Xcode.

   1. Add all of the `.h` and `.m` files from the extracted SDK's `generated-src` directory into your Xcode project.

         
![\[.h and .m files are in the generated-src\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/use-sdk-in-ios-objc-project-add-sdk-src.png)

   To import the AWS Mobile SDK for iOS Objective-C into your project by explicitly downloading AWS Mobile SDK or using [Carthage](https://github.com/Carthage/Carthage#installing-carthage), follow the instructions in the *README.md* file. Be sure to use only one of these options to import the AWS Mobile SDK.

### Call API methods using the iOS SDK generated by API Gateway in an Objective-C project
<a name="use-sdk-ios-objc-call-sdk"></a>

When you generated the SDK with the prefix of `SIMPLE_CALC` for this [SimpleCalc API](simple-calc-lambda-api.md) with two models for input (`Input`) and output (`Result`) of the methods, in the SDK, the resulting API client class becomes `SIMPLE_CALCSimpleCalcClient` and the corresponding data classes are `SIMPLE_CALCInput` and `SIMPLE_CALCResult`, respectively. The API requests and responses are mapped to the SDK methods as follows:
+ The API request of

  ```
  GET /?a=...&b=...&op=...
  ```

  becomes the SDK method of

  ```
  (AWSTask *)rootGet:(NSString *)op a:(NSString *)a b:(NSString *)b
  ```

  The `AWSTask.result` property is of the `SIMPLE_CALCResult` type if the `Result` model was added to the method response. Otherwise, the property is of the `NSDictionary` type.
+ This API request of

  ```
  POST /
      
  {
     "a": "Number",
     "b": "Number",
     "op": "String"
  }
  ```

  becomes the SDK method of

  ```
  (AWSTask *)rootPost:(SIMPLE_CALCInput *)body
  ```
+ The API request of

  ```
  GET /{a}/{b}/{op}
  ```

  becomes the SDK method of

  ```
  (AWSTask *)aBOpGet:(NSString *)a b:(NSString *)b op:(NSString *)op
  ```

The following procedure describes how to call the API methods in Objective-C app source code; for example, as part of the `viewDidLoad` delegate in a `ViewController.m` file.

**To call the API through the iOS SDK generated by API Gateway**

1. Import the API client class header file to make the API client class callable in the app:

   ```
   #import "SIMPLE_CALCSimpleCalc.h"
   ```

   The `#import` statement also imports `SIMPLE_CALCInput.h` and `SIMPLE_CALCResult.h` for the two model classes.

1. Instantiate the API client class:

   ```
   SIMPLE_CALCSimpleCalcClient *apiInstance = [SIMPLE_CALCSimpleCalcClient defaultClient];
   ```

   To use Amazon Cognito with the API, set the `defaultServiceConfiguration` property on the default `AWSServiceManager` object, as shown in the following, before calling the `defaultClient` method to create the API client object (shown in the preceding example):

   ```
   AWSCognitoCredentialsProvider *creds = [[AWSCognitoCredentialsProvider alloc] initWithRegionType:AWSRegionUSEast1 identityPoolId:your_cognito_pool_id];
   AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast1 credentialsProvider:creds];
   AWSServiceManager.defaultServiceManager.defaultServiceConfiguration = configuration;
   ```

1. Call the `GET /?a=1&b=2&op=+` method to perform `1+2`:

   ```
   [[apiInstance rootGet: @"+" a:@"1" b:@"2"] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
       _textField1.text = [self handleApiResponse:task];
       return nil;
   }];
   ```

   where the helper function `handleApiResponse:task` formats the result as a string to be displayed in a text field (`_textField1`).

   ```
   - (NSString *)handleApiResponse:(AWSTask *)task {
       if (task.error != nil) {
           return [NSString stringWithFormat: @"Error: %@", task.error.description];
       } else if (task.result != nil && [task.result isKindOfClass:[SIMPLE_CALCResult class]]) {
           return [NSString stringWithFormat:@"%@ %@ %@ = %@\n",task.result.input.a, task.result.input.op, task.result.input.b, task.result.output.c];
       }
       return nil;
   }
   ```

   The resulting display is `1 + 2 = 3`.

1. Call the `POST /` with a payload to perform `1-2`:

   ```
   SIMPLE_CALCInput *input = [[SIMPLE_CALCInput alloc] init];
       input.a = [NSNumber numberWithInt:1];
       input.b = [NSNumber numberWithInt:2];
       input.op = @"-";
       [[apiInstance rootPost:input] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
           _textField2.text = [self handleApiResponse:task];
           return nil;
       }];
   ```

   The resulting display is `1 - 2 = -1`.

1. Call the `GET /{a}/{b}/{op}` to perform `1/2`:

   ```
   [[apiInstance aBOpGet:@"1" b:@"2" op:@"div"] continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
       _textField3.text = [self handleApiResponse:task];
       return nil;
   }];
   ```

   The resulting display is `1 div 2 = 0.5`. Here, `div` is used in place of `/` because the [simple Lambda function](simple-calc-nodejs-lambda-function.md) in the backend does not handle URL encoded path variables.

## Use generated iOS SDK (Swift) to call API
<a name="how-to-generate-sdk-ios-swift"></a>

Before beginning the following procedure, you must complete the steps in [Generate SDKs for REST APIs in API Gateway](how-to-generate-sdk.md) for iOS in Swift and download the .zip file of the generated SDK.

**Topics**
+ [Install AWS mobile SDK and API Gateway-generated SDK in a Swift project](#use-sdk-ios-swift-install-sdk)
+ [Call API methods through the iOS SDK generated by API Gateway in a Swift project](#use-sdk-ios-swift-call-api)

### Install AWS mobile SDK and API Gateway-generated SDK in a Swift project
<a name="use-sdk-ios-swift-install-sdk"></a>

The following procedure describes how to install the SDK.

**To install and use an iOS SDK generated by API Gateway in Swift**

1. Extract the contents of the API Gateway-generated .zip file you downloaded earlier. Using the [SimpleCalc API](simple-calc-lambda-api.md), you may want to rename the unzipped SDK folder to something like **sdk\$1swift\$1simple\$1calc**. In this SDK folder there is a `README.md` file and a `Podfile` file. The `README.md` file contains the instructions to install and use the SDK. This tutorial provides details about these instructions. The installation leverages [CocoaPods](https://cocoapods.org) to import required AWS Mobile SDK components. You must update the `Podfile` to import the SDKs into your Swift app's Xcode project. The unarchived SDK folder also contains a `generated-src` folder that contains the source code of the generated SDK of your API.

1. Launch Xcode and create a new iOS Swift project. Make a note of the project's target. You will need to set it in the `Podfile`.

      
![\[Find the target in Xcode.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-find-target.png)

1. To import the required AWS Mobile SDK components into the Xcode project by using CocoaPods, do the following:

   1. If it is not installed, install CocoaPods by running the following command in a terminal window:

      ```
      sudo gem install cocoapods
      pod setup
      ```

   1. Copy the `Podfile` file from the extracted SDK folder into the same directory containing your Xcode project file. Replace the following block:

      ```
      target '<YourXcodeTarget>' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      with your project's target name as shown: 

      ```
      target 'app_swift_simple_calc' do
          pod 'AWSAPIGateway', '~> 2.4.7'
      end
      ```

      If your Xcode project already contains a `Podfile` with the correct target, you can simply add the following line of code to the `do ... end` loop:

      ```
      pod 'AWSAPIGateway', '~> 2.4.7'
      ```

   1. Open a terminal window and run the following command in the app directory:

      ```
      pod install
      ```

      This installs the API Gateway component and any dependent AWS Mobile SDK components into the app's project.

   1. Close the Xcode project and then open the `*.xcworkspace` file to relaunch Xcode.

   1. Add all of the SDK's header files (`.h`) and Swift source code files (`.swift`) from the extracted `generated-src` directory to your Xcode project.

         
![\[.h and .swift files are in the generated-src\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-add-sdk-src.png)

   1. To enable calling the Objective-C libraries of the AWS Mobile SDK from your Swift code project, set the `Bridging_Header.h` file path on the **Objective-C Bridging Header** property under the **Swift Compiler - General** setting of your Xcode project configuration: 

         
![\[Set the Bridging_Header.h file path under the Swift Compiler - General.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-set-bridging-header.png)
**Tip**  
You can type **bridging** in the search box of Xcode to locate the **Objective-C Bridging Header** property.

   1. Build the Xcode project to verify that it is properly configured before proceeding further. If your Xcode uses a more recent version of Swift than the one supported for the AWS Mobile SDK, you will get Swift compiler errors. In this case, set the **Use Legacy Swift Language Version** property to **Yes** under the **Swift Compiler - Version** setting:

         
![\[Set the Legacy Swift Language Version property to Yes.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/use-sdk-in-ios-swift-project-set-legacy-swift-version.png)

   To import the AWS Mobile SDK for iOS in Swift into your project by explicitly downloading the AWS Mobile SDK or using [Carthage](https://github.com/Carthage/Carthage#installing-carthage), follow the instructions in the `README.md` file that comes with the SDK package. Be sure to use only one of these options to import the AWS Mobile SDK.

### Call API methods through the iOS SDK generated by API Gateway in a Swift project
<a name="use-sdk-ios-swift-call-api"></a>

When you generated the SDK with the prefix of `SIMPLE_CALC` for this [SimpleCalc API](simple-calc-lambda-api.md) with two models to describe the input (`Input`) and output (`Result`) of the API's requests and responses, in the SDK, the resulting API client class becomes `SIMPLE_CALCSimpleCalcClient` and the corresponding data classes are `SIMPLE_CALCInput` and `SIMPLE_CALCResult`, respectively. The API requests and responses are mapped to the SDK methods as follows: 
+ The API request of

  ```
  GET /?a=...&b=...&op=...
  ```

  becomes the SDK method of

  ```
  public func rootGet(op: String?, a: String?, b: String?) -> AWSTask
  ```

  The `AWSTask.result` property is of the `SIMPLE_CALCResult` type if the `Result` model was added to the method response. Otherwise, it is of the `NSDictionary` type.
+ This API request of

  ```
  POST /
      
  {
     "a": "Number",
     "b": "Number",
     "op": "String"
  }
  ```

  becomes the SDK method of

  ```
  public func rootPost(body: SIMPLE_CALCInput) -> AWSTask
  ```
+ The API request of

  ```
  GET /{a}/{b}/{op}
  ```

  becomes the SDK method of

  ```
  public func aBOpGet(a: String, b: String, op: String) -> AWSTask
  ```

The following procedure describes how to call the API methods in Swift app source code; for example, as part of the `viewDidLoad()` delegate in a `ViewController.m` file.

**To call the API through the iOS SDK generated by API Gateway**

1. Instantiate the API client class:

   ```
   let client = SIMPLE_CALCSimpleCalcClient.default()
   ```

   To use Amazon Cognito with the API, set a default AWS service configuration (shown following) before getting the `default` method (shown previously):

   ```
   let credentialsProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityPoolId: "my_pool_id")        
   let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentialsProvider)        
   AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
   ```

1. Call the `GET /?a=1&b=2&op=+` method to perform `1+2`:

   ```
   client.rootGet("+", a: "1", b:"2").continueWithBlock {(task: AWSTask) -> AnyObject? in
       self.showResult(task)
       return nil
   }
   ```

   where the helper function `self.showResult(task)` prints the result or error to the console; for example: 

   ```
   func showResult(task: AWSTask) {
       if let error = task.error {
           print("Error: \(error)")
       } else if let result = task.result {
           if result is SIMPLE_CALCResult {
               let res = result as! SIMPLE_CALCResult
               print(String(format:"%@ %@ %@ = %@", res.input!.a!, res.input!.op!, res.input!.b!, res.output!.c!))
           } else if result is NSDictionary {
               let res = result as! NSDictionary
               print("NSDictionary: \(res)")
           }
       }
   }
   ```

   In a production app, you can display the result or error in a text field. The resulting display is `1 + 2 = 3`.

1. Call the `POST /` with a payload to perform `1-2`:

   ```
   let body = SIMPLE_CALCInput()
   body.a=1
   body.b=2
   body.op="-"
   client.rootPost(body).continueWithBlock {(task: AWSTask) -> AnyObject? in
       self.showResult(task)
       return nil
   }
   ```

   The resultant display is `1 - 2 = -1`.

1. Call the `GET /{a}/{b}/{op}` to perform `1/2`:

   ```
   client.aBOpGet("1", b:"2", op:"div").continueWithBlock {(task: AWSTask) -> AnyObject? in
       self.showResult(task)
       return nil
   }
   ```

   The resulting display is `1 div 2 = 0.5`. Here, `div` is used in place of `/` because the [simple Lambda function](simple-calc-nodejs-lambda-function.md) in the backend does not handle URL encoded path variables.

# Develop REST APIs using OpenAPI in API Gateway
<a name="api-gateway-import-api"></a>

You can use API Gateway to import a REST API from an external definition file into API Gateway. Currently, API Gateway supports [OpenAPI v2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md) and [OpenAPI v3.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.1.md) definition files, with exceptions listed in [Amazon API Gateway important notes for REST APIs](api-gateway-known-issues.md#api-gateway-known-issues-rest-apis). You can update an API by overwriting it with a new definition, or you can merge a definition with an existing API. You specify the options by using a `mode` query parameter in the request URL. 

For a tutorial on using the Import API feature from the API Gateway console, see [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md).

**Topics**
+ [Import an edge-optimized API into API Gateway](import-edge-optimized-api.md)
+ [Import a Regional API into API Gateway](import-export-api-endpoints.md)
+ [Import an OpenAPI file to update an existing API definition](api-gateway-import-api-update.md)
+ [Set the OpenAPI `basePath` property](api-gateway-import-api-basePath.md)
+ [AWS variables for OpenAPI import](import-api-aws-variables.md)
+ [Errors and warnings from importing your API into API Gateway](api-gateway-import-api-errors-warnings.md)
+ [Export a REST API from API Gateway](api-gateway-export-api.md)

# Import an edge-optimized API into API Gateway
<a name="import-edge-optimized-api"></a>

You can import an API's OpenAPI definition file to create a new edge-optimized API by specifying the `EDGE` endpoint type as an additional input, besides the OpenAPI file, to the import operation. You can do so using the API Gateway console, AWS CLI, or an AWS SDK.

For a tutorial on using the Import API feature from the API Gateway console, see [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md).

**Topics**
+ [Import an edge-optimized API using the API Gateway console](#import-edge-optimized-api-with-console)
+ [Import an edge-optimized API using the AWS CLI](#import-edge-optimized-api-with-awscli)

## Import an edge-optimized API using the API Gateway console
<a name="import-edge-optimized-api-with-console"></a>

To import an edge-optimized API using the API Gateway console, do the following:

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Create API**.

1. Under **REST API**, choose **Import**.

1.  Copy an API's OpenAPI definition and paste it into the code editor, or choose **Choose file** to load an OpenAPI file from a local drive.

1.  For **API endpoint type**, select **Edge-optimized**.

1.  Choose **Create API** to start importing the OpenAPI definitions.

## Import an edge-optimized API using the AWS CLI
<a name="import-edge-optimized-api-with-awscli"></a>

The following [import-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-rest-api.html) command imports an API from an OpenAPI definition file to create a new edge-optimized API:

```
aws apigateway import-rest-api \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```

or with an explicit specification of the `endpointConfigurationTypes` query string parameter to `EDGE`: 

```
aws apigateway import-rest-api \
    --parameters endpointConfigurationTypes=EDGE \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```



# Import a Regional API into API Gateway
<a name="import-export-api-endpoints"></a>

When importing an API, you can choose the regional endpoint configuration for the API. You can use the API Gateway console, the AWS CLI, or an AWS SDK.

When you export an API, the API endpoint configuration is not included in the exported API definitions.

For a tutorial on using the Import API feature from the API Gateway console, see [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md).

**Topics**
+ [Import a regional API using the API Gateway console](#import-regional-api-with-console)
+ [Import a regional API using the AWS CLI](#import-regional-api-with-awscli)

## Import a regional API using the API Gateway console
<a name="import-regional-api-with-console"></a>

To import an API of a regional endpoint using the API Gateway console, do the following:

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Create API**.

1. Under **REST API**, choose **Import**.

1.  Copy an API's OpenAPI definition and paste it into the code editor, or choose **Choose file** to load an OpenAPI file from a local drive.

1. For **API endpoint type**, select **Regional**.

1.  Choose **Create API** to start importing the OpenAPI definitions.

## Import a regional API using the AWS CLI
<a name="import-regional-api-with-awscli"></a>

The following [import-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-rest-api.html) command imports an OpenAPI definition file and sets the endpoint type to Regional:

```
aws apigateway import-rest-api \
    --parameters endpointConfigurationTypes=REGIONAL \
    --fail-on-warnings \
    --body 'file://path/to/API_OpenAPI_template.json'
```

# Import an OpenAPI file to update an existing API definition
<a name="api-gateway-import-api-update"></a>

 You can import API definitions only to update an existing API, without changing its endpoint configuration, as well as stages and stage variables, or references to API keys. 

 The import-to-update operation can occur in two modes: merge or overwrite. 

When an API (`A`) is merged into another (`B`), the resulting API retains the definitions of both `A` and `B` if the two APIs do not share any conflicting definitions. When conflicts arise, the method definitions of the merging API (`A`) overrides the corresponding method definitions of the merged API (`B`). For example, suppose `B` has declared the following methods to return `200` and `206` responses:

```
GET /a
POST /a
```

and `A` declares the following method to return `200` and `400` responses:

```
GET /a
```

When `A` is merged into `B`, the resulting API yields the following methods:

```
GET /a
```

which returns `200` and `400` responses, and 

```
POST /a
```

which returns `200` and `206` responses.

Merging an API is useful when you have decomposed your external API definitions into multiple, smaller parts and only want to apply changes from one of those parts at a time. For example, this might occur if multiple teams are responsible for different parts of an API and have changes available at different rates. In this mode, items from the existing API that aren't specifically defined in the imported definition are left alone. 

When an API (`A`) overwrites another API (`B`), the resulting API takes the definitions of the overwriting API (`A`). Overwriting an API is useful when an external API definition contains the complete definition of an API. In this mode, items from an existing API that aren't specifically defined in the imported definition are deleted. 

 To merge an API, submit a `PUT` request to `https://apigateway.<region>.amazonaws.com/restapis/<restapi_id>?mode=merge`. The `restapi_id` path parameter value specifies the API to which the supplied API definition will be merged. 

 The following code snippet shows an example of the `PUT` request to merge an OpenAPI API definition in JSON, as the payload, with the specified API already in API Gateway. 

```
PUT /restapis/<restapi_id>?mode=merge
Host:apigateway.<region>.amazonaws.com
Content-Type: application/json
Content-Length: ...

An OpenAPI API definition in JSON
```

 The merging update operation takes two complete API definitions and merges them together. For a small and incremental change, you can use the [resource update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateResource.html) operation. 

 To overwrite an API, submit a `PUT` request to `https://apigateway.<region>.amazonaws.com/restapis/<restapi_id>?mode=overwrite`. The `restapi_id` path parameter specifies the API that will be overwritten with the supplied API definitions. 

 The following code snippet shows an example of an overwriting request with the payload of a JSON-formatted OpenAPI definition: 

```
PUT /restapis/<restapi_id>?mode=overwrite
Host:apigateway.<region>.amazonaws.com
Content-Type: application/json
Content-Length: ...

An OpenAPI API definition in JSON
```

 When the `mode` query parameter isn't specified, merge is assumed.

**Note**  
 The `PUT` operations are idempotent, but not atomic. That means if a system error occurs part way through processing, the API can end up in a bad state. However, repeating the operation successfully puts the API into the same final state as if the first operation had succeeded. 

# Set the OpenAPI `basePath` property
<a name="api-gateway-import-api-basePath"></a>

In [OpenAPI 2.0](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md), you can use the `basePath` property to provide one or more path parts that precede each path defined in the `paths` property. Because API Gateway has several ways to express a resource's path, the Import API feature provides the following options for interpreting the `basePath` property during import: ignore, prepend, and split.

In [https://swagger.io/docs/specification/api-host-and-base-path/](https://swagger.io/docs/specification/api-host-and-base-path/), `basePath` is no longer a top-level property. Instead, API Gateway uses a [server variable](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#serverVariableObject) as a convention. The Import API feature provides the same options for interpreting the base path during import. The base path is identified as follows:
+ If the API doesn't contain any `basePath` variables, the Import API feature checks the `server.url` string to see if it contains a path beyond `"/"`. If it does, that path is used as the base path.
+ If the API contains only one `basePath` variable, the Import API feature uses it as the base path, even if it's not referenced in the `server.url`.
+ If the API contains multiple `basePath` variables, the Import API feature uses only the first one as the base path.

## Ignore
<a name="api-gateway-import-api-basePath-ignore"></a>

If the OpenAPI file has a `basePath` value of `/a/b/c` and the `paths` property contains `/e` and `/f`, the following `POST` or `PUT` request: 

```
POST /restapis?mode=import&basepath=ignore
```



```
PUT /restapis/api_id?basepath=ignore
```

 results in the following resources in the API: 
+ `/`
+ `/e`
+ `/f`

 The effect is to treat the `basePath` as if it was not present, and all of the declared API resources are served relative to the host. This can be used, for example, when you have a custom domain name with an API mapping that doesn't include a *Base Path* and a *Stage* value that refers to your production stage. 

**Note**  
 API Gateway automatically creates a root resource for you, even if it isn't explicitly declared in your definition file. 

 When unspecified, `basePath` takes `ignore` by default. 

## Prepend
<a name="api-gateway-import-api-basePath-prepend"></a>

 If the OpenAPI file has a `basePath` value of `/a/b/c` and the `paths` property contains `/e` and `/f`, the following `POST` or `PUT` request: 

```
POST /restapis?mode=import&basepath=prepend
```



```
PUT /restapis/api_id?basepath=prepend
```

 results in the following resources in the API: 
+ `/`
+ `/a`
+ `/a/b`
+ `/a/b/c`
+ `/a/b/c/e`
+ `/a/b/c/f`

 The effect is to treat the `basePath` as specifying additional resources (without methods) and to add them to the declared resource set. This can be used, for example, when different teams are responsible for different parts of an API and the `basePath` could reference the path location for each team's API part. 

**Note**  
 API Gateway automatically creates intermediate resources for you, even if they aren't explicitly declared in your definition. 

## Split
<a name="api-gateway-import-api-basePath-split"></a>

 If the OpenAPI file has a `basePath` value of `/a/b/c` and the `paths` property contains `/e` and `/f`, the following `POST` or `PUT` request: 

```
POST /restapis?mode=import&basepath=split
```



```
PUT /restapis/api_id?basepath=split
```

 results in the following resources in the API: 
+ `/`
+ `/b`
+ `/b/c`
+ `/b/c/e`
+ `/b/c/f`

 The effect is to treat top-most path part, `/a`, as the beginning of each resource's path, and to create additional (no method) resources within the API itself. This could, for example, be used when `a` is a stage name that you want to expose as part of your API. 

# AWS variables for OpenAPI import
<a name="import-api-aws-variables"></a>

You can use the following AWS variables in OpenAPI definitions. API Gateway resolves the variables when the API is imported. To specify a variable, use `${variable-name}`. The following table describes the available AWS variables. 


| Variable name | Description | 
| --- | --- | 
| AWS::AccountId | The AWS account ID that imports the API. For example, 123456789012. | 
| AWS::Partition | The AWS partition in which the API is imported. For standard AWS Regions, the partition is aws. | 
| AWS::Region | The AWS Region in which the API is imported. For example, us-east-2. | 

## AWS variables example
<a name="import-api-aws-variables-example"></a>

The following example uses AWS variables to specify an AWS Lambda function for an integration.

------
#### [ OpenAPI 3.0 ]

```
openapi: "3.0.1"
info:
  title: "tasks-api"
  version: "v1.0"
paths:
  /:
    get:
      summary: List tasks
      description: Returns a list of tasks
      responses:
        200:
          description: "OK"
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Task"
        500:
          description: "Internal Server Error"
          content: {}
      x-amazon-apigateway-integration:
        uri:
          arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:LambdaFunctionName/invocations
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"
components:
  schemas:
    Task:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
```

------

# Errors and warnings from importing your API into API Gateway
<a name="api-gateway-import-api-errors-warnings"></a>

When you import your external definition file into API Gateway, API Gateway might generate warnings and errors. The following sections discuss the errors and warnings that might occur during import.

## Errors during import
<a name="api-gateway-import-api-errors"></a>

 During the import, errors can be generated for major issues like an invalid OpenAPI document. Errors are returned as exceptions (for example, `BadRequestException`) in an unsuccessful response. When an error occurs, the new API definition is discarded and no change is made to the existing API. 

## Warnings during import
<a name="api-gateway-import-api-warnings"></a>

 During the import, warnings can be generated for minor issues like a missing model reference. If a warning occurs, the operation will continue if the `failonwarnings=false` query expression is appended to the request URL. Otherwise, the updates will be rolled back. By default, `failonwarnings` is set to `false`. In such cases, warnings are returned as a field in the resulting [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource. Otherwise, warnings are returned as a message in the exception. 

# Export a REST API from API Gateway
<a name="api-gateway-export-api"></a>

 Once you created and configured a REST API in API Gateway, using the API Gateway console or otherwise, you can export it to an OpenAPI file using the API Gateway Export API, which is part of the Amazon API Gateway Control Service. To use the API Gateway Export API, you need to sign your API requests. For more information about signing requests, see [Signing AWS API requests](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html) in the *IAM User Guide*. You have options to include the API Gateway integration extensions, as well as the [Postman](https://www.postman.com) extensions, in the exported OpenAPI definition file. 

**Note**  
When exporting the API using the AWS CLI, be sure to include the extensions parameter as shown in the following example, to ensure that the `x-amazon-apigateway-request-validator` extension is included:  

```
aws apigateway get-export --parameters extensions='apigateway' --rest-api-id abcdefg123 --stage-name dev --export-type swagger latestswagger2.json
```

 You cannot export an API if its payloads are not of the `application/json` type. If you try, you will get an error response stating that JSON body models are not found. 

## Request to export a REST API
<a name="api-gateway-export-api-request"></a>

 With the Export API, you export an existing REST API by submitting a GET request, specifying the to-be-exported API as part of URL paths. The request URL is of the following format: 

------
#### [ OpenAPI 3.0 ]

```
 https://<host>/restapis/<restapi_id>/stages/<stage_name>/exports/oas30
```

------
#### [ OpenAPI 2.0 ]

```
 https://<host>/restapis/<restapi_id>/stages/<stage_name>/exports/swagger
```

------

 You can append the `extensions` query string to specify whether to include API Gateway extensions (with the `integration` value) or Postman extensions (with the `postman` value). 

 In addition, you can set the `Accept` header to `application/json` or `application/yaml` to receive the API definition output in JSON or YAML format, respectively. 

 For more information about submitting GET requests using the API Gateway Export API, see [GetExport](https://docs.aws.amazon.com/apigateway/latest/api/API_GetExport.html). 

**Note**  
 If you define models in your API, they must be for the content type of "application/json" for API Gateway to export the model. Otherwise, API Gateway throws an exception with the "Only found non-JSON body models for ..." error message.   
 Models must contain properties or be defined as a particular JSONSchema type. 

## Download REST API OpenAPI definition in JSON
<a name="api-gateway-export-api-download-swagger-json"></a>

To export and download a REST API in OpenAPI definitions in JSON format:

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------

 Here, `<region>` could be, for example, `us-east-1`. For all the regions where API Gateway is available, see [Regions and Endpoints](https://docs.aws.amazon.com/general/latest/gr/rande.html#apigateway_region). 

## Download REST API OpenAPI definition in YAML
<a name="api-gateway-export-api-download-swagger-yaml"></a>

To export and download a REST API in OpenAPI definitions in YAML format:

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------

## Download REST API OpenAPI definition with Postman extensions in JSON
<a name="api-gateway-export-api-download-swagger-json-with-postman"></a>

To export and download a REST API in OpenAPI definitions with Postman in JSON format:

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30?extensions=postman
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger?extensions=postman
Host: apigateway.<region>.amazonaws.com
Accept: application/json
```

------

## Download REST API OpenAPI definition with API Gateway integration in YAML
<a name="api-gateway-export-api-download-swagger-yaml-with-apig"></a>

To export and download a REST API in OpenAPI definitions with API Gateway integration in YAML format:

------
#### [ OpenAPI 3.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/oas30?extensions=integrations
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------
#### [ OpenAPI 2.0 ]

```
GET /restapis/<restapi_id>/stages/<stage_name>/exports/swagger?extensions=integrations
Host: apigateway.<region>.amazonaws.com
Accept: application/yaml
```

------

## Export REST API using the API Gateway console
<a name="api-gateway-export-api-from-console"></a>

After [deploying your REST API to a stage](set-up-deployments.md#create-deployment), you can proceed to export the API in the stage to an OpenAPI file using the API Gateway console.

 In the **Stages** pane in the API Gateway console, choose **Stage actions**, **Export**.

![\[Export REST API using the API Gateway console\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/export-new-console.png)


Specify an **API specification type**, **Format**, and **Extensions** to download your API's OpenAPI definition. 

# Publish REST APIs for customers to invoke
<a name="rest-api-publish"></a>

Simply creating and developing an API Gateway API doesn't automatically make it callable by your users. To make it callable, you must deploy your API to a stage. In addition, you might want to customize the URL that your users will use to access your API. You can give it a domain that is consistent with your brand or is more memorable than the default URL for your API.

In this section, you can learn how to deploy your API and customize the URL that you provide to users to access it. 

**Note**  
To augment the security of your API Gateway APIs, the `execute-api.{region}.amazonaws.com` domain is registered in the [Public Suffix List (PSL)](https://publicsuffix.org/). For further security, we recommend that you use cookies with a `__Host-` prefix if you ever need to set sensitive cookies in the default domain name for your API Gateway APIs. This practice will help to defend your domain against cross-site request forgery attempts (CSRF). For more information see the [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes) page in the Mozilla Developer Network.

**Topics**
+ [Deploy REST APIs in API Gateway](how-to-deploy-api.md)
+ [Custom domain name for public REST APIs in API Gateway](how-to-custom-domains.md)

# Deploy REST APIs in API Gateway
<a name="how-to-deploy-api"></a>

 After creating your API, you must deploy it to make it callable by your users. 

To deploy an API, you create an API deployment and associate it with a stage. A stage is a logical reference to a lifecycle state of your API (for example, `dev`, `prod`, `beta`, `v2`). API stages are identified by the API ID and stage name. They're included in the URL that you use to invoke the API. Each stage is a named reference to a deployment of the API and is made available for client applications to call. 

**Important**  
Every time you update an API, you must redeploy the API to an existing stage or to a new stage. Updating an API includes modifying routes, methods, integrations, authorizers, resource policies, and anything else other than stage settings. 

As your API evolves, you can continue to deploy it to different stages as different versions of the API. You can also deploy your API updates as a [canary release deployment](canary-release.md). This enables your API clients to access, on the same stage, the production version through the production release, and the updated version through the canary release. 

To call a deployed API, the client submits a request against an API's URL. The URL is determined by an API's protocol (HTTP(S) or (WSS)), hostname, stage name, and (for REST APIs) resource path. The hostname and the stage name determine the API's base URL. 

Using the API's default domain name, the base URL of a REST API (for example) in a given stage (`{stageName}`) is in the following format:

```
https://{restapi-id}.execute-api.{region}.amazonaws.com/{stageName}
```

 To make the API's default base URL more user-friendly, you can create a custom domain name (for example, `api.example.com`) to replace the default hostname of the API. To support multiple APIs under the custom domain name, you must map an API stage to a base path. 

With a custom domain name of `{api.example.com}` and the API stage mapped to a base path of (`{basePath}`) under the custom domain name, the base URL of a REST API becomes the following: 

```
https://{api.example.com}/{basePath}
```

 For each stage, you can optimize API performance by adjusting the default account-level request throttling limits and enabling API caching. You can also enable logging for API calls to CloudTrail or CloudWatch, and can select a client certificate for the backend to authenticate the API requests. In addition, you can override stage-level settings for individual methods and define stage variables to pass stage-specific environment contexts to the API integration at runtime. 

Stages enable robust version control of your API. For example, you can deploy an API to a `test` stage and a `prod` stage, and use the `test` stage as a test build and use the `prod` stage as a stable build. After the updates pass the test, you can promote the `test` stage to the `prod` stage. The promotion can be done by redeploying the API to the `prod` stage or updating a stage variable value from the stage name of `test` to that of `prod`.

 In this section, we discuss how to deploy an API by using the [API Gateway console](https://console.aws.amazon.com/apigateway) or calling the [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/api/). To use other tools, see the documentation of the [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/apigateway/) or an [AWS SDK](https://aws.amazon.com/developer/tools/#sdk). 

**Topics**
+ [Create a deployment for a REST API in API Gateway](set-up-deployments.md)
+ [Set up a stage for a REST API in API Gateway](set-up-stages.md)
+ [Set up an API Gateway canary release deployment](canary-release.md)
+ [Updates to REST APIs that require redeployment](updating-api.md)

# Create a deployment for a REST API in API Gateway
<a name="set-up-deployments"></a>

 In API Gateway, a REST API deployment is represented by a [Deployment](https://docs.aws.amazon.com/apigateway/latest/api/API_Deployment.html) resource. It's similar to an executable of an API that is represented by a [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) resource. 

For the client to call your API, you must create a deployment and associate a stage with it. A stage is represented by a [Stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html) resource. It represents a snapshot of the API, including methods, integrations, models, mapping templates, and Lambda authorizers (formerly known as custom authorizers). When you update the API, you can redeploy the API by associating a new stage with the existing deployment. We discuss creating a stage in [Set up a stage for a REST API in API Gateway](set-up-stages.md).

**Topics**
+ [Create a deployment](#create-deployment)
+ [Next steps for your API deployment](#apigateway-deployment-next-steps)

## Create a deployment
<a name="create-deployment"></a>

The following procedures show how to create a deployment for a REST API.

------
#### [ AWS Management Console ]

 You must have created a REST API before deploying it for the first time. For more information, see [Develop REST APIs in API Gateway](rest-api-develop.md). 

 The API Gateway console lets you deploy an API by creating a deployment and associating it with a new or existing stage. 

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1.  In the **APIs** navigation pane, choose the API you want to deploy. 

1. In the **Resources** pane, choose **Deploy API**.

1. For **Stage**, select from the following:

   1. To create a new stage, select **New stage**, and then enter a name in **Stage name**. Optionally, you can provide a description for the deployment in **Deployment description**.

   1. To choose an existing stage, select the stage name from the dropdown menu. You might want to provide a description of the new deployment in **Deployment description**.

   1. To create a deployment that is not associated with a stage, select **No stage**. Later, you can associate this deployment with a stage.

1. Choose **Deploy**.

------
#### [ AWS CLI ]

When you create a deployment, you instantiate the [Deployment](https://docs.aws.amazon.com/apigateway/latest/api/API_Deployment.html) resource.

The following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command creates a new deployment:

```
 aws apigateway create-deployment --rest-api-id rest-api-id
```

You can't call the API until you associate this deployment with a stage. With an existing stage, you can do this by updating the stage's [deploymentId](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#deploymentId) property with the newly created deployment ID. The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command updates the stage with a new deployment. In the console, this is called the **Active deployment**.

```
 aws apigateway update-stage \
    --rest-api-id rest-api-id \ 
    --stage-name 'stage-name' \ 
    --patch-operations op='replace',path='/deploymentId',value='deployment-id'
```

When you create your deployment, you can also associate it with a new stage at the same time. The following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command creates a new deployment and associates it with a new stage called `beta`:

```
 aws apigateway create-deployment \
    --rest-api-id rest-api-id \
    --stage-name beta
```

------

To redeploy an API, perform the same steps. You can reuse the same stage.

## Next steps for your API deployment
<a name="apigateway-deployment-next-steps"></a>

The following are next steps for your API deployment.

Modify stage settings  
After an API is deployed, you can modify the stage settings to enable or disable the API cache, logging, or request throttling. You can also choose a client certificate for the backend to authenticate API Gateway and set stage variables to pass deployment context to the API integration at runtime. For more information, see [Modify stage settings](set-up-stages.md#how-to-stage-settings)  
After modifying stage settings, you must redeploy the API for the changes to take effect.  
 If the updated settings, such as enabling logging, requires a new IAM role, you can add the required IAM role without redeploying the API. However, it might take a few minutes before the new IAM role takes effect. Before that happens, traces of your API calls are not logged even if you have enabled the logging option. 

Choose different deployment-stage combinations  
 Because a deployment represents an API snapshot and a stage defines a path into a snapshot, you can choose different deployment-stage combinations to control how users call into different versions of the API. This is useful, for example, when you want to roll back API state to a previous deployment or to merge a 'private branch' of the API into the public one.   
 The following procedure shows how to do this using the **Stage Editor** in the API Gateway console. It is assumed that you must have deployed an API more than once.   

1. If you're not already on the **Stages** pane, in the main navigation pane, choose **Stages**.

1. Select the stage you want to update.

1. On the **Deployment history** tab, select the deployment you want the stage to use. 

1. Choose **Change active deployment**.

1. Confirm you want to change the active deployment and choose **Change active deployment** in the **Make active deployment** dialog box.

Pass deployment-specific data to your API.  
 For a deployment, you can set or modify stage variables to pass deployment-specific data to the API integration at runtime. You can do this on the **Stage Variables** tab in the **Stage Editor**. For more information, see instructions in [Use stage variables for a REST API in API Gateway](stage-variables.md).

# Set up a stage for a REST API in API Gateway
<a name="set-up-stages"></a>

A stage is a named reference to a deployment, which is a snapshot of the API. You use a [Stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html) to manage and optimize a particular deployment. For example, you can configure stage settings to enable caching, customize request throttling, configure logging, define stage variables, or attach a canary release for testing. The following section shows how to create and configure your stage.

## Create a new stage
<a name="how-to-create-stage-console"></a>

 After the initial deployment, you can add more stages and associate them with existing deployments. You can use the API Gateway console to create a new stage, or you can choose an existing stage while deploying an API. In general, you can add a new stage to an API deployment before redeploying the API. To create a new stage using the API Gateway console, follow these steps: 

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the main navigation pane, choose **Stages** under an API.

1. From the **Stages** navigation pane, choose **Create stage**.

1.  For **Stage name**, enter a name, for example, **prod**. 
**Note**  
Stage names can only contain alphanumeric characters, hyphens, and underscores. Maximum length is 128 characters.

1.  (Optional). For **Description**, enter a stage description.

1. For **Deployment**, select the date and time of the existing API deployment you want to associate with this stage.

1. Under **Additional settings**, you can specify additional settings for your stage.

1. Choose **Create stage**.

## Modify stage settings
<a name="how-to-stage-settings"></a>

After a successful deployment of an API, the stage is populated with default settings. You can use the console or the API Gateway REST API to change the stage settings, including API caching and logging. If you've modified the default endpoint of your REST API, when you update a stage, the modification is propagated to all stages of your API. The following steps show you how to do so using the **Stage editor** of the API Gateway console.

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the main navigation pane, choose **Stages** under an API.

1. In the **Stages** pane, choose the name of the stage.

1. In the **Stage details** section, choose **Edit**.

1. (Optional) For **Stage description**, edit the description.

1. For **Additional settings**, you modify the following settings:

     
**Cache settings**  
To enable API caching for the stage, turn on **Provision API cache**. Then configure the **Default method-level caching**, **Cache capacity**, **Encrypt cache data**, **Cache time-to-live (TTL)**, as well as any requirements for per-key cache invalidation.  
Caching is not active until you turn on the default method-level caching or turn on the method-level cache for a specific method.  
For more information about cache settings, see [Cache settings for REST APIs in API Gateway](api-gateway-caching.md).  
If you enable API caching for an API stage, your AWS account might be charged for API caching. Caching isn't eligible for the AWS Free Tier.  
**Throttling settings**  
To set stage-level throttling targets for all of the methods associated with this API, turn on **Throttling**.  
For **Rate**, enter a target rate. This is the rate, in requests per second, that tokens are added to the token bucket. The stage-level rate must not be more than the [account-level](api-gateway-request-throttling.md#apig-request-throttling-account-level-limits) rate as specified in [Quotas for configuring and running a REST API in API Gateway](api-gateway-execution-service-limits-table.md).   
For **Burst**, enter a target burst rate. The burst rate, is the capacity of the token bucket. This allows more requests through for a period of time than the target rate. This stage-level burst rate must not be more than the [account-level](api-gateway-request-throttling.md#apig-request-throttling-account-level-limits) burst rate as specified in [Quotas for configuring and running a REST API in API Gateway](api-gateway-execution-service-limits-table.md).   
Throttling rates are not hard limits, and are applied on a best-effort basis. In some cases, clients can exceed the targets that you set. Don’t rely on throttling to control costs or block access to an API. Consider using [AWS Budgets](https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-managing-costs.html) to monitor costs and [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) to manage API requests.  
**Firewall and certificate settings**  
To associate an AWS WAF web ACL with the stage, select a web ACL from the **Web ACL** dropdown list. If desired, choose **Block API Request if WebACL cannot be evaluated (Fail- Close)**.  
To select a client certificate for your stage, select a certificate from the **Client certificate** dropdown menu.

1. Choose **Continue**.

1. Review your changes and choose **Save changes**.

1. To enable Amazon CloudWatch Logs for all of the methods associated with this stage of this API Gateway API, in the **Logs and tracing** section, choose **Edit**.
**Note**  
To enable CloudWatch Logs, you must also specify the ARN of an IAM role that enables API Gateway to write information to CloudWatch Logs on behalf of your user. To do so, choose **Settings** from the **APIs** main navigation pane. Then, for **CloudWatch log role**, enter the ARN of an IAM role.   
For common application scenarios, the IAM role could attach the managed policy of [AmazonAPIGatewayPushToCloudWatchLogs](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonAPIGatewayPushToCloudWatchLogs.html).  
The IAM role must also contain the following trust relationship statement:  

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Sid": "",
         "Effect": "Allow",
         "Principal": {
           "Service": "apigateway.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```
  
For more information about CloudWatch, see the *[Amazon CloudWatch User Guide](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html)*.

1. Select a logging level from the **CloudWatch Logs** dropdown menu. The logging levels are the following:
   + **Off** – Logging is not turned on for this stage. 
   + **Errors only** – Logging is enabled for errors only. 
   + **Errors and info logs** – Logging is enabled for all events.

1. Select **Data tracing** to have API Gateway report to CloudWatch the data trace logging for your stage. This can be useful to troubleshoot APIs, but can result in logging sensitive data.
**Note**  
We recommend that you don't use **Data tracing** for production APIs.

1. Select **Detailed metrics** to have API Gateway report to CloudWatch the API metrics of `API calls`, `Latency`, `Integration latency`, `400 errors`, and `500 errors`. For more information about CloudWatch, see the [Basic monitoring and detailed monitoring](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-metrics-basic-detailed.html) in the Amazon CloudWatch User Guide.
**Important**  
Your account is charged for accessing method-level CloudWatch metrics, but not the API-level or stage-level metrics.

1. To enable access logging to a destination, turn on **Custom access logging**.

1. For **Access log destination ARN**, enter the ARN of a log group or a Firehose stream. 

   The ARN format for Firehose is `arn:aws:firehose:{region}:{account-id}:deliverystream/amazon-apigateway-{your-stream-name}`. The name of your Firehose stream must be `amazon-apigateway-{your-stream-name}`.

1. In **Log format**, enter a log format. To learn more about example log formats, see [CloudWatch log formats for API Gateway](set-up-logging.md#apigateway-cloudwatch-log-formats).

1. To enable [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-services-apigateway.html) tracing for the API stage, select ** X-Ray tracing**. For more information, see [Trace user requests to REST APIs using X-Ray in API Gateway](apigateway-xray.md).

1. Choose **Save changes**. Redeploy your API for the new settings to take effect.

## Override stage-level settings
<a name="how-to-method-override"></a>

After you customize the stage-level settings, you can override them for each API method. Some of these options might result in additional charges to your AWS account.

1. To configure method overrides, expand the stage under the secondary navigation pane, and then choose a method.  
![\[Expand the stage under the secondary navigation pane, and choose a method.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/method-override-view-new-console.png)

1. For **Method overrides**, choose **Edit**.

1. To turn on method-level CloudWatch settings, for **CloudWatch Logs**, select a logging level.

1. To turn on data trace logging for your method, select **Data tracing**.
**Note**  
We recommend that you don't use **Data tracing** for production APIs.

1. To turn on method-level detailed metrics, select **Detailed metrics**. Your account is charged for accessing method-level CloudWatch metrics, but not the API-level or stage-level metrics.

1. To turn on method-level throttling, select **Throttling**. Enter the appropriate method-level options. To learn more about throttling, see [Throttle requests to your REST APIs for better throughput in API Gateway](api-gateway-request-throttling.md).

1. To configure the method-level cache, select **Enable method cache**. If you change the default method-level caching setting in the **Stage details**, it doesn't affect this setting.

1. Choose **Save**.

# Add an API Gateway REST API as a target for Amazon Bedrock AgentCore Gateway
<a name="mcp-server"></a>

An Amazon Bedrock AgentCore Gateway provides AI agent developers a secure way to expose your API Gateway REST APIs as Model Context Protocol (MCP)-compatible tools. AgentCore Gateway uses targets to define tools. When you add your stage as a target, your Gateway becomes a single MCP URL that enables access to the tools for an agent. For more information, see [API Gateway REST API stages as targets](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-target-api-gateway.html) in the *Amazon Bedrock AgentCore Gateway Developer Guide*.

API Gateway targets connect your AgentCore Gateway to stages of your REST APIs. You can include the entire stage as a target, or select resources. After you create the API Gateway target, AgentCore Gateway translates incoming MCP requests into HTTP requests and handles the response formatting. MCP clients can retrieve API documentation using the `tools/list` method and invoke APIs using the `tools/call` method.

## Considerations
<a name="w2aac15c11c11c34c11b7"></a>

The following considerations might impact your use adding a stage as a target to a AgentCore Gateway:
+ You must already have a AgentCore Gateway.
+ Only public REST APIs are supported.
+ The default endpoint of your API cannot be disabled.
+ Every method of your API must either have an [operation name](https://docs.aws.amazon.com/apigateway/latest/api/API_PutMethod.html#apigw-PutMethod-request-operationName) defined for it, or your need to create a name override when you add your stage as a target. This name is used as the tool name that agents use to interact with your method.
+ You can use `API_KEY`, `NO_AUTH`, or `GATEWAY_IAM_ROLE` credential provider types for Outbound Auth to allow your Gateway to access your API. The `API_KEY` credential provider is defined by AgentCore Gateway. You can use your existing API Gateway API key. For more information, see [Setting up Outbound Auth](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-outbound-auth.html).
+ If you use a Amazon Cognito user pool or Lambda authorizer to control access to your API, MCP clients cannot access it.
+ Your API must be in the same account and Region as your AgentCore Gateway.

## Add a stage of an API as a target for a AgentCore Gateway
<a name="mcp-server-api-gateway"></a>

The following procedure shows how to add a stage of an API as a target for a AgentCore Gateway.

**To add a stage of an API as a target for a AgentCore Gateway**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API that's deployed to a stage.

1. In the main navigation pane, choose **Stages**.

1. Choose **Stage actions**, and then choose **Create MCP target**.

1. For **AgentCore Gateway**, select an AgentCore Gateway.

1. For **Target name**, enter a target name.

1. For **Target description**, enter a description.

1. Keep the provided API and stage.

1. For **Select API resources**, select the resources of your API that agents using your AgentCore Gateway can access.

   If you don't select a resource, an agent cannot view the documentation or invoke the endpoint. 

1. The combination of the resource and the method are the operations for the tool. If your operation does not have a name, create a name override.

   You can also define an operation name for a method when you create it.

1. For **Outbound Auth configuration**, choose either **IAM Role **, **No authorization** or **API key**.

1. Choose **Create target**.

To view all the AgentCore Gateways that have access to your APIs, choose the **MCP targets** section in the main navigation pane. In this section, you can create a MCP target for any API in your Region deployed to a stage. Choose **Create MCP target** and follow the previous steps.

You can also view the available tools for your target and edit your target in the AgentCore Gateway console. For more information, see [Add targets to an existing AgentCore Gateway](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-building-adding-targets.html).

# Delete a stage
<a name="how-to-delete-stage"></a>

When you no longer need a stage, you can delete it to avoid paying for unused resources. The following steps show you how to use the API Gateway console to delete a stage.

**Warning**  
 Deleting a stage might cause part or all of the corresponding API to be unusable by API callers. Deleting a stage cannot be undone, but you can recreate the stage and associate it with the same deployment. 

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the main navigation pane, choose **Stages**.

1. In the **Stages** pane, choose the stage you want to delete, and then choose **Stage actions**, **Delete stage**.

1. When you're prompted, enter **confirm**, and then choose **Delete**.

# Set up tags for an API stage in API Gateway
<a name="set-up-tags"></a>

In API Gateway, you can add a tag to an API stage, remove the tag from the stage, or view the tag. To do this, you can use the API Gateway console, the AWS CLI/SDK, or the API Gateway REST API.

A stage can also inherit tags from its parent REST API. For more information, see [Tag inheritance in the Amazon API Gateway V1 API](apigateway-tagging-supported-resources.md#apigateway-tagging-inheritance).

For more information about tagging API Gateway resources, see [Tagging your API Gateway resources](apigateway-tagging.md).

**Topics**
+ [Set up tags for an API stage using the API Gateway console](#set-up-tags-using-console)
+ [Set up tags for an API stage using the AWS CLI](#set-up-tags-using-cli)
+ [Set up tags for an API stage using the API Gateway REST API](#set-up-tags-using-api)

## Set up tags for an API stage using the API Gateway console
<a name="set-up-tags-using-console"></a>

The following procedure describes how to set up tags for an API stage.

**To set up tags for an API stage by using the API Gateway console**

1. Sign in to the API Gateway console.

1. Choose an existing API, or create a new API that includes resources, methods, and the corresponding integrations.

1. Choose a stage or deploy the API to a new stage.

1. In the main navigation pane, choose **Stages**.

1. Choose the **Tags** tab. You might need to choose the right arrow button to show the tab.

1. Choose **Manage tags**.

1. In the **Tag Editor**, choose **Add tag**. Enter a tag key (for example, `Department`) in the **Key** field, and enter a tag value (for example, `Sales`) in the **Value** field. Choose **Save** to save the tag.

1.  If needed, repeat step 5 to add more tags to the API stage. The maximum number of tags per stage is 50.

1.  To remove an existing tag from the stage, choose **Remove**.

1. If the API has been deployed previously in the API Gateway console, you need to redeploy it for the changes to take effect.

## Set up tags for an API stage using the AWS CLI
<a name="set-up-tags-using-cli"></a>

You can set up tags for an API stage using the AWS CLI using the [create-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-stage.html) command or the [tag-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/tag-resource.html) command. You can delete one or more tags from an API stage using the [untag-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/untag-resource.html) command. 

The following [create-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-stage.html) command adds a tag when creating a `test` stage:

```
aws apigateway create-stage --rest-api-id abc1234 --stage-name test --description 'Testing stage' --deployment-id efg456 --tag Department=Sales
```

The following [tag-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/tag-resource.html) command adds a tag to a `prod` stage:

```
aws apigateway tag-resource --resource-arn arn:aws:apigateway:us-east-2::/restapis/abc123/stages/prod --tags Department=Sales
```

The following [untag-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/untag-resource.html) command removes the `Department=Sales` tag from the `test` stage:

```
aws apigateway untag-resource --resource-arn arn:aws:apigateway:us-east-2::/restapis/abc123/stages/test --tag-keys Department 
```

## Set up tags for an API stage using the API Gateway REST API
<a name="set-up-tags-using-api"></a>

You can set up tags for an API stage using the API Gateway REST API by doing one of the following:
+ Call [https://docs.aws.amazon.com/apigateway/latest/api/API_TagResource.html](https://docs.aws.amazon.com/apigateway/latest/api/API_TagResource.html) to tag an API stage.
+  Call [https://docs.aws.amazon.com/apigateway/latest/api/API_UntagResource.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UntagResource.html) to delete one or more tags from an API stage.
+ Call [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateStage.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateStage.html) to add one or more tags to an API stage that you're creating.

You can also call [https://docs.aws.amazon.com/apigateway/latest/api/API_GetTags.html](https://docs.aws.amazon.com/apigateway/latest/api/API_GetTags.html) to describe tags in an API stage.

### Tag an API stage
<a name="tag-a-stage-using-api"></a>

After you deploy an API (`m5zr3vnks7`) to a stage (`test`), tag the stage by calling [https://docs.aws.amazon.com/apigateway/latest/api/API_TagResource.html](https://docs.aws.amazon.com/apigateway/latest/api/API_TagResource.html). The required stage Amazon Resource Name (ARN) (`arn:aws:apigateway:us-east-1::/restapis/m5zr3vnks7/stages/test`) must be URL encoded (`arn%3Aaws%3Aapigateway%3Aus-east-1%3A%3A%2Frestapis%2Fm5zr3vnks7%2Fstages%2Ftest`). 

```
PUT /tags/arn%3Aaws%3Aapigateway%3Aus-east-1%3A%3A%2Frestapis%2Fm5zr3vnks7%2Fstages%2Ftest

{
  "tags" : {
    "Department" : "Sales"
  }
}
```

 You can also use the previous request to update an existing tag to a new value. 

You can add tags to a stage when calling [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateStage.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateStage.html) to create the stage:

```
POST /restapis/<restapi_id>/stages

{
  "stageName" : "test",
  "deploymentId" : "adr134",
  "description" : "test deployment",
  "cacheClusterEnabled" : "true",
  "cacheClusterSize" : "500",
  "variables" : {
    "sv1" : "val1"
  },
  "documentationVersion" : "test",

  "tags" : {
    "Department" : "Sales",
    "Division" : "Retail"
  }
}
```

### Untag an API stage
<a name="untag-a-stage-using-api"></a>

 To remove the `Department` tag from the stage, call [https://docs.aws.amazon.com/apigateway/latest/api/API_UntagResource.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UntagResource.html): 

```
DELETE /tags/arn%3Aaws%3Aapigateway%3Aus-east-1%3A%3A%2Frestapis%2Fm5zr3vnks7%2Fstages%2Ftest?tagKeys=Department
Host: apigateway.us-east-1.amazonaws.com
Authorization: ...
```

 To remove more than one tag, use a comma-separated list of tag keys in the query expression—for example, `?tagKeys=Department,Division,…`. 

### Describe tags for an API stage
<a name="get-tags-using-api"></a>

To describe existing tags on a given stage, call [https://docs.aws.amazon.com/apigateway/latest/api/API_GetTags.html](https://docs.aws.amazon.com/apigateway/latest/api/API_GetTags.html):

```
GET /tags/arn%3Aaws%3Aapigateway%3Aus-east-1%3A%3A%2Frestapis%2Fm5zr3vnks7%2Fstages%2Ftags
Host: apigateway.us-east-1.amazonaws.com
Authorization: ...
```

The successful response is similar to the following:

```
200 OK

{
    "_links": {
        "curies": {
            "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-tags-{rel}.html",
            "name": "tags",
            "templated": true
        },
        "tags:tag": {
            "href": "/tags/arn%3Aaws%3Aapigateway%3Aus-east-1%3A%3A%2Frestapis%2Fm5zr3vnks7%2Fstages%2Ftags"
        },
        "tags:untag": {
            "href": "/tags/arn%3Aaws%3Aapigateway%3Aus-east-1%3A%3A%2Frestapis%2Fm5zr3vnks7%2Fstages%2Ftags{?tagKeys}",
            "templated": true
        }
    },
    "tags": {
        "Department": "Sales"
    }
}
```

# Use stage variables for a REST API in API Gateway
<a name="stage-variables"></a>

Stage variables are key-value pairs that you can define as configuration attributes associated with a deployment stage of a REST API. They act like environment variables and can be used in your API setup and mapping templates. With deployment stages in API Gateway, you can manage multiple release stages for each API and use stage variables you can configure an API deployment stage to interact with different backend endpoints.

Stage variables are not intended to be used for sensitive data, such as credentials. To pass sensitive data to integrations, use an AWS Lambda authorizer. You can pass sensitive data to integrations in the output of the Lambda authorizer. To learn more, see [Output from an API Gateway Lambda authorizer](api-gateway-lambda-authorizer-output.md).

## Use cases for stage variables
<a name="use-cases"></a>

The following are use cases for your stage variables.

**Specify a different backend endpoint**  
Your API can pass a `GET` request as an HTTP proxy to the backend web host. You can use a stage variable so that when API callers invoke your production endpoint, API Gateway calls `example.com`. Then, when API callers invoke the beta stage, API Gateway calls a different web host, such as `beta.example.com`. Similarly, stage variables can be used to specify a different AWS Lambda function name for each stage in your API. You can't use a stage variable to set a different integration endpoint, such as pointing the `GET` request to an HTTP proxy integration in one stage and a Lambda proxy integration in another stage.  
When specifying a Lambda function name as a stage variable value, you must configure the permissions on the Lambda function manually. When you specify a Lambda function in the API Gateway console, a AWS CLI command will pop-up to configure the proper permissions. You can also use the following AWS CLI command to do this.  

```
aws lambda add-permission --function-name "arn:aws:lambda:us-east-2:123456789012:function:my-function" --source-arn "arn:aws:execute-api:us-east-2:123456789012:api_id/*/HTTP_METHOD/resource" --principal apigateway.amazonaws.com --statement-id apigateway-access --action lambda:InvokeFunction
```

**Pass information using mapping templates**  
You can access stage variables in the mapping templates, or pass configuration parameters to your AWS Lambda or HTTP backend. For example, you might want to reuse the same Lambda function for multiple stages in your API, but the function should read data from a different Amazon DynamoDB table depending on the stage. In the mapping templates that generate the request for the Lambda function, you can use stage variables to pass the table name to Lambda.

To use a stage variable, you first configure a stage variable, and then you assign it a value. For example, to customize the HTTP integration endpoint, first create the `url` stage variable, and then in your API's integration request, enter the stage variable value, **http://\$1\$1stageVariables.url\$1**. This value tells API Gateway to substitute your stage variable `${}` at runtime, depending on which stage your API is running. For more information, see [Set up stage variables for REST APIs in API Gateway](how-to-set-stage-variables-aws-console.md). 

# Set up stage variables for REST APIs in API Gateway
<a name="how-to-set-stage-variables-aws-console"></a>

This section shows how to set up various stage variables for two deployment stages of a sample API by using the Amazon API Gateway console. To understand how to use stage variables in API Gateway, we recommend that you follow all procedures in this section.

## Prerequisites
<a name="how-to-set-stage-variables-aws-console-prerequisites"></a>

Before you begin, make sure the following prerequisites are met: 
+ You must have an API available in API Gateway. Follow the instructions in [Develop REST APIs in API Gateway](rest-api-develop.md).
+ You must have deployed the API at least once. Follow the instructions in [Deploy REST APIs in API Gateway](how-to-deploy-api.md).
+ You must have created the first stage for a deployed API. Follow the instructions in [Create a new stage](set-up-stages.md#how-to-create-stage-console).

  

## Invoke an HTTP endpoint through an API with a stage variable
<a name="how-to-set-stage-variables-aws-console-http-endpoint"></a>

This procedure describes how to create a stage variable for an HTTP endpoint and two stages for your API. In addition, you create the stage variables, `url`, `stageName`, and `function` that are used in the following procedures in this section.

**To invoke an HTTP endpoint through an API with a stage variable**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Create an API, and then create a `GET` method on the API's root resource. Set the integration type to **HTTP** and set the **Endpoint URL** to **http://\$1\$1stageVariables.url\$1**.

1. Deploy the API to a new stage named **beta**. 

1. In the main navigation pane, choose **Stages**, and then select the **beta** stage. 

1. On the **Stage variables** tab, choose **Edit**.

1. Choose **Add stage variable**.

1. For **Name**, enter **url**. For **value**, enter **httpbin.org/get**.

1. Choose **Add stage variable**, and then do the following:

   For **Name**, enter **stageName**. For **value**, enter **beta**.

1. Choose **Add stage variable**, and then do the following:

   For **Name**, enter **function**. For **value**, enter **HelloWorld**.

1. Choose **Save**.

1.  Now create a second stage. From the **Stages** navigation pane, choose **Create stage**. For **Stage name**, enter **prod**. Select a recent deployment from **Deployment**, and then choose **Create stage**.

1.  As with the **beta** stage, set the same three stage variables (**url**, **stageName**, and **function**) to different values (**petstore-demo-endpoint.execute-api.com/petstore/pets**, **prod**, and **HelloEveryone**), respectively. 

1. In the **Stages** navigation pane, choose **beta**. Under **Stage details**, choose the copy icon to copy your API's invoke URL, and then enter your API's invoke URL in a web browser. This starts the **beta** stage `GET` request on the root resource of the API. 
**Note**  
The **Invoke URL** link points to the root resource of the API in its **beta** stage. Entering the URL in a web browser calls the **beta** stage `GET` method on the root resource. If methods are defined on child resources and not on the root resource itself, entering the URL in a web browser returns a `{"message":"Missing Authentication Token"}` error response. In this case, you must append the name of a specific child resource to the **Invoke URL** link. 

1. The response you get from the **beta** stage `GET` request is shown next. You can also verify the result by using a browser to navigate to **http://httpbin.org/get**. This value was assigned to the `url` variable in the **beta** stage. The two responses are identical. 

1. In the **Stages** navigation pane, choose the **prod** stage. Under **Stage details**, choose the copy icon to copy your API's invoke URL, and then enter your API's invoke URL in a web browser. This starts the **prod** stage `GET` request on the root resource of the API. 

1. The response you get from the **prod** stage `GET` request is shown next. You can verify the result by using a browser to navigate to **http://petstore-demo-endpoint.execute-api.com/petstore/pets**. This value was assigned to the `url` variable in the **prod** stage. The two responses are identical. 

## Pass stage-specific metadata into an HTTP backend
<a name="how-to-set-stage-variables-aws-console-stage-metadata"></a>

This procedure describes how to use a stage variable value in a query parameter expression to pass stage-specific metadata into an HTTP backend. We will use the `stageName` stage variable declared in the previous procedure.

**To pass stage-specific metadata into an HTTP backend**

1. In the **Resource** navigation pane, choose the **GET** method. 

   To add a query string parameter to the method's URL, choose the **Method request** tab, and then in the **Method request settings** section, choose **Edit**. 

1. Choose **URL query string parameters** and do the following:

   1. Choose **Add query string**.

   1. For **Name**, enter **stageName**.

   1. Keep **Required** and **Caching** turned off.

1. Choose **Save**.

1. Choose the **Integration request** tab, and then in the **Integration request settings** section, choose **Edit**.

1. For **Endpoint URL**, append **?stageName=\$1\$1stageVariables.stageName\$1** to the previously defined URL value, so the entire **Endpoint URL** is **http://\$1\$1stageVariables.url\$1?stageName=\$1\$1stageVariables.stageName\$1**.

1. Choose **Deploy API** and select the **beta** stage.

1. In the main navigation pane, choose **Stages**. In the **Stages** navigation pane, choose **beta**. Under **Stage details**, choose the copy icon to copy your API's invoke URL, and then enter your API's invoke URL in a web browser. 
**Note**  
 We use the beta stage here because the HTTP endpoint (as specified by the `url` variable "http://httpbin.org/get") accepts query parameter expressions and returns them as the `args` object in its response. 

1. You get the following response. Notice that `beta`, assigned to the `stageName` stage variable, is passed in the backend as the `stageName` argument. 

      
![\[Response from the API's GET method with an HTTP endpoint using the url stage variable.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/stageVariables-new-console-invoke-beta-stage-with-url-and-stageName-response.png)

## Invoke a Lambda function through an API with a stage variable
<a name="how-to-set-stage-variables-aws-console-lambda-function"></a>

This procedure describes how to use a stage variable to call a Lambda function as a backend of your API. You use the `function` stage variable declared in [Invoke an HTTP endpoint through an API with a stage variable](#how-to-set-stage-variables-aws-console-http-endpoint).

 When setting a Lambda function as the value of a stage variable, use the function's local name, possibly including its alias or version specification, as in **HelloWorld**, **HelloWorld:1** or **HelloWorld:alpha**. Do not use the function's ARN (for example, **arn:aws:lambda:us-east-1:123456789012:function:HelloWorld**). The API Gateway console assumes the stage variable value for a Lambda function as the unqualified function name and expands the given stage variable into an ARN. 

**To invoke a Lambda function through an API with a stage variable**

1. Create a Lambda function named **HelloWorld** using the default Node.js runtime. The code must contain the following:

   ```
   export const handler = function(event, context, callback) {
       if (event.stageName)
           callback(null, 'Hello, World! I\'m calling from the ' + event.stageName + ' stage.');
       else
           callback(null, 'Hello, World! I\'m not sure where I\'m calling from...');
   };
   ```

   For more information on how to create a Lambda function, see [Getting started with the REST API console](getting-started-rest-new-console.md#getting-started-rest-new-console-create-function).

1. In the **Resources** pane, select **Create resource**, and then do the following:

   1. For **Resource path**, select **/**.

   1. For **Resource name**, enter **lambdav1**.

   1. Choose **Create resource**.

1. Choose the **/lambdav1** resource, and then choose **Create method**.

   Then, do the following:

   1. For **Method type**, select **GET**.

   1. For **Integration type**, select **Lambda function**.

   1. Keep **Lambda proxy integration** turned off.

   1. For **Lambda function**, enter `${stageVariables.function}`.  
![\[Create a GET method integrated with a Lambda function as specified by the function stage variable.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/stageVariables-new-console-create-lambda-get-method.png)
**Tip**  
When prompted with the **Add permission command**, copy the [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command. Run the command on each Lambda function that will be assigned to the `function` stage variable. For example, if the `$stageVariables.function` value is `HelloWorld`, run the following AWS CLI command:   

      ```
      aws lambda add-permission --function-name arn:aws:lambda:us-east-1:account-id:function:HelloWorld --source-arn arn:aws:execute-api:us-east-1:account-id:api-id/*/GET/lambdav1 --principal apigateway.amazonaws.com --statement-id statement-id-guid --action lambda:InvokeFunction
      ```
 Failing to do so results in a `500 Internal Server Error` response when invoking the method. Replace `${stageVariables.function}` with the Lambda function name that is assigned to the stage variable.   
   

![\[AWS CLI command to add permission to the Lambda function to be invoked by the method you created.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/stageVariables-new-console-add-permission-to-lambda-function.png)


   1. Choose **Create method**.

1. Deploy the API to both the **prod** and **beta** stages.

1. In the main navigation pane, choose **Stages**. In the **Stages** navigation pane, choose **beta**. Under **Stage details**, choose the copy icon to copy your API's invoke URL, and then enter your API's invoke URL in a web browser. Append **/lambdav1** to the URL before you press enter.

   You get the following response.

   ```
   "Hello, World! I'm not sure where I'm calling from..."
   ```

## Pass stage-specific metadata to a Lambda function through a stage variable
<a name="pass-version-info-to-lambda-backend-with-stage-variable"></a>

This procedure describes how to use a stage variable to pass stage-specific configuration metadata into a Lambda function. You create a `POST` method and an input mapping template to generate payload using the `stageName` stage variable you declared earlier.

**To pass stage-specific metadata to a Lambda function through a stage variable**

1. Choose the **/lambdav1** resource, and then choose **Create method**.

   Then, do the following:

   1. For **Method type**, select **POST**.

   1. For **Integration type**, select **Lambda function**.

   1. Keep **Lambda proxy integration** turned off.

   1. For **Lambda function**, enter `${stageVariables.function}`.

   1. When prompted with the **Add permission command**, copy the the [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command. Run the command on each Lambda function that will be assigned to the `function` stage variable.

   1. Choose **Create method**.

1. Choose the **Integration request** tab, and then in the **Integration request settings** section, choose **Edit**.

1. Choose **Mapping templates**, and then choose **Add mapping template**.

1. For **Content type**, enter **application/json**.

1. For **Template body**, enter the following template:

   ```
   #set($inputRoot = $input.path('$'))
   {
       "stageName" : "$stageVariables.stageName"
   }
   ```
**Note**  
 In a mapping template, a stage variable must be referenced within quotes (as in `"$stageVariables.stageName"` or `"${stageVariables.stageName}"`). In other places, it must be referenced without quotes (as in `${stageVariables.function}`). 

1. Choose **Save**.

1. Deploy the API to both the **beta** and **prod** stages.

1. To use a REST API client to pass stage-specific metadata, do the following:

   1. In the **Stages** navigation pane, choose **beta**. Under **Stage details**, choose the copy icon to copy your API's invoke URL, and then enter your API's invoke URL in the input field of a REST API client. Append **/lambdav1** before you submit your request.

      You get the following response.

      ```
      "Hello, World! I'm calling from the beta stage."
      ```

   1. In the **Stages** navigation pane, choose **prod**. Under **Stage details**, choose the copy icon to copy your API's invoke URL, and then enter your API's invoke URL in the input field of a REST API client. Append **/lambdav1** before you submit your request.

      You get the following response.

      ```
      "Hello, World! I'm calling from the prod stage."
      ```

1. To use the **Test** feature to pass stage-specific metadata, do the following:

   1. In the **Resources** navigation pane, choose the **Test** tab. You might need to choose the right arrow button to show the tab.

   1. For **function**, enter **HelloWorld**.

   1. For **stageName**, enter **beta**.

   1. Choose **Test**. You do not need to add a body to your `POST` request.

      You get the following response.

      ```
      "Hello, World! I'm calling from the beta stage."
      ```

   1. You can repeat the previous steps to test the **Prod** stage. For **stageName**, enter **Prod**.

      You get the following response.

      ```
      "Hello, World! I'm calling from the prod stage."
      ```

# API Gateway stage variables reference for REST APIs in API Gateway
<a name="aws-api-gateway-stage-variables-reference"></a>

 You can use API Gateway stage variables in the following cases.

## Parameter mapping expressions
<a name="stage-variables-in-parameter-mapping-expressions"></a>

A stage variable can be used in a parameter mapping expression for an API method's request or response header parameter, without any partial substitution. In the following example, the stage variable is referenced without the `$` and the enclosing `{...}`. 
+ `stageVariables.<variable_name>`

## Mapping templates
<a name="stage-variables-in-mapping-templates"></a>

 A stage variable can be used anywhere in a mapping template, as shown in the following examples. 
+  `{ "name" : "$stageVariables.<variable_name>"}`
+ `{ "name" : "${stageVariables.<variable_name>}"}`

## HTTP integration URIs
<a name="stage-variables-in-integration-HTTP-uris"></a>

A stage variable can be used as part of an HTTP integration URL, as shown in the following examples:
+ A full URI without protocol – `http://${stageVariables.<variable_name>}`
+ A full domain – `http://${stageVariables.<variable_name>}/resource/operation`
+ A subdomain – `http://${stageVariables.<variable_name>}.example.com/resource/operation`
+ A path – `http://example.com/${stageVariables.<variable_name>}/bar`
+ A query string – `http://example.com/foo?q=${stageVariables.<variable_name>}` 

## AWS integration URIs
<a name="stage-variables-in-integration-aws-uris"></a>

 A stage variable can be used as part of AWS URI action or path components, as shown in the following example.
+ `arn:aws:apigateway:<region>:<service>:${stageVariables.<variable_name>}`

## AWS integration URIs (Lambda functions)
<a name="stage-variables-in-integration-lambda-functions"></a>

 A stage variable can be used in place of a Lambda function name, or version/alias, as shown in the following examples. 
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:${stageVariables.<function_variable_name>}/invocations`
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:<function_name>:${stageVariables.<version_variable_name>}/invocations`

**Note**  
To use a stage variable for a Lambda function, the function must be in the same account as the API. Stage variables don't support cross-account Lambda functions.

## Amazon Cognito user pool
<a name="stage-variables-in-integration-lambda-functions"></a>

A stage variable can be used in place of a Amazon Cognito user pool for a `COGNITO_USER_POOLS` authorizer.
+ `arn:aws:cognito-idp:<region>:<account_id>:userpool/${stageVariables.<variable_name>}`

## AWS integration credentials
<a name="stage-variables-in-integration-aws-credentials"></a>

 A stage variable can be used as part of AWS user/role credential ARN, as shown in the following example. 
+  `arn:aws:iam::<account_id>:${stageVariables.<variable_name>}` 

# Set up an API Gateway canary release deployment
<a name="canary-release"></a>

[Canary release](https://martinfowler.com/bliki/CanaryRelease.html) is a software development strategy in which a new version of an API (as well as other software) is deployed for testing purposes, and the base version remains deployed as a production release for normal operations on the same stage. For purposes of discussion, we refer to the base version as a production release in this documentation. Although this is reasonable, you are free to apply canary release on any non-production version for testing.

In a canary release deployment, total API traffic is separated at random into a production release and a canary release with a pre-configured ratio. Typically, the canary release receives a small percentage of API traffic and the production release takes up the rest. The updated API features are only visible to API traffic through the canary. You can adjust the canary traffic percentage to optimize test coverage or performance. 

By keeping canary traffic small and the selection random, most users are not adversely affected at any time by potential bugs in the new version, and no single user is adversely affected all the time.

After the test metrics pass your requirements, you can promote the canary release to the production release and disable the canary from the deployment. This makes the new features available in the production stage. 

**Topics**
+ [Canary release deployment in API Gateway](#api-gateway-canary-release-deployment-overview)
+ [Create a canary release deployment](create-canary-deployment.md)
+ [Update a canary release](update-canary-deployment.md)
+ [Promote a canary release](promote-canary-deployment.md)
+ [Turn off a canary release](delete-canary-deployment.md)

## Canary release deployment in API Gateway
<a name="api-gateway-canary-release-deployment-overview"></a>

 In API Gateway, a canary release deployment uses the deployment stage for the production release of the base version of an API, and attaches to the stage a canary release for the new versions, relative to the base version, of the API. The stage is associated with the initial deployment and the canary with subsequent deployments. At the beginning, both the stage and the canary point to the same API version. We use stage and production release interchangeably and use canary and canary release interchangeably throughout this section.

To deploy an API with a canary release, you create a canary release deployment by adding [canary settings](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings) to the [stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html) of a regular [deployment](https://docs.aws.amazon.com/apigateway/latest/api/API_Deployment.html). The canary settings describe the underlying canary release and the stage represents the production release of the API within this deployment. To add canary settings, set `canarySettings` on the deployment stage and specify the following: 
+  A deployment ID, initially identical to the ID of the base version deployment set on the stage. 
+  A [percentage of API traffic](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#percentTraffic), between 0.0 and 100.0 inclusive, for the canary release. 
+  [Stage variables for the canary release](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#stageVariableOverrides) that can override production release stage variables. 
+  The [use of the stage cache](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#useStageCache) for canary requests, if the [useStageCache](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#useStageCache) is set and API caching is enabled on the stage.

 After a canary release is enabled, the deployment stage cannot be associated with another non-canary release deployment until the canary release is disabled and the canary settings removed from the stage. 

When you enable API execution logging, the canary release has its own logs and metrics generated for all canary requests. They are reported to a production stage CloudWatch Logs log group as well as a canary-specific CloudWatch Logs log group. The same applies to access logging. The separate canary-specific logs are helpful to validate new API changes and decide whether to accept the changes and promote the canary release to the production stage, or to discard the changes and revert the canary release from the production stage.

The production stage execution log group is named `API-Gateway-Execution-Logs/{rest-api-id}/{stage-name}` and the canary release execution log group is named `API-Gateway-Execution-Logs/{rest-api-id}/{stage-name}/Canary`. For access logging, you must create a new log group or choose an existing one. The canary release access log group name has the `/Canary` suffix appended to the selected log group name. 

A canary release can use the stage cache, if enabled, to store responses and use cached entries to return results to the next canary requests, within a pre-configured time-to-live (TTL) period. 

In a canary release deployment, the production release and canary release of the API can be associated with the same version or with different versions. When they are associated with different versions, responses for production and canary requests are cached separately and the stage cache returns corresponding results for production and canary requests. When the production release and canary release are associated with the same deployment, the stage cache uses a single cache key for both types of requests and returns the same response for the same requests from the production release and canary release. 

# Create a canary release deployment
<a name="create-canary-deployment"></a>

You create a canary release deployment when deploying the API with [canary settings](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateDeployment.html#canarySettings) as an additional input to the [deployment creation](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateDeployment.html) operation. 

You can also create a canary release deployment from an existing non-canary deployment by making a [https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html) request to add the canary settings on the stage.

When creating a non-canary release deployment, you can specify a non-existing stage name. API Gateway creates one if the specified stage does not exist. However, you cannot specify any non-existing stage name when creating a canary release deployment. You will get an error and API Gateway will not create any canary release deployment. 

 You can create a canary release deployment in API Gateway using the API Gateway console, the AWS CLI, or an AWS SDK.

**Topics**
+ [Create a canary deployment using the API Gateway console](#create-canary-deployment-using-console)
+ [Create a canary deployment using the AWS CLI](#create-canary-deployment-using-cli)

## Create a canary deployment using the API Gateway console
<a name="create-canary-deployment-using-console"></a>

To use the API Gateway console to create a canary release deployment, follow the instructions below:<a name="to-create-canary-release-on-new-deployment"></a>

**To create the initial canary release deployment**

1.  Sign in to the API Gateway console.

1.  Choose an existing REST API or create a new REST API.

1.  In the main navigation pane, choose **Resources**, and then choose **Deploy API**. Follow the on-screen instructions in **Deploy API** to deploy the API to a new stage. 

   So far, you have deployed the API to a production release stage. Next, you configure canary settings on the stage and, if needed, also enable caching, set stage variables, or configure API execution or access logs.

1.  To enable API caching or associate an AWS WAF web ACL with the stage, in the **Stage details** section, choose **Edit**. For more information, see [Cache settings for REST APIs in API Gateway](api-gateway-caching.md) or [To associate an AWS WAF web ACL with an API Gateway API stage using the API Gateway console](apigateway-control-access-aws-waf.md#apigateway-control-access-aws-waf-console).

1.  To configure execution or access logging, in the **Logs and tracing** section, choose **Edit** and follow the on-screen instructions. For more information, see [Set up CloudWatch logging for REST APIs in API Gateway](set-up-logging.md).

1. To set stage variables, choose the **Stage variables** tab and follow the on-screen instructions to add or modify stage variables. For more information, see [Use stage variables for a REST API in API Gateway](stage-variables.md).

1.  Choose the **Canary** tab, and then choose **Create canary**. You might need to choose the right arrow button to show the **Canary** tab.

1.  Under **Canary settings**, for **Canary**, enter the percentage of requests to be diverted to the canary.

1. If desired, select **Stage cache** to turn on caching for the canary release. The cache is not available for the canary release until API caching is enabled.

1. To override existing stage variables, for **Canary override**, enter a new stage variable value.

After the canary release is initialized on the deployment stage, you change the API and want to test the changes. You can redeploy the API to the same stage so that both the updated version and the base version are accessible through the same stage. The following steps describe how to do that. <a name="to-deploy-latest-api-to-canary-release"></a>

**To deploy the latest API version to a canary**

1.  With each update of the API, choose **Deploy API**.

1.  In **Deploy API**, choose the stage that contains a canary from the **Deployment stage** dropdown list. 

1.  (Optional) Enter a description for **Deployment description**. 

1.  Choose **Deploy** to push the latest API version to the canary release.

1.  If desired, reconfigure the stage settings, logs, or canary settings, as describe in [To create the initial canary release deployment](#to-create-canary-release-on-new-deployment).

 As a result, the canary release points to the latest version while the production release still points to the initial version of the API. The [https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings) now has a new **deploymentId** value, whereas the stage still has the initial [https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#deploymentId](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#deploymentId) value. Behind the scenes, the console calls [https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html).

## Create a canary deployment using the AWS CLI
<a name="create-canary-deployment-using-cli"></a>

**To create a canary deployment for a new stage**

1. Use the following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to create a deployment with two stage variables, but without a canary:

   ```
   aws apigateway create-deployment \
       --variables sv0=val0,sv1=val1 \
       --rest-api-id abcd1234 \
       --stage-name 'prod'
   ```

   The output will look like the following:

   ```
   {
       "id": "du4ot1", 
       "createdDate": 1511379050
   }
   ```

1. Use the following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to create a canary deployment on the `prod` stage:

   ```
   aws apigateway create-deployment \
       --rest-api-id abcd1234 \
       --canary-settings percentTraffic=10.5,stageVariableOverrides={sv1='val2',sv2='val3'},useStageCache=false \
       --stage-name 'prod'
   ```

   The output will look like the following:

   ```
   {
       "id": "a6rox0", 
       "createdDate": 1511379433
   }
   ```

   The resulting deployment `id` identifies the test version of the API for the canary release. As a result, the associated stage is canary-enabled.

1. (Optional) Use the following [get-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-stage.html) command to view the stage representation:

   ```
   aws apigateway get-stage --rest-api-id acbd1234 --stage-name prod
   ```

   The following shows a representation of the `Stage` as the output of the command:

   ```
   {
       "stageName": "prod", 
       "variables": {
           "sv0": "val0", 
           "sv1": "val1"
       }, 
       "cacheClusterEnabled": false, 
       "cacheClusterStatus": "NOT_AVAILABLE", 
       "deploymentId": "du4ot1", 
       "lastUpdatedDate": 1511379433, 
       "createdDate": 1511379050, 
       "canarySettings": {
           "percentTraffic": 10.5, 
           "deploymentId": "a6rox0", 
           "useStageCache": false, 
           "stageVariableOverrides": {
               "sv2": "val3", 
               "sv1": "val2"
           }
       }, 
       "methodSettings": {}
   }
   ```

   In this example, the base version of the API will use the stage variables of `{"sv0":val0", "sv1":val1"}`, while the test version uses the stage variables of `{"sv1":val2", "sv2":val3"}`. Both the production release and canary release use the same stage variable of `sv1`, but with different values, `val1` and `val2`, respectively. The stage variable of `sv0` is used solely in the production release and the stage variable of `sv2` is used in the canary release only. 

You can also create a canary release deployment from an existing regular deployment by updating the stage to enable a canary.

**To create a canary release deployment from an existing deployment**

1. Use the [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to create a deployment without a canary:

   ```
   aws apigateway create-deployment \
       --variables sv0=val0,sv1=val1 \  
       --rest-api-id abcd1234 \
       --stage-name 'beta'
   ```

1. Use the [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command to update the stage to enable a canary:

   ```
   aws apigateway update-stage \
       --rest-api-id abcd1234 \
       --stage-name 'beta' \
       --patch-operations '[{
               "op": "replace",
               "value": "0.0",
               "path": "/canarySettings/percentTraffic"
           }, {
               "op": "copy",
               "from": "/canarySettings/stageVariableOverrides",
               "path": "/variables"
           }, {
               "op": "copy",
               "from": "/canarySettings/deploymentId",
               "path": "/deploymentId"
           }]'
   ```

   The output will look like the following:

   ```
   {
       "stageName": "beta", 
       "variables": {
           "sv0": "val0", 
           "sv1": "val1"
       }, 
       "cacheClusterEnabled": false, 
       "cacheClusterStatus": "NOT_AVAILABLE", 
       "deploymentId": "cifeiw", 
       "lastUpdatedDate": 1511381930, 
       "createdDate": 1511380879, 
       "canarySettings": {
           "percentTraffic": 10.5, 
           "deploymentId": "cifeiw", 
           "useStageCache": false, 
           "stageVariableOverrides": {
               "sv2": "val3", 
               "sv1": "val2"
           }
       }, 
       "methodSettings": {}
   }
   ```

   Because you enabled a canary on an existing version of the API, both the production release (`Stage`) and canary release (`canarySettings`) point to the same deployment. After you change the API and deploy it to this stage again, the new version will be in the canary release, while the base version remains in the production release. This is manifested in the stage evolution when the `deploymentId` in the canary release is updated to the new deployment `id` and the `deploymentId` in the production release remains unchanged.

# Update a canary release
<a name="update-canary-deployment"></a>

 After a canary release is deployed, you may want to adjust the percentage of the canary traffic or enable or disable the use of a stage cache to optimize the test performance. You can also modify stage variables used in the canary release when the execution context is updated. To make such updates, call the [https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html) operation with new values on [canarySettings](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings). 

You can update a canary release using the API Gateway console, the AWS CLI [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command or an AWS SDK.

**Topics**
+ [Update a canary release using the API Gateway console](#update-canary-deployment-using-console)
+ [Update a canary release using the AWS CLI](#update-canary-deployment-using-cli)

## Update a canary release using the API Gateway console
<a name="update-canary-deployment-using-console"></a>

To use the API Gateway console to update existing canary settings on a stage, do the following:

**To update existing canary settings**

1.  Sign in to the API Gateway console and choose an existing REST API.

1.  In the main navigation pane, choose **Stages**, and then choose an existing stage.

1.  Choose the **Canary** tab, and then choose **Edit**. You might need to choose the right arrow button to show the **Canary** tab. 

1.  Update the **Request distribution** by increasing or decreasing the percentage number between 0.0 and 100.0, inclusive. 

1.  Select or clear the **Stage cache** the check box. 

1.  Add, remove, or modify **Canary stage variables**.

1.  Choose **Save**.

## Update a canary release using the AWS CLI
<a name="update-canary-deployment-using-cli"></a>

To use the AWS CLI to update a canary, use the [https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command and modify the patch operation for each parameter of the canary.

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command updates if the canary uses the stage cache:

```
aws apigateway update-stage \
    --rest-api-id {rest-api-id} \
    --stage-name '{stage-name}' \
    --patch-operations op=replace,path=/canarySettings/useStageCache,value=true
```

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command updates the canary traffic percentage:

```
aws apigateway update-stage \
    --rest-api-id {rest-api-id} \
    --stage-name '{stage-name}' \
    --patch-operations op=replace,path=/canarySettings/percentTraffic,value=25.0
```

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) updates stage variables. The example shows how to create a new stage variable named `newVar`, override the `var2` stage variable, and remove the `var1` stage variable:

```
aws apigateway update-stage  \
    --rest-api-id {rest-api-id} \
    --stage-name '{stage-name}'  \
    --patch-operations '[{                                      
        "op": "replace",                                        
        "path": "/canarySettings/stageVariableOverrides/newVar", 
        "value": "newVal"                                      
      }, { 
        "op": "replace",                                        
        "path": "/canarySettings/stageVariableOverrides/var2",   
        "value": "val4"                                        
      }, {                                                      
        "op": "remove",                                         
        "path": "/canarySettings/stageVariableOverrides/var1"    
      }]'
```

You can update all of the above by combining the operations into a single `patch-operations` value:

```
aws apigateway update-stage  \
    --rest-api-id {rest-api-id} \
    --stage-name '{stage-name}' \
    --patch-operations '[{                                       
        "op": "replace",                                         
        "path": "/canarySettings/percentTraffic",                        
        "value": "20.0"                                          
    }, {                                                         
        "op": "replace",                                         
        "path": "/canarySettings/useStageCache",                        
        "value": "true"                                          
    }, {                                                         
        "op": "remove",                                          
        "path": "/canarySettings/stageVariableOverrides/var1"    
    }, {                                                         
        "op": "replace",                                         
        "path": "/canarySettings/stageVariableOverrides/newVar", 
        "value": "newVal"                                        
    }, {                                                         
        "op": "replace",                                         
        "path": "/canarySettings/stageVariableOverrides/val2",   
        "value": "val4"                                          
      }]'
```



# Promote a canary release
<a name="promote-canary-deployment"></a>

When you promote a canary release, the canary release replaces the current stage settings. Promoting a canary release does not disable the canary on the stage. To disable a canary, you must remove the canary settings on the stage. To promote a canary, do the following.
+ Reset the [deployment ID](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#deploymentId) of the stage with the [deployment ID](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings) settings of the canary. This updates the API snapshot of the stage with the snapshot of the canary, making the test version the production release as well.
+ Update stage variables with canary stage variables, if any. This updates the API execution context of the stage with that of the canary. Without this update, the new API version may produce unexpected results if the test version uses different stage variables or different values of existing stage variables.
+ Set the percentage of canary traffic to 0.0%.

**Topics**
+ [Promote a canary release using the API Gateway console](#promote-canary-release-deployment-console)
+ [Promote a canary release using the AWS CLI](#promote-canary-release-cli)

## Promote a canary release using the API Gateway console
<a name="promote-canary-release-deployment-console"></a>

To use the API Gateway console to promote a canary release deployment, do the following:

**To promote a canary release deployment**

1.  Sign in to the API Gateway console and choose an existing API in the primary navigation pane.

1.  In the main navigation pane, choose **Stages**, and then choose an existing stage.

1.  Choose the **Canary** tab.

1.  Choose **Promote canary**.

1.  Confirm changes to be made and choose **Promote canary**.

After the promotion, the production release references the same API version (**deploymentId**) as the canary release. You can verify this using the AWS CLI. For example, see [Promote a canary release using the AWS CLI](#promote-canary-release-cli). 

## Promote a canary release using the AWS CLI
<a name="promote-canary-release-cli"></a>

To promote a canary release to the production release using the AWS CLI commands, call the `update-stage` command to copy the canary-associated `deploymentId` to the stage-associated `deploymentId`, to reset the canary traffic percentage to zero (`0.0`), and, to copy any canary-bound stage variables to the corresponding stage-bound ones. 

Suppose we have a canary release deployment, described by a stage similar to the following: 

```
{
    "_links": {
        ...
    },
    "accessLogSettings": {
        ...
    },
    "cacheClusterEnabled": false,
    "cacheClusterStatus": "NOT_AVAILABLE",
    "canarySettings": {
        "deploymentId": "eh1sby",
        "useStageCache": false,
        "stageVariableOverrides": {
            "sv2": "val3",
            "sv1": "val2"
        },
        "percentTraffic": 10.5
    },
    "createdDate": "2017-11-20T04:42:19Z",
    "deploymentId": "nfcn0x",
    "lastUpdatedDate": "2017-11-22T00:54:28Z",
    "methodSettings": {
        ...
    },
    "stageName": "prod",
    "variables": {
        "sv1": "val1"
    }
}
```

Use the following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command to promote the canary:

```
aws apigateway update-stage  \
    --rest-api-id {rest-api-id}  \
    --stage-name '{stage-name}'  \
    --patch-operations '[{                                
        "op": "replace",                                  
        "value": "0.0",                                    
        "path": "/canarySettings/percentTraffic"         
      }, {                                                
        "op": "copy",                                     
        "from": "/canarySettings/stageVariableOverrides", 
        "path": "/variables"                             
      }, {                                                
        "op": "copy",                                     
        "from": "/canarySettings/deploymentId",           
        "path": "/deploymentId"                           
      }]'
```

The output will look like the following:

```
{
    "_links": {
        ...
    },
    "accessLogSettings": {
        ...
    },
    "cacheClusterEnabled": false,
    "cacheClusterStatus": "NOT_AVAILABLE",
    "canarySettings": {
        "deploymentId": "eh1sby",
        "useStageCache": false,
        "stageVariableOverrides": {
            "sv2": "val3",
            "sv1": "val2"
        },
        "percentTraffic": 0
    },
    "createdDate": "2017-11-20T04:42:19Z",
    "deploymentId": "eh1sby",
    "lastUpdatedDate": "2017-11-22T05:29:47Z",
    "methodSettings": {
        ...
    },
    "stageName": "prod",
    "variables": {
        "sv2": "val3",
        "sv1": "val2"
    }
}
```

Promoting a canary release to the stage does not disable the canary and the deployment remains to be a canary release deployment. To make it a regular production release deployment, you must disable the canary settings. For more information about how to disable a canary release deployment, see [Turn off a canary release](delete-canary-deployment.md).

# Turn off a canary release
<a name="delete-canary-deployment"></a>

To turn off a canary release deployment is to set the [https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings) to null to remove it from the stage. 

You can disable a canary release deployment using the API Gateway console, the AWS CLI, or an AWS SDK.

**Topics**
+ [Turn off a canary release using the API Gateway console](#delete-canary-release-console)
+ [Turn off a canary release using the AWS CLI](#delete-canary-release-cli)

## Turn off a canary release using the API Gateway console
<a name="delete-canary-release-console"></a>

To use the API Gateway console to turn off a canary release deployment, use the following steps:

**To turn off a canary release deployment**

1. Sign in to the API Gateway console and choose an existing API in the main navigation pane.

1. In the main navigation pane, choose **Stages**, and then choose an existing stage.

1.  Choose the **Canary** tab.

1.  Choose **Delete**.

1.  Confirm you want to delete the canary by choosing **Delete**.

As a result, the [https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings) property becomes `null` and is removed from the deployment [stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html). You can verify this using the AWS CLI. For example, see [Turn off a canary release using the AWS CLI](#delete-canary-release-cli).

## Turn off a canary release using the AWS CLI
<a name="delete-canary-release-cli"></a>

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command turns off the canary release deployment:

```
aws apigateway update-stage \
    --rest-api-id abcd1234 \
    --stage-name canary \
    --patch-operations '[{"op":"remove", "path":"/canarySettings"}]'
```

The output looks like the following:

```
{
    "stageName": "prod", 
    "accessLogSettings": {
        ...
    }, 
    "cacheClusterEnabled": false, 
    "cacheClusterStatus": "NOT_AVAILABLE", 
    "deploymentId": "nfcn0x", 
    "lastUpdatedDate": 1511309280, 
    "createdDate": 1511152939, 
    "methodSettings": {
        ...
    }
}
```

 As shown in the output, the [canarySettings](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#canarySettings) property is no longer present in the [stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html) of a canary-disabled deployment.

# Updates to REST APIs that require redeployment
<a name="updating-api"></a>

Maintaining an API amounts to viewing, updating and deleting the existing API setups. You can maintain an API using the API Gateway console, AWS CLI, CloudFormation, an SDK or the API Gateway REST API. Updating an API involves modifying certain resource properties or configuration settings of the API. Resource updates require redeploying the API, where configuration updates do not. 

The following table describes API resources that require redeployment of your API when you update them. 


| Resource | Notes | 
| --- | --- | 
| [ApiKey](https://docs.aws.amazon.com/apigateway/latest/api/API_ApiKey.html) | For applicable properties and supported operations, see [apikey:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateApiKey.html). The update requires redeploying the API. | 
| [Authorizer](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html) | For applicable properties and supported operations, see [authorizer:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateAuthorizer.html). The update requires redeploying the API. | 
|  [disableExecuteApiEndpoint](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateRestApi.html#apigw-UpdateRestApi-response-disableExecuteApiEndpoint) | The update requires modifying any stage on the API such as redeploying the API to a stage. | 
| [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) | For applicable properties and supported operations, see [documentationpart:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateDocumentationPart.html). The update requires redeploying the API. | 
| [DocumentationVersion](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationVersion.html) | For applicable properties and supported operations, see [documentationversion:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateDocumentationVersion.html). The update requires redeploying the API. | 
| [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) | For applicable properties and supported operations, see [gatewayresponse:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateGatewayResponse.html#remarks). The update requires redeploying the API. | 
| [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html) |  For applicable properties and supported operations, see [integration:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateIntegration.html). The update requires redeploying the API.  | 
| [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) | For applicable properties and supported operations, see [integrationresponse:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateIntegrationResponse.html). The update requires redeploying the API. | 
| [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) | For applicable properties and supported operations, see [method:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateMethod.html). The update requires redeploying the API. | 
| [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) | For applicable properties and supported operations, see [methodresponse:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateMethodResponse.html). The update requires redeploying the API. | 
| [Model](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) | For applicable properties and supported operations, see [model:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateModel.html). The update requires redeploying the API. | 
| [RequestValidator](https://docs.aws.amazon.com/apigateway/latest/api/API_RequestValidator.html) | For applicable properties and supported operations, see [requestvalidator:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateRequestValidator.html). The update requires redeploying the API. | 
| [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) | For applicable properties and supported operations, see [resource:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateResource.html). The update requires redeploying the API. | 
| [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateRestApi.html) | For applicable properties and supported operations, see [restapi:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateRestApi.html). The update requires redeploying the API. This includes modifying resource policies. | 
| [VpcLink](https://docs.aws.amazon.com/apigateway/latest/api/API_VpcLink.html) | For applicable properties and supported operations, see [vpclink:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateVpcLink.html). The update requires redeploying the API. | 

The following table describes API configurations that don't require redeployment of your API when you update them.


| Configuration | Notes | 
| --- | --- | 
| [Account](https://docs.aws.amazon.com/apigateway/latest/api/API_GetAccount.html) |  For applicable properties and supported operations, see [account:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateAccount.html). The update does not require redeploying the API.  | 
| [Deployment](https://docs.aws.amazon.com/apigateway/latest/api/API_Deployment.html) | For applicable properties and supported operations, see [deployment:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateDeployment.html).  | 
| [DomainName](https://docs.aws.amazon.com/apigateway/latest/api/API_DomainName.html) | For applicable properties and supported operations, see [domainname:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateDomainName.html). The update does not require redeploying the API. | 
| [BasePathMapping](https://docs.aws.amazon.com/apigateway/latest/api/API_BasePathMapping.html) |  For applicable properties and supported operations, see [basepathmapping:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateBasePathMapping.html). The update does not require redeploying the API.  | 
| [IP address type](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateRestApi.html) |  The update does not require redeploying the API.  | 
| [Stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html) |  For applicable properties and supported operations, see [stage:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html). The update does not require redeploying the API.  | 
| [Usage](https://docs.aws.amazon.com/apigateway/latest/api/API_GetUsage.html) |  For applicable properties and supported operations, see [usage:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateUsage.html). The update does not require redeploying the API.  | 
| [UsagePlan](https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlan.html) | For applicable properties and supported operations, see [usageplan:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateUsagePlan.html). The update does not require redeploying the API. | 

# Custom domain name for public REST APIs in API Gateway
<a name="how-to-custom-domains"></a>

*Custom domain names* are simpler and more intuitive URLs that you can provide to your API users.

After deploying your API, you (and your customers) can invoke the API using the default base URL of the following format: 

```
https://api-id.execute-api.region.amazonaws.com/stage
```

where *api-id* is generated by API Gateway, *region* is the AWS Region, and *stage* is specified by you when deploying the API.

The hostname portion of the URL, `api-id.execute-api.region.amazonaws.com` refers to an API endpoint. The default API endpoint name is randomly generated, difficult to recall, and not user-friendly.

With custom domain names, you can set up your API's hostname, and choose a base path (for example, `myservice`) to map the alternative URL to your API. For example, a more user-friendly API base URL can become:

```
https://api.example.com/myservice
```

**Note**  
For information about custom domain names for private APIs, see [Custom domain names for private APIs in API Gateway](apigateway-private-custom-domains.md).

## Considerations
<a name="custom-domain-considerations"></a>

The following considerations might impact your use of a custom domain name:
+ You can disable the default endpoint for your API. Clients can still connect to your default endpoint, but they will receive a `403 Forbidden` status code.
+ A Regional custom domain name can be associated with REST APIs and HTTP APIs. You can use the [API Gateway Version 2 APIs](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/api-reference.html) to create and manage Regional custom domain names for REST APIs. 
+ A custom domain name must be unique within a Region across all AWS accounts. 
+ You can migrate your custom domain name between edge-optimized and Regional endpoints, but you can't migrate a public custom domain to a private custom domain name.
+ You must create or update your DNS provider's resource record to map to your API endpoint. Without such a mapping, API requests bound for the custom domain name cannot reach API Gateway.
+ You can support an almost infinite number of domain names without exceeding the default quota by using a wildcard certificate. For more information, see [Wildcard custom domain names](#wildcard-custom-domain-names).
+ You can choose a security policy for your custom domain name. For more information, see [Choose a security policy for your custom domain in API Gateway](apigateway-custom-domain-tls-version.md).
+ To configure API mappings with multiple levels, you must use a Regional custom domain name and use the TLS 1.2 security policy.

## Prerequisites for custom domain names
<a name="how-to-custom-domains-prerequisites"></a>

The following are prerequisites for creating a public or private custom domain name. For information about custom domain names for private APIs, see [Custom domain names for private APIs in API Gateway](apigateway-private-custom-domains.md).

### Register a domain name
<a name="custom-domain-names-register"></a>

You must have a registered internet domain name in order to set up custom domain names for your APIs. You can register your internet domain name using [Amazon Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/) or using a third-party domain registrar of your choice. Your custom domain name can be the name of a subdomain or the root domain (also known as the "zone apex") of a registered internet domain.

Your domain name must follow the [RFC 1035](https://tools.ietf.org/html/rfc1035#section-2.3.4) specification and can have a maximum of 63 octets per label and 255 octets in total.

### Specify the certificate for your custom domain name
<a name="custom-domain-names-certificates"></a>

Before setting up a custom domain name for an API, you must have an SSL/TLS certificate ready in ACM. If ACM is not available in the AWS Region where you are creating your custom domain name, you must import a certificate to API Gateway in that Region.

To import an SSL/TLS certificate, you must provide the PEM-formatted SSL/TLS certificate body, its private key, and the certificate chain for the custom domain name.

Each certificate stored in ACM is identified by its ARN. With certificates issued by ACM, you do not have to worry about exposing any sensitive certificate details, such as the private key. To use an AWS managed certificate for a domain name, you simply reference its ARN. 

If your application uses certificate pinning, sometimes known as SSL pinning, to pin an ACM certificate, the application might not be able to connect to your domain after AWS renews the certificate. For more information, see [Certificate pinning problems](https://docs.aws.amazon.com/acm/latest/userguide/troubleshooting-pinning.html) in the *AWS Certificate Manager User Guide*.

## Wildcard custom domain names
<a name="wildcard-custom-domain-names"></a>

With wildcard custom domain names, you can support an almost infinite number of domain names without exceeding the [default quota](limits.md). For example, you could give each of your customers their own domain name, `customername.example.com`.

To create a wildcard custom domain name, specify a wildcard (`*`) as the first subdomain of a custom domain that represents all possible subdomains of a root domain.

For example, the wildcard custom domain name `*.example.com` results in subdomains such as `a.example.com`, `b.example.com`, and `c.example.com`. When you create the wildcard custom domain name, all its subdomains are routed by the routing mode of the wildcard domain name. To route subdomains to different APIs, you can do either of the following:
+ Use routing rules to route incoming requests to `*.example.com` to different target REST APIs using the `Host` header. For more information, see [Example 4: Routing rules for wildcard domain names](rest-api-routing-rules-examples.md#rest-api-routing-rules-examples-rule-for-wildcard-domains). 
+ Create a domain name for any subdomains that you want to route to a different endpoint. In a single AWS account, you can have both `*.example.com` and `a.example.com`.

You can use the `$context.domainName` and `$context.domainPrefix` context variables to determine the domain name that a client used to call your API. To learn more about context variables, see [Variables for data transformations for API Gateway](api-gateway-mapping-template-reference.md).

To create a wildcard custom domain name, you must provide a certificate issued by ACM that has been validated using either the DNS or the email validation method.

**Note**  
You can't create a wildcard custom domain name if a different AWS account has created a custom domain name that conflicts with the wildcard custom domain name. For example, if account A has created `a.example.com`, then account B can't create the wildcard custom domain name `*.example.com`.  
If account A and account B share an owner, you can contact the [AWS Support Center](https://console.aws.amazon.com/support/home#/) to request an exception.

## Next steps for custom domain names
<a name="how-to-custom-domains-next-steps"></a>

The following are next steps for custom domain names.

**Next steps**
+ To learn how to set your SSL/TLS certificate, see [Get certificates ready in AWS Certificate Manager](how-to-specify-certificate-for-custom-domain-name.md).
+ To learn how to create a Regional custom domain name, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md).
+ To learn how to create an edge-optimized custom domain name, see [Set up an edge-optimized custom domain name in API Gateway](how-to-edge-optimized-custom-domain-name.md).
+ To learn how to migrate between Regional and edge-optimized custom domain names, see [Migrate a custom domain name to a different API endpoint type in API Gateway](apigateway-regional-api-custom-domain-migrate.md).
+ To learn how to connect API stages to a custom domain name, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).
+ To learn how to choose a security policy for your custom domain name, see [Choose a security policy for your custom domain in API Gateway](apigateway-custom-domain-tls-version.md).
+ To learn how to turn off the default endpoint for your custom domain name, see [Disable the default endpoint for REST APIs](rest-api-disable-default-endpoint.md).
+ To learn how to use Route 53 health checks to control DNS failover from an API Gateway API, see [Configure custom health checks for DNS failover for an API Gateway API](dns-failover.md).

If this is your first time creating a custom domain name, we recommend that you start with [Get certificates ready in AWS Certificate Manager](how-to-specify-certificate-for-custom-domain-name.md), to specify your certificate, and then [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md) to create a Regional custom domain name. 

# Get certificates ready in AWS Certificate Manager
<a name="how-to-specify-certificate-for-custom-domain-name"></a>

Before setting up a custom domain name for an API, you must have an SSL/TLS certificate ready in AWS Certificate Manager. For more information, see the [AWS Certificate Manager User Guide](https://docs.aws.amazon.com/acm/latest/userguide/).

## Considerations
<a name="how-to-specify-certificate-for-custom-domain-name-considerations"></a>

The following are considerations for your SSL/TLS certificate.
+ If you create an edge-optimized custom domain name, API Gateway leverages CloudFront to support certificates for custom domain names. As such, the requirements and constraints of a custom domain name SSL/TLS certificate are dictated by [CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-web-values-specify.html). For example, the maximum size of the public key is 2048 and the private key size can be 1024, 2048, and 4096. The public key size is determined by the certificate authority you use. Ask your certificate authority to return keys of a size different from the default length. For more information, see [Secure access to your objects](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https.html) and [Create signed URLs and signed cookies](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html).
+ If you create a Regional custom domain name, the maximum size of the public key is 2048.
+ To use an ACM certificate with a Regional custom domain name, you must request or import the certificate in the same Region as your API. The certificate must cover the custom domain name.
+  To use an ACM certificate with an edge-optimized custom domain name, you must request or import the certificate in the US East (N. Virginia) – `us-east-1` Region.
+  You must have a registered domain name, such as `example.com`. You can use either [Amazon Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/) or a third-party accredited domain registrar. For a list of such registrars, see [Accredited Registrar Directory](https://www.icann.org/en/accredited-registrars) at the ICANN website. 

## To create or import an SSL/TLS certificate into ACM
<a name="how-to-specify-certificate-for-custom-domain-name-setup"></a>

The following procedures show how to create or import an SSL/TLS certificate for a domain name.

------
#### [ To request a certificate provided by ACM for a domain name ]

1. Sign in to the [AWS Certificate Manager console](https://console.aws.amazon.com/acm).

1. Choose **Request a certificate**.

1. For **Certificate type**, choose **Request a public certificate**.

1. Choose **Next**.

1. For **Fully qualified domain name**, enter a custom domain name for your API, for example, `api.example.com`.

1. Optionally, choose **Add another name to this certificate**.

1. For **Validation method**, choose a method for validating domain ownership.

1. For **Key algorithm**, choose an encryption algorithm.

1. Choose **Request**.

1. For a valid request, a registered owner of the internet domain must consent to the request before ACM issues the certificate. If you use Route 53 to manage your public DNS records, you can update your records through the ACM console directly.

------
#### [ To import into ACM a certificate for a domain name ]

1.  Get a PEM-encoded SSL/TLS certificate for your custom domain name from a certificate authority. For a partial list of such CAs, see the [Mozilla Included CA List](https://ccadb.my.salesforce-sites.com/mozilla/IncludedCACertificateReport). 

   1. Generate a private key for the certificate and save the output to a file, using the [OpenSSL](https://www.openssl.org) toolkit at the OpenSSL website:

      ```
      openssl genrsa -out private-key-file 2048
      ```

   1. Generate a certificate signing request (CSR) with the previously generated private key, using OpenSSL:

      ```
      openssl req -new -sha256 -key private-key-file -out CSR-file
      ```

   1. Submit the CSR to the certificate authority and save the resulting certificate.

   1. Download the certificate chain from the certificate authority.
**Note**  
 If you obtain the private key in another way and the key is encrypted, you can use the following command to decrypt the key before submitting it to API Gateway for setting up a custom domain name.   

   ```
   openssl pkcs8 -topk8 -inform pem -in MyEncryptedKey.pem -outform pem -nocrypt -out MyDecryptedKey.pem
   ```

1. Upload the certificate to AWS Certificate Manager:

   1. Sign in to the [AWS Certificate Manager console](https://console.aws.amazon.com/acm).

   1. Choose **Import a certificate**.

   1. For **Certificate body**, enter the body of the PEM-formatted server certificate from your certificate authority. The following shows an abbreviated example of such a certificate.

      ```
      -----BEGIN CERTIFICATE-----
      EXAMPLECA+KgAwIBAgIQJ1XxJ8Pl++gOfQtj0IBoqDANBgkqhkiG9w0BAQUFADBB
      ...
      az8Cg1aicxLBQ7EaWIhhgEXAMPLE
      -----END CERTIFICATE-----
      ```

   1. For **Certificate private key**, enter your PEM-formatted certificate's private key. The following shows an abbreviated example of such a key. 

      ```
      -----BEGIN RSA PRIVATE KEY-----
      EXAMPLEBAAKCAQEA2Qb3LDHD7StY7Wj6U2/opV6Xu37qUCCkeDWhwpZMYJ9/nETO
      ...
      1qGvJ3u04vdnzaYN5WoyN5LFckrlA71+CszD1CGSqbVDWEXAMPLE
      -----END RSA PRIVATE KEY-----
      ```

   1. For **Certificate chain**, enter the PEM-formatted intermediate certificates and, optionally, the root certificate, one after the other without any blank lines. If you include the root certificate, your certificate chain must start with intermediate certificates and end with the root certificate. Use the intermediate certificates provided by your certificate authority. Do not include any intermediaries that are not in the chain of trust path. The following shows an abbreviated example. 

      ```
      -----BEGIN CERTIFICATE-----
      EXAMPLECA4ugAwIBAgIQWrYdrB5NogYUx1U9Pamy3DANBgkqhkiG9w0BAQUFADCB
      ...
      8/ifBlIK3se2e4/hEfcEejX/arxbx1BJCHBvlEPNnsdw8EXAMPLE
      -----END CERTIFICATE-----
      ```

      Here is another example.

      ```
      -----BEGIN CERTIFICATE-----
      Intermediate certificate 2
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      Intermediate certificate 1
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      Optional: Root certificate
      -----END CERTIFICATE-----
      ```

   1. Choose **Next**, and then choose **Next**.

------

After the certificate is successfully created or imported, make note of the certificate ARN. You need it when setting up the custom domain name.

# Set up a Regional custom domain name in API Gateway
<a name="apigateway-regional-api-custom-domain-create"></a>

Use a Regional custom domain name to create a user-friendly API base URL. With a Regional custom domain name, you can map HTTP and REST API stages to the same custom domain name and use mutual TLS authentication. 

## Considerations
<a name="regional-custom-domain-names"></a>

The following are considerations for your Regional custom domain name:
+ You must provide a Region-specific ACM certificate. This certificate must be in the same Region as your API. For more information about creating or uploading a custom domain name certificate, see [Get certificates ready in AWS Certificate Manager](how-to-specify-certificate-for-custom-domain-name.md).
+ When you create a Regional custom domain name (or migrate one) with an ACM certificate, API Gateway creates a service-linked role in your account. The service-linked role is required to attach your ACM certificate to your Regional endpoint. The role is named **AWSServiceRoleForAPIGateway** and will have the **APIGatewayServiceRolePolicy** managed policy attached to it. For more information about use of the service-linked role, see [Using Service-Linked Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html).
+ After your create your Regional custom domain name, you must create a DNS record to point the custom domain name to the Regional domain. This enables the traffic that is bound to the custom domain name to be routed to the API's Regional hostname.

  The DNS record can be the CNAME or an A Alias record. If you use Route 53 as your DNS provider, create an A Alias record. If you use a third-party DNS provider, use a CNAME record. If you use a CNAME record and create an API Gateway interface VPC endpoint with private DNS enabled for a private API, you can't resolve the custom domain name within the VPC that hosts your private API. 

## Create a Regional custom domain name
<a name="apigateway-regional-api-custom-domain-create-procedure"></a>

The following procedure shows how to create a Regional custom domain name. After you complete this procedure, you create a routing rule to route stages of your API to your custom domain name.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose **Create**.

1. For **Domain name**, enter a domain name.

1. For **Routing mode**, choose **Routing rules only**.

   In this routing mode, you can only send traffic from your custom domain name to your APIs by using routing rules. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

1. For **Minimum TLS version**, select a version.

1. Under **Endpoint configuration**, for **API endpoint type**, choose **Regional**.

1. Choose an ACM certificate. The certificate must be in the same Region as the API.

1. Choose **Create**.

------
#### [ AWS CLI ]

The following [create-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-domain-name.html) command creates a custom domain name:

```
aws apigatewayv2 create-domain-name \ 
    --domain-name 'regional.example.com' \
    --domain-name-configurations CertificateArn=arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --routing-mode ROUTING_RULE_ONLY
```

The output will look like the following:

```
{
    "ApiMappingSelectionExpression": "$request.basepath",
    "DomainName": "regional.example.com",
    "DomainNameConfigurations": [
        {
            "ApiGatewayDomainName": "d-numh1z56v6.execute-api.us-west-2.amazonaws.com",
            "CertificateArn": "arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678",
            "DomainNameStatus": "AVAILABLE",
            "EndpointType": "REGIONAL",
            "HostedZoneId": "Z2OJLYMUO9EFXC",
            "SecurityPolicy": "TLS_1_2"
        }
        "RoutingMode": "ROUTING_RULE_ONLY"
    ]
}
```

The `DomainNameConfigurations` property value returns the Regional API's hostname. You must create a DNS record to point your custom domain name to this Regional domain name. This enables the traffic that is bound to the custom domain name to be routed to this Regional API's hostname.

------

## Create a routing rule for your Regional custom domain name
<a name="apigateway-regional-api-custom-domain-base-path-mapping"></a>

After you create your custom domain name, you configure how traffic is routed from your custom domain name to your APIs. Because you set the routing mode to `ROUTING_RULE_ONLY`, you use routing rules to route incoming requests to your custom domain name to your APIs.

In this example, you create a catch-all rule that routes all incoming requests to your custom domain name to one stage of your API. You can also configure routing rules based on different header and path conditions. For more information, see [Routing rules to connect API stages to a custom domain name for REST APIs](rest-api-routing-rules.md).

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a custom domain name.

1. On the **Routing details** tab, choose **Add routing rule**.

1. Choose **Add a new condition** to add a new condition.

1. Keep this rule without any conditions. This routes all requests to your custom domain name to your target API and target stage.

1. For **Action**, use the dropdown to select your target API and target stage.

1. Choose **Next**.

1. In the priority field, enter **100**.

   API Gateway evaluates rules in priority order, from the lowest value to the highest value. Because this is a catch-all rule, you use a high priority so API Gateway can match any additional rules you create first.

1. Choose **Create routing rule**.

------
#### [ AWS CLI ]

The following `create-routing-rule` command creates a catch-all routing rule:

```
aws apigatewayv2 create-routing-rule \
  --domain-name 'regional.example.com' \
  --priority 100 \
  --conditions  \
  --actions '[{
    "InvokeApi": {
      "ApiId": "a1b2c3",
      "Stage": "prod"
    }
  }]'
```

------

You can change the routing mode and create new rules at any time. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

## Create a DNS record for your Regional custom domain name
<a name="apigateway-regional-api-custom-domain-dns-record"></a>

After you create your custom domain name and create base path mappings, you create a DNS record to point your custom domain name your newly created Regional domain name.

------
#### [ AWS Management Console ]

To use the AWS Management Console, follow the Route 53 documentation on [configuring Route 53 to route traffic to API Gateway](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

------
#### [ AWS CLI ]

To configure your DNS records to map the Regional custom domain name to its hostname of the given hosted zone ID, first create a JSON file that contains the configuration for setting up a DNS record for the Regional domain name. 

The following `setup-dns-record.json` shows how to create a DNS `A` record to map a Regional custom domain name (`regional.example.com`) to its Regional hostname (`d-numh1z56v6.execute-api.us-west-2.amazonaws.com`) provisioned as part of the custom domain name creation. The `DNSName` and `HostedZoneId` properties of `AliasTarget` can take the `regionalDomainName` and `regionalHostedZoneId` values, respectively, of the custom domain name. You can also get the Regional Route 53 Hosted Zone IDs in [Amazon API Gateway Endpoints and Quotas](https://docs.aws.amazon.com/general/latest/gr/apigateway.html).

```
{
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "regional.example.com",
        "Type": "A",
        "AliasTarget": {
          "DNSName": "d-numh1z56v6.execute-api.us-west-2.amazonaws.com",
          "HostedZoneId": "Z2OJLYMUO9EFXC",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}
```

The following [change-resource-record-sets](https://docs.aws.amazon.com/cli/latest/reference/route53/change-resource-record-sets.html) creates a DNS record for your Regional custom domain name:

```
aws route53 change-resource-record-sets \
    --hosted-zone-id Z2OJLYMUO9EFXC \
    --change-batch file://path/to/your/setup-dns-record.json
```

Replace the`hosted-zone-id` with the Route 53 Hosted Zone ID of the DNS record set in your account. The `change-batch` parameter value points to a JSON file (*setup-dns-record.json*) in a folder (*path/to/your*).

------

# Set up an edge-optimized custom domain name in API Gateway
<a name="how-to-edge-optimized-custom-domain-name"></a>

When you create a custom domain name for an edge-optimized API, API Gateway sets up a CloudFront distribution and a DNS record to map the API domain name to the CloudFront distribution domain name. Requests for the API are then routed to API Gateway through the mapped CloudFront distribution. This mapping is for API requests that are bound for the custom domain name to be routed to API Gateway through the mapped CloudFront distribution.

## Considerations
<a name="how-to-edge-optimized-custom-domain-name-considerations"></a>

The following are considerations for your edge-optimized custom domain name:
+  To set up an edge-optimized custom domain name or to update its certificate, you must have a permission to update CloudFront distributions.

  The following permissions are required to update CloudFront distributions: 

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
           {
              "Sid": "AllowCloudFrontUpdateDistribution",
              "Effect": "Allow",
              "Action": [
                  "cloudfront:updateDistribution"
              ],
              "Resource": [
                  "*"
              ]
          }
      ]
  }
  ```

------
+ You must request or import a certificate for your edge-optimized custom domain name in the US East (N. Virginia) – `us-east-1` Region.
+ The CloudFront distribution created by API Gateway is owned by a Region-specific account affiliated with API Gateway. When tracing operations to create and update such a CloudFront distribution in CloudTrail, you must use this API Gateway account ID. For more information, see [Log custom domain name creation in CloudTrail](#how-to-custom-domain-log-cloudfront-distribution-update-in-cloudtrail).
+  API Gateway supports edge-optimized custom domain names by leveraging Server Name Indication (SNI) on the CloudFront distribution. For more information on using custom domain names on a CloudFront distribution, including the required certificate format and the maximum size of a certificate key length, see [ Using Alternate Domain Names and HTTPS](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https-alternate-domain-names.html) in the *Amazon CloudFront Developer Guide*
+ An edge-optimized custom domain names takes about 40 minutes to be ready.
+ After you create your edge-optimized custom domain name, you must create a DNS record to map the custom domain name to the CloudFront distribution name.

## Create an edge-optimize custom domain name
<a name="how-to-custom-domains-console"></a>

The following procedure describes how to create an edge-optimized custom domain name for an API.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose **Add domain name**.

1. For **Domain name**, enter a domain name.

1. For **Routing mode**, choose **API\$1MAPPING\$1ONLY**.

1. For **API endpoint type**, choose **Edge-optimized**.

1. Choose a minimum TLS version.

1. Choose an ACM certificate.

1. Choose **Add domain name**.

------
#### [ REST API ]

1. Call [domainname:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateDomainName.html), specifying the custom domain name and the ARN of a certificate stored in AWS Certificate Manager.

    The successful API call returns a `201 Created` response containing the certificate ARN as well as the associated CloudFront distribution name in its payload.

1. Note the CloudFront distribution domain name shown in the output. You need it in the next step to set the custom domain's A-record alias target in your DNS.

For code examples of this REST API call, see [domainname:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateDomainName.html).

------

An edge-optimized custom domain names takes about 40 minutes to be ready, but the console immediately displays the associated CloudFront distribution domain name, in the form of `distribution-id.cloudfront.net`, along with the certificate ARN. In the meantime, you can create a base path mapping or a routing rule and then configure the DNS record alias to map the custom domain name to the associated CloudFront distribution domain name.

## Configure base path mapping of an API with a custom domain name as its hostname
<a name="how-to-custom-domains-mapping-console"></a>

Because you set the routing mode to `API_MAPPING_ONLY`, you can use base path mapping to use a single custom domain name as the hostname of multiple APIs. This makes an API accessible through the combination of the custom domain name and the associated base path.

For example, if in API Gateway, you created an API named `PetStore` and another API named `Dogs` and then set up a custom domain name of `api.example.com`, you can set the `PetStore` API's URL as `https://api.example.com`.

This associates the `PetStore` API with the base path of an empty string. If you set the `PetStore` API's URL as `https://api.example.com/PetStore`, this associates the `PetStore` API with the base path of `PetStore`. You can assign a base path of `MyDogList` for the `Dogs` API. The URL of `https://api.example.com/MyDogList` is then the root URL of the `Dogs` API.

To configure API mappings on multiple levels, you can only use a Regional custom domain name. Edge-optimized custom domain names are not supported. For more information, see [Use API mappings to connect API stages to a custom domain name for REST APIs](rest-api-mappings.md).

The following procedure sets up API mappings to map paths from your custom domain name to your API stages.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the API Gateway console main navigation pane.

1. Choose a custom domain name.

1. Choose **Configure API mappings**.

1. Choose **Add new mapping**.

1. Specify the **API**, **Stage**, and **Path** (optional) for the mapping.

1. Choose **Save**.

------
#### [ REST API ]

 Call [basepathmapping:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateBasePathMapping.html) on a specific custom domain name, specifying the `basePath`, `restApiId`, and a deployment `stage` property in the request payload.

 The successful API call returns a `201 Created` response.

For code examples of the REST API call, see [basepathmapping:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateBasePathMapping.html).

------

For more flexibility on how you route traffic to your APIs, you can change the routing mode to `ROUTING_RULE_ONLY` or `ROUTING_RULE_THEN_API_MAPPING` and create a routing rule. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

## Create a DNS record for your edge-optimized custom domain name
<a name="how-to-edge-optimized-custom-domain-name-dns-record"></a>

After you initiate the creation of your edge-optimized custom domain name, set up the DNS record alias.

We recommend that you use Route 53 to create an A-record alias for your custom domain name and specify the CloudFront distribution domain name as the alias target. This means that Route 53 can route your custom domain name even if it is a zone apex. For more information, see [Choosing Between Alias and Non-Alias Resource Record Sets](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html) in the *Amazon Route 53 Developer Guide*.

 For instructions for Amazon Route 53, see [Routing traffic to an Amazon API Gateway API by using your domain name](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-api-gateway.html) in the *Amazon Route 53 Developer Guide*.

## Log custom domain name creation in CloudTrail
<a name="how-to-custom-domain-log-cloudfront-distribution-update-in-cloudtrail"></a>

When CloudTrail is enabled for logging API Gateway calls made by your account, API Gateway logs the associated CloudFront distribution updates when a custom domain name is created or updated for an API. These logs are available in `us-east-1`. Because these CloudFront distributions are owned by API Gateway, each of these reported CloudFront distributions is identified by one of the following Region-specific API Gateway account IDs, instead of the API owner's account ID. 


| **Region** | **Account ID** | 
| --- | --- | 
| us-east-1 | 392220576650 | 
| us-east-2 | 718770453195 | 
| us-west-1 | 968246515281 | 
| us-west-2 | 109351309407 | 
| ca-central-1 | 796887884028 | 
| eu-west-1 | 631144002099 | 
| eu-west-2 | 544388816663 | 
| eu-west-3 | 061510835048 | 
| eu-central-1 | 474240146802 | 
| eu-central-2 | 166639821150 | 
| eu-north-1 | 394634713161 | 
| eu-south-1 | 753362059629 | 
| eu-south-2 | 359345898052 | 
| ap-northeast-1 | 969236854626 | 
| ap-northeast-2 | 020402002396 | 
| ap-northeast-3 | 360671645888 | 
| ap-southeast-1 | 195145609632 | 
| ap-southeast-2 | 798376113853 | 
| ap-southeast-3 | 652364314486 | 
| ap-southeast-4 | 849137399833 | 
| ap-south-1 | 507069717855 | 
| ap-south-2 | 644042651268 | 
| ap-east-1 | 174803364771 | 
| sa-east-1 | 287228555773 | 
| me-south-1 | 855739686837 | 
| me-central-1 | 614065512851 | 

## Rotate a certificate imported into ACM
<a name="how-to-rotate-custom-domain-certificate"></a>

 ACM automatically handles renewal of certificates it issues. You do not need to rotate any ACM-issued certificates for your custom domain names. CloudFront handles it on your behalf. 

 However, if you import a certificate into ACM and use it for a custom domain name, you must rotate the certificate before it expires. This involves importing a new third-party certificate for the domain name and rotate the existing certificate to the new one. You need to repeat the process when the newly imported certificate expires. Alternatively, you can request ACM to issue a new certificate for the domain name and rotate the existing one to the new ACM-issued certificate. After that, you can leave ACM and CloudFront to handle the certificate rotation for you automatically. To create or import a new ACM certificate, follow the steps in [To create or import an SSL/TLS certificate into ACM](how-to-specify-certificate-for-custom-domain-name.md#how-to-specify-certificate-for-custom-domain-name-setup).

The following procedure describes how to rotate a certificate for a domain name.

**Note**  
It takes about 40 minutes to rotate a certificate imported into ACM.

------
#### [ AWS Management Console ]

1. Request or import a certificate in ACM.

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the API Gateway console main navigation pane.

1. Choose an edge-optimized custom domain name.

1. For **Endpoint configuration**, choose **Edit**.

1. For **ACM certificate**, select a certificate from dropdown list.

1. Choose **Save changes** to begin rotating the certificate for the custom domain name. 

------
#### [ REST API ]

 Call [domainname:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateDomainName.html) action, specifying the ARN of the new ACM certificate for the specified domain name. 

------
#### [ AWS CLI ]

 The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) updates the ACM certificate for an edge-optimized domain name.

```
aws apigateway update-domain-name \
    --domain-name edge.example.com \
    --patch-operations "op='replace',path='/certificateArn',value='arn:aws:acm:us-east-2:111122223333:certificate/CERTEXAMPLE123EXAMPLE'"
```

 The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) updates the ACM certificate for a Regional domain name.

```
aws apigateway update-domain-name \
    --domain-name regional.example.com \
    --patch-operations "op='replace',path='/regionalCertificateArn',value='arn:aws:acm:us-east-2:111122223333:certificate/CERTEXAMPLE123EXAMPLE'"
```

------

## Call your API with custom domain names when you use a base path mapping
<a name="how-to-custom-domains-call-api-with-sni"></a>

Calling an API with a custom domain name is the same as calling the API with its default domain name, provided that the correct URL is used.

The following examples compare and contrast a set of default URLs and corresponding custom URLs of two APIs (`udxjef` and `qf3duz`) in a specified Region (`us-east-1`), and of a given custom domain name (`api.example.com`).


| API ID | Stage | Default URL | Base path | Custom URL | 
| --- | --- | --- | --- | --- | 
| udxjef | prod | https://udxjef.execute-api.us-east-1.amazonaws.com/prod | /petstore | https://api.example.com/petstore | 
| udxjef | tst | https://udxjef.execute-api.us-east-1.amazonaws.com/tst | /petdepot | https://api.example.com/petdepot | 
| qf3duz | dev | https://qf3duz.execute-api.us-east-1.amazonaws.com/dev | /bookstore | https://api.example.com/bookstore | 
| qf3duz | tst | https://qf3duz.execute-api.us-east-1.amazonaws.com/tst | /bookstand | https://api.example.com/bookstand | 

For more flexibility on how you route traffic to your APIs, you can create a routing rule. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

 API Gateway supports custom domain names for an API by using [Server Name Indication (SNI)](https://en.wikipedia.org/wiki/Server_Name_Indication). You can invoke the API with a custom domain name using a browser or a client library that supports SNI. 

 API Gateway enforces SNI on the CloudFront distribution. For information on how CloudFront uses custom domain names, see [Amazon CloudFront Custom SSL](https://aws.amazon.com/cloudfront/custom-ssl-domains/). 

# Migrate a custom domain name to a different API endpoint type in API Gateway
<a name="apigateway-regional-api-custom-domain-migrate"></a>

 You can migrate your custom domain name between edge-optimized and Regional endpoints. You can't migrate a public custom domain name to a private custom domain name. You first add the new endpoint configuration type to the existing `endpointConfiguration.types` list for the custom domain name. Next, you set up a DNS record to point the custom domain name to the newly provisioned endpoint. Finally, you remove the obsolete custom domain name endpoint.

## Considerations
<a name="apigateway-regional-api-custom-domain-migration-considerations"></a>

The following are considerations for migrating your custom domain between a Regional API endpoint and an edge-optimized API endpoint:
+ An edge-optimized custom domain name requires a certificate provided by ACM from the US East (N. Virginia) – `us-east-1` Region. This certificate is distributed to all the geographic locations.
+ A Regional custom domain name requires a certificate provided by ACM in the same Region hosting the API. You can migrate an edge-optimized custom domain name that is not in the `us-east-1` Region to a Regional custom domain name by requesting a new ACM certificate from the Region that is local to the API.
+ It might take up to 60 seconds to complete a migration between an edge-optimized custom domain name and a Regional custom domain name. The migration time also depends on when you update your DNS records.
+ You can only add an additional endpoint configuration if the endpoint access mode is set to `BASIC`. Once you have two endpoint configurations, you can't change the endpoint access mode. For more information, see [Endpoint access mode](apigateway-security-policies.md#apigateway-security-policies-endpoint-access-mode).
+ If your custom domain name uses a security policy that starts with `SecurityPolicy_`, when you add a new endpoint configuration type, the endpoint access mode is the same across both endpoint types, and you must choose a security policy that starts with `SecurityPolicy_` for the new endpoint configuration type.

## Migrate custom domain names
<a name="apigateway-api-custom-domain-names-migrate-procedure"></a>

**Note**  
To complete the migration, make sure that you remove the obsolete endpoint from your custom domain name.

The following procedure shows how to migrate an edge-optimized custom domain name to a Regional custom domain name.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose an edge-optimized custom domain name.

1. For **Endpoint configuration**, choose **Edit**.

1. Choose **Add Regional endpoint**.

1. For **ACM certificate**, choose a certificate.

   The Regional certificate must be in the same Region as the Regional API.

1. Choose **Save changes**.

1. Set up a DNS record to point the Regional custom domain name to this Regional hostname. For more information, see [configuring Route 53 to route traffic to API Gateway](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

1. After you confirm that your DNS configuration is using the correct endpoint, you delete the edge-optimized endpoint configuration. Choose your custom domain name, and then for **Edge-optimized endpoint configuration**, choose **Delete**.

1. Confirm your choice and delete the endpoint.

------
#### [ AWS CLI ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command migrates an edge-optmized custom domain name to a Regional custom domain name:

```
aws apigateway update-domain-name \
    --domain-name 'api.example.com' \
    --patch-operations  '[ 
        { "op":"add", "path": "/endpointConfiguration/types","value": "REGIONAL" },
        { "op":"add", "path": "/regionalCertificateArn", "value": "arn:aws:acm:us-west-2:123456789012:certificate/cd833b28-58d2-407e-83e9-dce3fd852149" }
      ]'
```

The Regional certificate must be of the same Region as the Regional API. 

The output will look like the following:

```
{
    "certificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/34a95aa1-77fa-427c-aa07-3a88bd9f3c0a",
    "certificateName": "edge-cert",
    "certificateUploadDate": "2017-10-16T23:22:57Z",
    "distributionDomainName": "d1frvgze7vy1bf.cloudfront.net",
    "domainName": "api.example.com",
    "endpointConfiguration": {
        "types": [
            "EDGE",
            "REGIONAL"
        ]
    },
    "regionalCertificateArn": "arn:aws:acm:us-west-2:123456789012:certificate/cd833b28-58d2-407e-83e9-dce3fd852149",
    "regionalDomainName": "d-fdisjghyn6.execute-api.us-west-2.amazonaws.com"
}
```

For the migrated Regional custom domain name, the resulting `regionalDomainName` property returns the Regional API hostname. You must set up a DNS record to point the Regional custom domain name to this Regional hostname. This enables the traffic that is bound to the custom domain name to be routed to the Regional host. 

After the DNS record is set, you can remove the edge-optimized custom domain name. The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command removes the edge-optimized custom domain name:

```
aws apigateway update-domain-name \
    --domain-name api.example.com \
    --patch-operations '[
            {"op":"remove", "path":"/endpointConfiguration/types", "value":"EDGE"},
            {"op":"remove", "path":"certificateName"},
            {"op":"remove", "path":"certificateArn"}
        ]'
```

------

The following procedure shows how to migrate an edge-optimized custom domain name that uses an enhanced security policy to a Regional custom domain name that also uses an enhanced security policy.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose an edge-optimized custom domain name.

1. For **Endpoint configuration**, choose **Edit**.

1. Choose **Add Regional endpoint**.

1. For **ACM certificate**, choose a certificate.

   The Regional certificate must be in the same Region as the Regional API.

1. For **Security policy**, choose a security policy that starts with `SecurityPolicy_`.

1. For **Endpoint access mode**, choose **Basic**.

1. Choose **Save changes**.

1. Set up a DNS record to point the Regional custom domain name to this Regional hostname. For more information, see [configuring Route 53 to route traffic to API Gateway](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

1. After you confirm that your DNS configuration is using the correct endpoint, you delete the edge-optimized endpoint configuration. Choose your custom domain name, and then for **Edge-optimized endpoint configuration**, choose **Delete**.

1. Confirm your choice and delete the endpoint.

------
#### [ AWS CLI ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command migrates an edge-optmized custom domain name to a Regional custom domain name:

```
aws apigateway update-domain-name \
    --domain-name 'api.example.com' \
    --patch-operations  '[ 
        { "op":"add", "path": "/endpointConfiguration/types","value": "REGIONAL" },
        { "op":"replace", "path": "/securityPolicy", "value":"SecurityPolicy_TLS13_1_3_2025_09"},
        { "op":"add", "path": "/regionalCertificateArn", "value": "arn:aws:acm:us-west-2:123456789012:certificate/cd833b28-58d2-407e-83e9-dce3fd852149" }
      ]'
```

The Regional certificate must be of the same Region as the Regional API. 

The output will look like the following:

```
{
    "certificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/34a95aa1-77fa-427c-aa07-3a88bd9f3c0a",
    "certificateName": "edge-cert",
    "certificateUploadDate": "2017-10-16T23:22:57Z",
    "distributionDomainName": "d1frvgze7vy1bf.cloudfront.net",
    "domainName": "api.example.com",
    "endpointConfiguration": {
        "types": [
            "EDGE",
            "REGIONAL"
        ]
    },
    "securityPolicy": "SecurityPolicy_TLS13_1_3_2025_09",
    "endpointAccessMode": "BASIC",
    "regionalCertificateArn": "arn:aws:acm:us-west-2:123456789012:certificate/cd833b28-58d2-407e-83e9-dce3fd852149",
    "regionalDomainName": "d-fdisjghyn6.execute-api.us-west-2.amazonaws.com"
}
```

For the migrated Regional custom domain name, the resulting `regionalDomainName` property returns the Regional API hostname. You must set up a DNS record to point the Regional custom domain name to this Regional hostname. This enables the traffic that is bound to the custom domain name to be routed to the Regional host. 

After the DNS record is set, you can remove the edge-optimized custom domain name. The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command removes the edge-optimized custom domain name:

```
aws apigateway update-domain-name \
    --domain-name api.example.com \
    --patch-operations '[
            {"op":"remove", "path":"/endpointConfiguration/types", "value":"EDGE"},
            {"op":"remove", "path":"certificateName"},
            {"op":"remove", "path":"certificateArn"}
        ]'
```

------

The following procedure shows how to migrate a Regional custom domain name to an edge-optimized custom domain name.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose a Regional custom domain name.

1. For **Endpoint configuration**, choose **Edit**.

1. Choose **Add edge-optimized endpoint**.

1. For **ACM certificate**, choose a certificate.

    The edge-optimized domain certificate must be created in the `us-east-1` Region. 

1. Choose **Save**.

1. Set up a DNS record to point the edge-optimized custom domain name to this edge-optimized hostname. For more information, see [configuring Route 53 to route traffic to API Gateway](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

1. After you confirm that your DNS configuration is using the correct endpoint, you delete the Regional endpoint configuration. Choose your custom domain name, and then for **Regional endpoint configuration**, choose **Delete**.

1. Confirm your choice and delete the endpoint.

------
#### [ AWS CLI ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command migrates your Regional custom domain name to an edge-optimized custom domain name:

```
aws apigateway update-domain-name \
    --domain-name 'api.example.com' \
    --patch-operations  '[ 
        { "op":"add", "path": "/endpointConfiguration/types","value": "EDGE" },
        { "op":"add", "path": "/certificateName", "value": "edge-cert" },
	{"op":"add", "path": "/certificateArn", "value": "arn:aws:acm:us-east-1:738575810317:certificate/34a95aa1-77fa-427c-aa07-3a88bd9f3c0a"}
      ]'
```

The edge-optimized domain certificate must be created in the `us-east-1` Region. 

The output will look like the following:

```
{
    "certificateArn": "arn:aws:acm:us-east-1:738575810317:certificate/34a95aa1-77fa-427c-aa07-3a88bd9f3c0a",
    "certificateName": "edge-cert",
    "certificateUploadDate": "2017-10-16T23:22:57Z",
    "distributionDomainName": "d1frvgze7vy1bf.cloudfront.net",
    "domainName": "api.example.com",
    "endpointConfiguration": {
        "types": [
            "EDGE",
            "REGIONAL"
        ]
    },
    "regionalCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/3d881b54-851a-478a-a887-f6502760461d",
    "regionalDomainName": "d-cgkq2qwgzf.execute-api.us-east-1.amazonaws.com"
}
```

For the specified custom domain name, API Gateway returns the edge-optimized API hostname as the `distributionDomainName` property value. You must set a DNS record to point the edge-optimized custom domain name to this distribution domain name. This enables traffic that is bound to the edge-optimized custom domain name to be routed to the edge-optimized API hostname. 

After the DNS record is set, you can remove the `REGION` endpoint type of the custom domain name. The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command removes the Regional endpoint type:

```
aws apigateway update-domain-name \
    --domain-name api.example.com \
    --patch-operations '[
        {"op":"remove", "path":"/endpointConfiguration/types", value:"REGIONAL"},
        {"op":"remove", "path":"regionalCertificateArn"}
      ]'
```

The output looks like the following:

```
{
    "certificateArn": "arn:aws:acm:us-east-1:738575810317:certificate/34a95aa1-77fa-427c-aa07-3a88bd9f3c0a",
    "certificateName": "edge-cert",
    "certificateUploadDate": "2017-10-16T23:22:57Z",
    "distributionDomainName": "d1frvgze7vy1bf.cloudfront.net",
    "domainName": "api.example.com",
    "endpointConfiguration": {
        "types": "EDGE"
    }
}
```

------

# Send traffic to your APIs through your custom domain name in API Gateway
<a name="rest-api-routing-mode"></a>

When you configure the routing mode for your custom domain name, you set how incoming traffic is directed to your APIs. You send traffic to your APIs using routing rules, API mappings, or routing rules and API mappings. The following section explains when to use routing rules, when to use API mappings, and how to set the routing mode for your custom domain name.

## When to use routing rules
<a name="when-to-use-routing-rules"></a>

When you use routing rules, you direct incoming requests that match certain conditions to specific REST APIs stages. For example, a rule can route a request to the `production` stage of your `users` REST API it if contains the header `version:v1` and the base path `/users`. Use routing rules to create advanced dynamic routing topologies that support use cases like A/B testing or increasing usage of new versions of your APIs.

We recommend that when directing traffic to a REST API, you use routing rules for your custom domain name. You can recreate any API mappings by using routing rules. For more information, see [Recreate an API mapping using routing rules](rest-api-routing-rules-recreate-api-mapping.md).

For REST APIs, you can also use routing rules and API mappings together. When you use routing rules and API mappings together, API Gateway always evaluates routing rules before it evaluates any API mappings. Use routing rules and API mappings together to migrate your current custom domain names or to explore routing rules.

### Considerations for routing rules
<a name="considerations-for-private-preview"></a>

The following considerations might impact your use of routing rules:
+ WebSocket or HTTP APIs aren't supported as target APIs for routing rules.
+ If your custom domain name has API mappings to both REST and HTTP APIs, routing rules isn't supported.
+ You can create a routing rule for a private custom domain to a private REST API. You can create a routing rule for a public custom domain to a Regional or edge-optimized API. 
+ You can't create a routing rule for a public custom domain to a private API. You can't create a routing rule for a private custom domain name to a public API.

## Choose between routing rules and API mappings
<a name="choose-between-routing-rules-and-api-mappings"></a>

We recommend that when possible, you use routing rules. Only use API mappings to send traffic to an HTTP or WebSocket API.

# Set the routing mode for your custom domain name
<a name="set-routing-mode"></a>

You can choose which routing mode API Gateway uses to route traffic to your APIs. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md). This section discusses routing modes for custom domain names. You must set a routing mode for your custom domain name to route traffic to your APIs. The following routing modes are supported:
+ **ROUTING\$1RULE\$1THEN\$1API\$1MAPPING** – Use this mode to send traffic to your APIs with both routing rules and API mappings. In this mode, all routing rules take priority over any API mappings. For an example of this mode, see [Example 2: Routing rules and API mappings](rest-api-routing-rules-examples.md#rest-api-routing-rules-examples-rule-and-mappings). 
+ **ROUTING\$1RULE\$1ONLY** – Use this mode to only allow routing rules to send traffic to your APIs. When your custom domain name uses this mode, you can't create an API mapping, but you can use the [get-api-mappings](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-api-mappings.html) command to view them. API callers can’t use API mappings to access this domain name.
+ **API\$1MAPPING\$1ONLY** – Use this mode to only allow API mappings to send traffic to your APIs. When your custom domain name uses this mode, you can't create a routing rule, but you can use the `list-routing-rules` command to view them. API callers can’t use routing rules to access this domain name.

  This is the default routing mode for all your existing domain names, and any new domain names you create.

When you create a custom domain name using `apigateway`, `API_MAPPING_ONLY` is called `BASE_PATH_MAPPING_ONLY` and `ROUTING_RULE_THEN_API_MAPPING` is called `ROUTING_RULE_THEN_BASE_PATH_MAPPING`. This behavior is only present for the AWS CLI, CloudFormation, or any SDKs, not in the AWS Management Console.

The following procedure shows how to change the routing mode for an existing custom domain name. When you change the routing mode of your custom domain name, API callers can’t access your domain name using any unsupported routing modes.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane.

1. Choose a custom domain name.

1. For **Domain details**, choose **Edit**.

1. For **Routing mode**, choose **ROUTING\$1RULE\$1THEN\$1API\$1MAPPING**.

1. Choose **Save**.

If you change the routing mode to `ROUTING_RULE_ONLY` or `API_MAPPING_ONLY`, any API mappings or routing rules you've created are removed from the domain name details page of the console. If you change the routing mode to support either routing rules or API mappings, these resources will return.

------
#### [ AWS CLI - apigatewayv2 ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) command updates a domain name to use the routing mode `ROUTING_RULE_THEN_API_MAPPING`:

```
aws apigatewayv2 update-domain-name \
  --domain-name 'api.example.com' \
  --routing-mode "ROUTING_RULE_THEN_API_MAPPING"
```

The output will look like the following:

```
{
"ApiMappingSelectionExpression": "$request.basepath",
"DomainName": "api.example.com",
"DomainNameArn": "arn:aws:apigateway:us-west-2::/domainnames/api.example.com",
"DomainNameConfigurations": [
  {
      "ApiGatewayDomainName": "d-abcdefg.execute-api.us-west-2.amazonaws.com",
      "CertificateArn": "arn:aws:acm:us-west-2:111122223333:certificate/abcdefg-123456-abcdefg",
      "DomainNameStatus": "AVAILABLE",
      "EndpointType": "REGIONAL",
      "HostedZoneId": "Z2OJLYMUO9EFXC",
      "SecurityPolicy": "TLS_1_2"
   }
 ],
"RoutingMode": "ROUTING_RULE_THEN_API_MAPPING",
"Tags": {}
}
```

------
#### [ AWS CLI - apigateway ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command updates a private custom domain name to use the routing mode `ROUTING_RULE_THEN_BASE_PATH_MAPPING`:

```
aws apigateway update-domain-name \
  --domain-name 'private.example.com' \
  --patch-operations "op='replace',path='/routingMode',value='ROUTING_RULE_THEN_BASE_PATH_MAPPING'"
```

The output will look like the following:

```
{
"domainName": "private.example.com",
"domainNameId": "abcd1234",
"domainNameArn": "arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234",
"certificateArn": "arn:aws:acm:us-west-2:111122223333:certificate/a1b2c3d4-5678-90ab-cdef",
"certificateUploadDate": "2024-09-10T10:31:20-07:00",
"endpointConfiguration": {
  "types": [
    "PRIVATE"
   ],
  "ipAddressType": "dualstack"
  },
"domainNameStatus": "AVAILABLE",
"securityPolicy": "TLS_1_2",
"policy": "...",
"routingMode" : "ROUTING_RULE_THEN_BASE_PATH_MAPPING"
}
```

------

# Routing rules to connect API stages to a custom domain name for REST APIs
<a name="rest-api-routing-rules"></a>

A routing rule is a set of conditions that when matched, invoke an action. For example, a rule can route any incoming request to a custom domain name that contains the header `Hello:World` and contains the base path `users` to the `production` stage of a REST API.

Rules are evaluated in priority order, and if you set the routing mode to `ROUTING_RULE_THEN_API_MAPPING`, API Gateway always evaluates all routing rules before evaluating any API mappings. The following list describes how a routing rule uses conditions, actions, and priorities. 

**Conditions**  
When the conditions for a rule are met, then its actions are performed. API Gateway supports up to two header conditions and one path condition. API Gateway evaluates header conditions and base path conditions together.  
You can create a rule without any conditions. When API Gateway evaluates this rule, the action is always performed. You can create a rule without any conditions as a catch-all rule.  
For more information about header conditions, see [Match headers conditions](#rest-api-routing-rules-condition-headers). For more information about path conditions, see [Match base path conditions](#rest-api-routing-rules-condition-path). 

**Actions**  
Actions are the result of matching conditions to a routing rule. Currently, the only supported action is to invoke a stage of a REST API.  
Each rule can have one action.

**Priority**  
The priority determines what order the rules are evaluated in, from the lowest value to the highest value. Rules can't have the same priority.  
You can set the priority from 1-1,000,000. If a rule has a priority of one, API Gateway evaluates it first. We recommend that when you create a rule, you add gaps in priorities. This helps you switch the priority of rules and add new rules. For more information, see [Change the priority of a routing rule](apigateway-routing-rules-use.md#rest-api-routing-rules-change-priority).

For examples of how API Gateway evaluates routing rules, see [Examples of how API Gateway evaluates routing rules](rest-api-routing-rules-examples.md).

## API Gateway routing rule condition types
<a name="rest-api-routing-rules-condition-types"></a>

The following section describes the routing rule condition types. API Gateway only matches a rule if all conditions are true.

### Match headers conditions
<a name="rest-api-routing-rules-condition-headers"></a>

When you create a header condition, you can match the header name and header glob value, such as `Hello:World`. API Gateway uses a literal match to validate match headers conditions. Your condition can use up to two headers using `AND` between them. For example, your condition can match if an incoming request contains `Hello:World` and `x-version:beta`.

The header name matching is case insensitive, but the header glob value is case sensitive. `Hello:World` will match `hello:World`, but not `Hello:world`.

For a list of restricted header values see, [Restrictions](#rest-api-routing-rules-restrictions).

#### Using wildcards with header conditions
<a name="rest-api-routing-rules-condition-headers-wildcards"></a>

You can only use wildcards in the header glob value, and the wildcard must be `*prefix-match`, `suffix-match*`, or `*contains*`. The following table shows examples for how to use wildcards for matching for header conditions. 


|  Header conditions  |  Requests that match the routing rule  |  Requests that don't match the routing rule  | 
| --- | --- | --- | 
|  `x-version: a*`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  | 
|  `x-version: *a`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  | 
|  `x-version: *a*`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  | 
|  `x-version: *a*` and `x-version: *b*`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  | 
|  `x-version: b*` and `x-version: *a`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  | 
|  `x-version: *`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  None  | 

If you create conditions for multiple header values, such as `Accept:application/json,text/xml`, we recommend that you use `*contains*` for your header conditions and avoid creating conditions using the comma (`,`) character.

Because API Gateway matches header conditions literally, semantic matches might be routed differently. The following table shows the difference in routing rules outcomes.


|  Header conditions  |  Requests that match the routing rule  |  Requests that don't match the routing rule  | 
| --- | --- | --- | 
|  `Accept: *json`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  | 
|  `Accept: *json*`  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-routing-rules.html)  |  None  | 

### Match base path conditions
<a name="rest-api-routing-rules-condition-path"></a>

When you create a base path condition, if the incoming request contains the path you specified, the rule is matched. The matching is case sensitive, so the path `New/Users` will not match with `new/users`.

You can create a base path condition for only one base path.

For a list of restricted base path conditions, [Restrictions](#rest-api-routing-rules-restrictions).

#### Strip the base path with base path conditions
<a name="rest-api-routing-rules-condition-path-split"></a>

When you create a base path condition, you can choose to strip the base path. When you strip the base path, API Gateway removes the incoming matched base path when it invokes the target API. This is the same behavior as when you use an API mapping. When you don't strip the base path, API Gateway forwards the entire base path to the target API. We recommend that you only strip the base path when you are recreating an API mapping.

The following table shows examples for how API Gateway evaluates the strip base path condition.


|  Condition  | Strip base path |  Incoming request  |  Result  | 
| --- | --- | --- | --- | 
|  If base path contains `PetStoreShopper/dogs`  |  True  |  `GET https://example.com/PetStoreShopper/dogs`  |  API Gateway calls the `GET` method of the `/` resource.  | 
|  If base path contains `PetStoreShopper/dogs`.  |  False  |  `GET https://example.com/PetStoreShopper/dogs`  |  API Gateway calls the `GET` method of the `PetStoreShopper/dogs` resource.  | 
|  If base path contains `PetStoreShopper`  |  True  |  `GET https://example.com/PetStoreShopper/dogs`  |  API Gateway calls the `GET` method of the `dogs` resource.  | 
|  If base path contains `PetStoreShopper`  |  False  |  `GET https://example.com/PetStoreShopper/dogs`  |  API Gateway calls the `GET` method of the `PetStoreShopper/dogs` resource.  | 
|  If base path contains `PetStoreShopper`  |  True  |  `GET https://example.com/PetStoreShopper?birds=available`  |  API Gateway calls the `GET` method of the `/` resource with the query string parameter `birds=available`.  | 
|  If base path contains `PetStoreShopper`  |  False  |  `GET https://example.com/PetStoreShopper?birds=available`  |  API Gateway calls the `GET` method of the `/PetStoreShopper` resource with the query string parameter `birds=available`.  | 

## Restrictions
<a name="rest-api-routing-rules-restrictions"></a>
+ The target API and the custom domain name must be in the same AWS account.
+ Each rule can have one target API. 
+ You can only create a routing rule for a private custom domain name to a private API, and for a public custom domain name to a public API. You can't mix public and private resources.
+ If your custom domain name has API mappings to both REST and HTTP APIs, routing rules isn't supported.
+ The maximum priority number is 1,000,000.
+ Header restrictions:
  + Each `anyOf` condition can only contain one header value.
  + The only allowed characters for header names and header glob values are specified by [RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230), which are `a-z`, `A-Z`, `0-9`, and the following special characters: `*?-!#$%&'.^_`|~`.
  + You can use a wildcard in the header glob value, but the wildcard must be `*prefix-match`, `suffix-match*`, or `*contains*`. You can't use `*` in the middle of a header glob value.
  + Wildcard header names aren't supported.
  + The header name must be less than 40 characters.
  + The header glob value must be less than 128 characters.
  + The header glob value for an infix match must be less than 40 characters.
  + The following headers aren't supported as conditions:
    + `access-control-*`
    + `apigw-*`
    + `Authorization`
    + `Connection`
    + `Content-Encoding`
    + `Content-Length`
    + `Content-Location`
    + `Forwarded`
    + `Keep-Alive`
    + `Origin`
    + `Proxy-Authenticate`
    + `Proxy-Authorization`
    + `TE`
    + `Trailers`
    + `Transfer-Encoding`
    + `Upgrade`
    + `x-amz-*`
    + `x-amzn-*`
    + `x-apigw-api-id`
    + `X-Forwarded-For`
    + `X-Forwarded-Host`
    + `X-Forwarded-Proto`
    + `x-restAPI`
    + `Via`
+ Base path restrictions:
  + The base path length must be less than 128 characters.
  + The base path must contain only letters, numbers, and the following characters: `$-_.+!*'()/`.

    These characters aren't supported for regular expressions (regex). 
  + The base path can't start or end with backslash (`\`) character.

# Examples of how API Gateway evaluates routing rules
<a name="rest-api-routing-rules-examples"></a>

The following section shows four examples of how API Gateway evaluates routing rules and API mappings.

## Example 1: Routing rules only
<a name="rest-api-routing-rules-examples-rule-only"></a>

In this example, the custom domain name `https://petstore.example.com` has the routing mode set to `ROUTING_RULE_ONLY` and has the following routing rules and priorities.


|  Rule ID  |  Priority  |  Conditions  |  Action  | 
| --- | --- | --- | --- | 
|  `abc123`  |   10   |   If request contains header: `Hello:World`   |   Target API 1   | 
|  `zzz000`  |   50   |   If request contains headers: `Accept:image/webp` and `Pet:Dog-*` and if the base path contains `PetStoreShopper`  |   Target API 2   | 
|  `efg456`  |   100   |  None  |   Target API 3   | 

The following table shows how API Gateway applies the previous routing rules to example requests.


| Request | Selected API | Explanation | 
| --- | --- | --- | 
|  `https://petstore.example.com -h "Hello:World"`  |  Target API 1  |  The request matches the routing rule `abc123`.  | 
|  `https://petstore.example.com/PetStoreShopper -h "Hello:World", "Pet:Dog-Bella", "Accept:image/webp"`  |  Target API 1  |  API Gateway evaluates all routing rules in priority order. Routing rule `abc123` has the first priority and the conditions match, so API Gateway invokes Target API 1. Although the conditions of the request also match routing rule `zzz000`, API Gateway doesn't evaluate any other routing rules after it makes a match.  | 
|  `https://petstore.example.com/PetStoreShopper -h "Pet:Dog-Bella", "Accept:image/webp"`  |  Target API 2  |  The request matches the routing rule `zzz000`. This was a match because the `Pet:Dog-Bella` was a string match to `Pet:Dog-*`  | 
|  `https://petstore.example.com/PetStoreShopper -h "Pet:Dog-Bella"`  |  Target API 3  |  The request doesn't match the routing rule `abc123`. The request doesn't match routing rule `zzz000` as all the required headers aren't present. The next priority rule matches all incoming requests, so API Gateway invokes Target API 3.  | 

## Example 2: Routing rules and API mappings
<a name="rest-api-routing-rules-examples-rule-and-mappings"></a>

In this example, the custom domain name `https://petstore.diagram.example.com` has the routing mode set to `ROUTING_RULE_THEN_API_MAPPING` and has the following routing rules and API mappings.


|  Rule ID  |  Priority  |  Conditions  |  Action  | 
| --- | --- | --- | --- | 
|  `abc123`  |   1   |   If request the base contains `pets`   |   Invoke the `Prod` stage of the `PetStore` API.   | 
|  `000zzz`  |   5   |   If request contains headers: `Cookie`:`*ux=beta*` and and if the base path contains `/refunds`  |   Invoke the `Beta` stage of the `Refunds` API.   | 

The following table shows API mappings for `https://petstore.backup.example.com`.


|  API mapping  |  Selected API  | 
| --- | --- | 
|   `/refunds`   |   Invoke the `Prod` stage of the `Refunds` API.   | 
|   `(none)`   |   Invoke the `Prod` stage of the `Search` API.   | 

The following diagram shows how API Gateway applies the previous routing rules and API mappings to example requests. The example requests are summarized in the table after this diagram.

![\[Diagram of how API Gateway applies the previous routing rules and API mappings.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/rr-diagram.png)


The following table shows how API Gateway applies the previous routing rules and API mappings to example requests.


| Request | Selected API | Explanation | 
| --- | --- | --- | 
|  `https://petstore.diagram.com/pets`  |  The `Prod` stage of the `PetStore` API.  |  The request matches routing rule `abc123`.  | 
|  `https://petstore.diagram.example.com/refunds -h "Cookie:lang=en-us;ux=beta"`  |  The `Beta` stage of the `Refunds` API.  |  The request matches routing rule `000zzz`. The `Cookie` header contains the correct `*contains*` match and base path match for this condition.   | 
|  `https://petstore.diagram.example.com/refunds`  |  The `Prod` stage of the `Refunds` API.   |  The request doesn't have the required headers to match the routing rule `zzz000`. If API Gateway can't successfully match a routing rule, it falls back to API mappings. API Gateway can map the base path to the `Prod` stage of the `Refunds` API.   | 
|  `https://petstore.diagram.example.com/`  |  The `Prod` stage of the `Search` API.   |  The request matches the API mapping to the empty path `(none)`.  | 

## Example 3: Routing rules and API mappings with multiple level
<a name="rest-api-routing-rules-examples-rule-and-mappings-with-multiple-levels"></a>

In this example, the custom domain name `https://petstore.backup.example.com` has the routing mode set to `ROUTING_RULE_THEN_API_MAPPING` and has the following routing rules and API mappings.

The following table shows routing rules for `https://petstore.backup.example.com`.


|  Rule ID  |  Priority  |  Conditions  |  Action  | 
| --- | --- | --- | --- | 
|  `abc123`  |   10   |   If request contains header: `Hello:World`   |   Target API 1   | 
|  `000zzz`  |   50   |   If request contains headers: `Accept`:`image/webp` and `Pet:Dog-*` and if the base path contains `PetStoreShopper`  |  Target API 2  | 

The following table shows API mappings for `https://petstore.backup.example.com`.


|  API mapping  |  Selected API  | 
| --- | --- | 
|   `PetStoreShopper`   |   Target API 3   | 
|   `PetStoreShopper/cats`   |   Target API 4   | 

The following table shows how API Gateway applies the previous routing rules and API mappings to example requests.


| Request | Selected API | Explanation | 
| --- | --- | --- | 
|  `https://petstore.example.com/PetStoreShopper -h "Accept:image/webp", "Pet:Cats" `  |  Target API 3  |  The request doesn't have the required headers to match the routing rule `zzz000`. If API Gateway can't successfully match a routing rule, it falls back to API mappings. API Gateway can map the base path to Target API 3.  | 
|  `https://petstore.example.com/PetStoreShopper/cats -h "Hello:World"`  |  Target API 1  |  The request matches routing rule `abc123`. If the routing mode is set to `ROUTING_RULE_THEN_API_MAPPING`, routing rules always take priority over API mappings.  | 
|  `https://petstore.example.com/Admin -h "Pet:Dog-Bella"`  |  None  |  The request doesn't match any routing rules or API mappings. Since there is no default routing rule, API Gateway rejects the call and sends the caller a `403 Forbidden` status code.  | 

## Example 4: Routing rules for wildcard domain names
<a name="rest-api-routing-rules-examples-rule-for-wildcard-domains"></a>

In this example, the custom domain name `https://*.example.com` is a wildcard domain name. The wildcard supports all subdomains which route back to the same domain. The following example routing rules change this behavior to allow subdomains to route to different target APIs by using the `Host` header.

The following table shows routing rules for `https://*.example.com`.


|  Rule ID  |  Priority  |  Conditions  |  Action  | 
| --- | --- | --- | --- | 
|  `abc123`  |   10   |   If request contains header: `Host:a.example.com`   |   Target API 1   | 
|  `000zzz`  |   50   |   If request contains headers: `Host:b.example.com`  |  Target API 2  | 
|  `efg456`  |   500   |  None  |  Target API 3  | 

The following table shows how API Gateway applies the previous routing rules to example requests.


| Request | Selected API | Explanation | 
| --- | --- | --- | 
|  `https://a.example.com`  |  Target API 1  |  The `Host` header is `a.example.com`. This request matches routing rule `abc123`.  | 
|  `https://b.example.com`  |  Target API 2  |  The `Host` header is `b.example.com`. This request matches routing rule `000zzz`.  | 
|  `https://testing.example.com`  |  Target API 3  |  This matches the catch-all routing rule `efg456`.  | 

# How to use routing rules
<a name="apigateway-routing-rules-use"></a>

You can create a routing rule using the AWS Management Console, AWS CLI, or any AWS SDK. After you create a rule, you can change it's priority.

## Create a routing rule
<a name="rest-api-routing-rules-create"></a>

The following procedure shows how to create a routing rule for a custom domain name with a routing mode set to either `ROUTING_RULE_THEN_API_MAPPING` or `ROUTING_RULE_ONLY`.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose a custom domain name.

1. On the **Routing details** tab, choose **Add routing rule**.

1. Choose **Add a new condition** to add a new condition.

   You can add a header or base path condition. To match all incoming requests to your custom domain name, don't add a condition. 

1. For **Action**, use the dropdown to select your target API and target stage.

1. Choose **Next**.

1. In the priority field, enter a number for your priority.

   API Gateway evaluates rules in priority order, from the lowest value to the highest value.

   If you're creating a rule without a condition, we recommend that you use a high value priority.

1. Choose **Create routing rule**.

------
#### [ AWS CLI ]

The following [create-routing-rule](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-routing-rule.html) command creates a routing rule with a priority of 50. In this example, API Gateway routes any incoming requests that have the headers `Hello:World` and `x-version:beta` and the base path `PetStoreShopper` to the target API `a1b2c3`.

```
 aws apigatewayv2 create-routing-rule \
  --domain-name 'api.example.com' \
  --priority 50 \
  --conditions '[
    {
      "MatchHeaders": {
        "AnyOf": [
          {
            "Header": "Hello",
            "ValueGlob": "World"
          }
        ]
      }
    },
    {
      "MatchHeaders": {
        "AnyOf": [
          {
            "Header": "x-version",
            "ValueGlob": "beta"
          }
        ]
      }
    },
    {
      "MatchBasePaths": {
        "AnyOf": [
          "PetStoreShopper"
        ]
      }
    }
  ]'\
  --actions '[
  {
    "InvokeApi": {
      "ApiId": "a1b2c3",
      "Stage": "prod"
    }
  }
 ]'
```

The output will look like the following.

```
{
    "Actions": [
        {
            "InvokeApi": {
                "ApiId": "a1b2c3",
                "Stage": "prod",
                "StripBasePath": false
            }
        }
    ],
    "Conditions": [
        {
            "MatchHeaders": {
                "AnyOf": [
                    {
                        "Header": "Hello",
                        "ValueGlob": "World"
                    }
                ]
            }
        },
        {
            "MatchHeaders": {
                "AnyOf": [
                    {
                        "Header": "x-version",
                        "ValueGlob": "beta"
                    }
                ]
            }
        },
        {
            "MatchBasePaths": {
                "AnyOf": [
                    "PetStoreShopper"
                ]
            }
        }
    ],
    "Priority": 50,
    "RoutingRuleArn": "arn:aws:apigateway:us-west-2:111122223333:/domainnames/api.example.com/routingrules/abc123",
    "RoutingRuleId": "abc123"
}
```

------

## Change the priority of a routing rule
<a name="rest-api-routing-rules-change-priority"></a>

You can change the priority of a routing rule. This takes effect immediately and might impact how API consumers invoke your custom domain names. We recommend that when you set the priorities of your routing rules, you leave gaps between rules.

For example, consider two routing rules, rule `abc123` with a priority of 50 and rule `zzz000` with a priority of 150. To change the priority of the rules so that API Gateway evaluates rule `zzz000` first, you can change the priority of rule `zzz000` to 30.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose a custom domain name.

1. On the **Routing details** tab, choose your routing rule, and then choose **Edit**. 

1. Choose **Next**.

1. For priority, enter the new priority.

1. Choose **Save changes**.

------
#### [ AWS CLI ]

The following [put-routing-rule](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/put-routing-rule.html) command changes the priority of a routing rule `abc123`.

```
 aws apigatewayv2 put-routing-rule \
  --domain-name 'api.example.com' \
  --priority 30 \
  --routing-rule-id abc123 \
  --conditions '[
    {
      "MatchHeaders": {
        "AnyOf": [
          {
            "Header": "Hello",
            "ValueGlob": "World"
          }
        ]
      }
    },
    {
      "MatchHeaders": {
        "AnyOf": [
          {
            "Header": "x-version",
            "ValueGlob": "beta"
          }
        ]
      }
    },
    {
      "MatchBasePaths": {
        "AnyOf": [
          "PetStoreShopper"
        ]
      }
    }
  ]'\
  --actions '[
  {
    "InvokeApi": {
      "ApiId": "a1b2c3",
      "Stage": "prod"
    }
  }
 ]'
```

The output will look like the following:

```
{
    "Actions": [
        {
            "InvokeApi": {
                "ApiId": "a1b2c3",
                "Stage": "prod",
                "StripBasePath": false
            }
        }
    ],
    "Conditions": [
        {
            "MatchHeaders": {
                "AnyOf": [
                    {
                        "Header": "Hello",
                        "ValueGlob": "World"
                    }
                ]
            }
        },
        {
            "MatchHeaders": {
                "AnyOf": [
                    {
                        "Header": "x-version",
                        "ValueGlob": "beta"
                    }
                ]
            }
        },
        {
            "MatchBasePaths": {
                "AnyOf": [
                    "PetStoreShopper"
                ]
            }
        }
    ],
    "Priority": 38,
    "RoutingRuleArn": "arn:aws:apigateway:us-west-2:111122223333:/domainnames/api.example.com/routingrules/abc123",
    "RoutingRuleId": "abc123"
}
```

------

# Recreate an API mapping using routing rules
<a name="rest-api-routing-rules-recreate-api-mapping"></a>

You can recreate an API mapping using routing rules. To recreate an API mapping, make sure to turn on base path striping. This preserves the behavior of API mappings. For more information, see [Strip the base path with base path conditions](rest-api-routing-rules.md#rest-api-routing-rules-condition-path-split).

The following tutorial shows how to recreate the API mapping `https:// api.example.com/orders/v2/items/categories/5` as a routing rule and how to update your access logs to log the routing rule ID API Gateway uses to send traffic to your API.

------
#### [ AWS Management Console ]

**To set the routing mode to ROUTING\$1RULE\$1THEN\$1API\$1MAPPING**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose your custom domain name.

1. For **Domain details**, choose **Edit**.

1. For **Routing mode**, choose **ROUTING\$1RULE\$1THEN\$1API\$1MAPPING**.

1. Choose **Save** 

After you set the routing mode, you create the routing rule.

**To create the routing rule**

1. On the **Routing details** tab, choose **Add routing rule**.

1. Choose **Add new condition** and then choose **Path**.

1. For **Path**, enter **orders/v2/items/categories/5**.

1. For **Strip base path**, choose **Active**.

1. For **Target API**, choose your target API.

1. For **Target stage**, choose your target stage.

1. Choose **Next**.

1. For priority, enter a priority.

   Even if you keep your existing API mapping, API Gateway will always use the new routing rule as routing rules always take priority over API mappings.

1. Choose **Save changes**.

After you create the routing rule, update the access log format for your stage or create a new log to confirm that API Gateway uses your routing rule to send traffic to your API.

**To update your access logs**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose your API.

1. In the main navigation pane, choose **Stages**.

1. For **Logs and tracing**, choose **Edit**.

   If you don't have a log group, see [Set up CloudWatch logging for REST APIs in API Gateway](set-up-logging.md).

1. Add **\$1context.customDomain.routingRuleIdMatched** to your log format.

   This log group records the routing rule ID that API Gateway used to send traffic to your API. For more information, see [I can't tell how API Gateway sent traffic to my APIs](rest-api-routing-rules-troubleshoot.md#rest-api-routing-rules-logging).

1. Choose **Save**.

After you update your access logs, invoke your custom domain name. The following is an example curl command to invoke the custom domain name `https://api.example.com` with the base path `orders/v2/items/categories/5`.

```
curl "https://api.example.com/orders/v2/items/categories/5"
```

After you have successfully invoked your custom domain name, confirm that CloudWatch Logs shows the `routingRuleIdMatched`. To learn how to use the CloudWatch Logs console to view a log group, see [View API Gateway log events in the CloudWatch console](view-cloudwatch-log-events-in-cloudwatch-console.md).

------
#### [ AWS CLI ]

1. Use the following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) command to update the domain name `api.example.com` to use the routing mode `ROUTING_RULE_THEN_API_MAPPING`.

   ```
   aws apigatewayv2 update-domain-name \
     --domain-name 'api.example.com' \
     --routing-mode ROUTING_RULE_THEN_API_MAPPING
   ```

1. Use the following [create-routing-rule](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-routing-rule.html) command to create a new routing rule to recreate the API mapping `https://api.example.com/orders/v2/items/categories/5`.

   ```
   aws apigatewayv2 create-routing-rule \
     --domain-name 'api.example.com' \
     --priority 50 \
     --conditions '[
     {
       "MatchBasePaths": {
         "AnyOf": [
           "orders/v2/items/categories/5"
         ]
       }
     }
   ]' \
     --actions '[
     {
       "InvokeApi": {
         "ApiId": "a1b2c3",
         "Stage": "prod",
         "StripBasePath": true
       }
     }
   ]'
   ```

1. Use the following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command to update the access logs format to include the `$context.customDomain.routingRuleIdMatched` variable. This variable records the routing rule ID that API Gateway used to send traffic to your API. You use this log to confirm that API Gateway uses your routing rule to send traffic to your API. For more information, see [I can't tell how API Gateway sent traffic to my APIs](rest-api-routing-rules-troubleshoot.md#rest-api-routing-rules-logging).

   ```
   aws apigateway update-stage \
     --rest-api-id a1bc2c3 \
     --stage-name prod \
     --patch-operations "op=replace,path=/accessLogSettings/format,value='\$context.path \$context.customDomain.routingRuleIdMatched \$context.requestId \$context.extendedRequestId'"
   ```

   If you don't have a log group, see [Set up CloudWatch logging for REST APIs in API Gateway](set-up-logging.md).

1. Use the following example curl command to invoke your custom domain name with the base path `orders/v2/items/categories/5`.

   ```
   curl "https://api.example.com/orders/v2/items/categories/5
   ```

1. Use the following [filter-log-events](https://docs.aws.amazon.com/cli/latest/reference/logs/filter-log-events.html) command to get the log events from the log group `access-log-group-orders` that contain routing rule ID `abc123`.

   ```
   aws logs filter-log-events --log-group-name access-log-group-orders --filter-pattern abc123
   ```

    This confirms that API Gateway used the routing rule to send traffic to your API.

------

# Troubleshooting issues with routing rules
<a name="rest-api-routing-rules-troubleshoot"></a>

The following troubleshooting guidance might help resolve issues with your routing rules.

## I can't tell how API Gateway sent traffic to my APIs
<a name="rest-api-routing-rules-logging"></a>

You can use access logs for your REST API stage to log and troubleshoot your routing rules. You can view the routing rule ID that API Gateway used to send traffic to your API using the `$context.customDomain.routingRuleIdMatched` variable. To view the API mapping that API Gateway used to send traffic to your API, use the `$context.customDomain.basePathMatched` variable. 

 To log your routing rules, you need to configure [an appropriate CloudWatch Logs role](set-up-logging.md#set-up-access-logging-permissions) ARN for your account and create a log group.

The following example access log group can retrieve the relevant information for troubleshooting routing rules and API mappings. API Gateway only populates the context variable for the routing mechanism it used, otherwise the context variable is `-`. 

------
#### [ CLF ]

```
$context.path $context.customDomain.routingRuleIdMatched $context.customDomain.basePathMatched $context.requestId $context.extendedRequestId
```

------
#### [ JSON ]

```
{"requestPath": "$context.path", "routingRuleId" : "$context.customDomain.routingRuleIdMatched", "API mapping" : "$context.customDomain.basePathMatched", "requestId":"$context.requestId", "extendedRequestId":"$context.extendedRequestId"}
```

------
#### [ XML ]

```
<request id="$context.requestId"> <requestPath>$context.path</requestPath> <ruleId>$context.customDomain.routingRuleIdMatched</ruleId> <ApiMapping>$context.customDomain.basePathMatched</ApiMapping> <extendedRequestId>$context.extendedRequestId</extendedRequestId> </request>
```

------
#### [ CSV ]

```
$context.path,$context.customDomain.routingRuleIdMatched,$context.customDomain.basePathMatched,$context.requestId,$context.extendedRequestId
```

------

We also recommend that you confirm the routing mode for your custom domain name. For more information, see [Set the routing mode for your custom domain name](set-routing-mode.md).

## I can't enable routing rules on my custom domain name
<a name="rest-routing-rules-access-denied"></a>

You might receive the following error from API Gateway:

```
Your account doesn’t have permission to use RoutingRules.
This might be caused by an IAM policy in your account with a deny statement on BasePathMapping or ApiMapping.
To grant permission for this account to use RoutingRules, use the UpdateAccount API.
This will impact any existing IAM policies that deny access to BasePathMapping or ApiMapping.
See API Gateway documentation for further details.
```

You'll receive this error if have or had an IAM policy that denies access to [BasePathMapping](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonapigatewaymanagement.html#amazonapigatewaymanagement-resources-for-iam-policies) or [ApiMapping](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonapigatewaymanagementv2.html#amazonapigatewaymanagementv2-resources-for-iam-policies). When you enable routing rules for a custom domain name, although your policy will continue to deny access to `BasePathMapping` or `ApiMapping`, the same policy can be used to access `RoutingRule`. This might allow a user to change the routing behavior of your custom domain name.

For example, if you had a policy like the following:

```
{
    "Sid": "DenyCreatingApiMappings",
    "Effect": "Deny",
    "Action": "apigateway:POST",
    "Resource": [
        "arn:aws:apigateway:us-west-2::/domainnames/example.com/apimappings"
    ]
}
```

When you enable routing rules for `example.com`, this policy will continue to deny access to creating an `ApiMapping` but will not deny access to creating a `RoutingRule`.

We recommend that you audit the IAM policies in your account. The following example policy will deny access to creating `ApiMapping`, `BasePathMapping`, and `RoutingRule`:

```
{
    "Sid": "DenyCreatingBasePathMappingsApiMappings",
    "Effect": "Deny",
    "Action": "apigateway:POST",
    "Resource": [
        "arn:aws:apigateway:us-west-2::/domainnames/example.com/basepathmappings",
        "arn:aws:apigateway:us-west-2::/domainnames/example.com/apimappings"
    ]
},
{
    "Sid": "DenyCreatingRoutingRules",
    "Effect": "Deny",
    "Action": "apigateway:CreateRoutingRule",
    "Resource": [
        "arn:aws:apigateway:us-west-2:111122223333:/domainnames/example.com/routingrules/*"
    ]
}
```

After you have confirmed all your policies have been updated, you can update your API's account-level settings to enable routing rules for a Region.

Use the following [update-account](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-account.html) command to update the settings for your API's account-level settings for a Region:

```
aws apigateway update-account --patch-operations 'op=remove,path=/features,value=BlockedForRoutingRules' --region us-west-2
```

After you update your API's account-level settings, you can change the routing mode of your custom domain name. You can also continue to use IAM policies to deny access to `RoutingRules`, `ApiMapping` or `BasePathMapping`.

# Use API mappings to connect API stages to a custom domain name for REST APIs
<a name="rest-api-mappings"></a>

You use API mappings to connect API stages to a custom domain name. This sends traffic to your APIs through your custom domain name.

An API mapping specifies an API, a stage, and optionally a path to use for the mapping. For example, you can map `https://api.example.com/orders` to the `production` stage of an API.

You can map HTTP and REST API stages to the same custom domain name.

Before you create an API mapping, you must have an API, a stage, and a custom domain name. To learn more about creating a custom domain name, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md).

## Incoming requests to your custom domain name
<a name="rest-api-mappings-incoming-requests"></a>

When you map a custom domain name to a stage of your API, API Gateway strips the incoming base path. This removes the mapped base path from the invocation to the API. For instance, if your base path mapping was `https://api.example.com/orders/shop/5` to the `test` stage, and you used the following request, `https://api.example.com/orders/shop/5/hats`, API Gateway would invoke the `/hats` resource of the `test` stage of your API, not the `orders/shop/5/hats` resource.

## Mapping API requests
<a name="rest-api-mappings-evalutation"></a>

The following explains how API Gateway evaluates API mappings.

You can create an API mapping using single-level mappings, such an API mapping from `orders` to the `beta` stage of an API and an API mapping from `shipping` to the `alpha` stage of an API. For a Regional custom domain names with the TLS 1.2 security policy, API Gateway supports multi-level API mappings. You can create an API mapping from `orders/v1/items` to the `alpha` stage of an API and `orders/v2/items` to the `beta` stage of an API. When you create a mapping with multiple levels, API Gateway sends requests to the API mapping that has the longest matching path.

You can create an API mapping to the empty path `(none)`. If no path matches the request, API Gateway sends the request to the empty path `(none)`.

In this example, the custom domain name `https://api.example.com` has the following API mappings.


|  API Mapping  |  Selected API  | 
| --- | --- | 
|  `(none)`  |   API 1   | 
|   `orders`   |   API 2   | 
|  `orders/v1/items`  |   API 3   | 
|  `orders/v2/items`  |   API 4   | 
|  `orders/v1/items/categories`  |   API 5   | 

The following table shows how API Gateway applies the previous API mappings to example requests.


| Request | Selected API | Explanation | 
| --- | --- | --- | 
|  `https://api.example.com/orders`  |  API 2  |  The request exactly matches this API mapping.  | 
|  `https://api.example.com/orders/v1/items`  |  API 3  |  The request exactly matches this API mapping.  | 
|  `https://api.example.com/orders/v2/items`  |  API 4  |  The request exactly matches this API mapping.  | 
|  `https://api.example.com/orders/v1/items/123`  |  API 3  |  API Gateway chooses the mapping that has the longest matching path. The `123` at the end of the request doesn't affect the selection. See [Incoming requests to your custom domain name](#rest-api-mappings-incoming-requests).  | 
|  `https://api.example.com/orders/v2/items/categories/5`  |  API 5  |  API Gateway chooses the mapping that has the longest matching path.  | 
|  `https://api.example.com/customers`  |  API 1  |  API Gateway uses the empty mapping as a catch-all.  | 
|  `https://api.example.com/ordersandmore`  |  API 2  |  API Gateway chooses the mapping that has the longest matching prefix. For a custom domain name configured with single-level mappings, such as only `https://api.example.com/orders` and `https://api.example.com/`, API Gateway would choose `API 1`, as there is no matching path with `ordersandmore`.  | 

## Restrictions
<a name="rest-api-mappings-restrictions"></a>
+ In an API mapping, the custom domain name and mapped APIs must be in the same AWS account.
+ API mappings must contain only letters, numbers, and the following characters: `$-_.+!*'()/`.
+ The maximum length for the path in an API mapping is 300 characters.
+ You can have 200 API mappings with multiple levels for each domain name. This limit doesn't include API mapping with single levels, such as `/prod`.
+ You can only map HTTP APIs to a regional custom domain name with the TLS 1.2 security policy.
+ You can't map WebSocket APIs to the same custom domain name as an HTTP API or REST API.
+ After you create your API mappings, you must create or update your DNS provider's resource record to map to your API endpoint.
+ If you create an API mappings with multiple levels, API Gateway converts all header names to lowercase.

## Create an API mapping
<a name="rest-api-mappings-examples"></a>

To create an API mapping, you must first create a custom domain name, API, and stage. Your custom domain name must have a routing mode set to either `ROUTING_RULE_THEN_API_MAPPING` or `API_MAPPING_ONLY`. For information about how to set the routing mode, see [Set the routing mode for your custom domain name](set-routing-mode.md).

For example AWS Serverless Application Model templates that create all resources, see [Sessions With SAM](https://github.com/aws-samples/sessions-with-aws-sam/tree/master/custom-domains) on GitHub.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Custom domain names** from the main navigation pane. 

1. Choose a custom domain name.

1. On the **Routing details** tab, choose **Configure API mappings**.

1. Enter the **API**, **Stage**, and **Path** for the mapping.

1. Choose **Save**.

------
#### [ AWS CLI ]

The following [create-api-mapping](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api-mapping.html) command creates an API mapping. In this example, API Gateway sends requests to `api.example.com/v1/orders` to the specified API and stage.

**Note**  
To create API mappings with multiple levels, you must use `apigatewayv2`.

```
aws apigatewayv2 create-api-mapping \
    --domain-name api.example.com \
    --api-mapping-key v1/orders \
    --api-id a1b2c3d4 \
    --stage test
```

------
#### [ CloudFormation ]

The following CloudFormation example creates an API mapping.

**Note**  
To create API mappings with multiple levels, you must use `AWS::ApiGatewayV2`.

```
MyApiMapping:
  Type: 'AWS::ApiGatewayV2::ApiMapping'
  Properties:
    DomainName: api.example.com
    ApiMappingKey: 'orders/v2/items'
    ApiId: !Ref MyApi
    Stage: !Ref MyStage
```

------

# IP address types for custom domain names in API Gateway
<a name="rest-custom-domain-ip-address-type"></a>

When you create a custom domain name, you specify the type of IP addresses that can invoke your domain. You can choose IPv4 to resolve IPv4 addresses to invoke your domain, or you can choose dualstack to allow both IPv4 and IPv6 addresses to invoke your domain. We recommend that you set the IP address type to dualstack to alleviate IP space exhaustion or for your security posture. For more information about the benefits of a dualstack IP address type, see [IPv6 on AWS](https://docs.aws.amazon.com/whitepapers/latest/ipv6-on-aws/internet-protocol-version-6.html).

You can change the IP address type by updating the endpoint configuration of your domain name.

## Considerations for IP address types
<a name="api-gateway-ip-address-type-considerations"></a>

The following considerations might impact your use of IP address types.
+ The default IP address type for API Gateway custom domain names for public APIs is IPv4.
+ Private custom domain names can only have a dualstack IP address type.
+ Your custom domain name doesn't need to have the same IP address type for all APIs mapped to it. If you disable your default API endpoint, this might affect how callers can invoke your domain.

## Change the IP address type of a custom domain name
<a name="rest-custom-domain-ip-address-type-change"></a>

You can change the IP address type by updating the domain name's endpoint configuration. You can update the endpoint configuration by using the AWS Management Console, the AWS CLI, CloudFormation, or an AWS SDK.

------
#### [ AWS Management Console ]

**To change the IP address type of a custom domain name**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a public custom domain name.

1. Choose **Endpoint configuration**.

1. For IP address type, select either **IPv4** or **Dualstack**.

1. Choose **Save**.

------
#### [ AWS CLI ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command updates an API to have an IP address type of dualstack:

```
aws apigateway update-domain-name \
    --domain-name dualstack.example.com \
    --patch-operations "op='replace',path='/endpointConfiguration/ipAddressType',value='dualstack'"
```

The output will look like the following:

```
{
    "domainName": "dualstack.example.com",
    "certificateUploadDate": "2025-02-04T14:46:10-08:00",
    "regionalDomainName": "d-abcd1234.execute-api.us-east-1.amazonaws.com",
    "regionalHostedZoneId": "Z3LQWSYCGH4ADY",
    "regionalCertificateArn": "arn:aws:acm:us-east-1:111122223333:certificate/a1b2c3d4-5678-90ab-cdef",
    "endpointConfiguration": {
        "types": [
            "REGIONAL"
        ],
        "ipAddressType": "dualstack"
    },
    "domainNameStatus": "AVAILABLE",
    "securityPolicy": "TLS_1_2",
    "tags": {}
}
```

------

# Choose a security policy for your custom domain in API Gateway
<a name="apigateway-custom-domain-tls-version"></a>

A *security policy* is a predefined combination of minimum TLS version and cipher suites offered by API Gateway. When your clients establish a TLS handshake to your API or custom domain name, the security policy enforces the TLS version and cipher suite accepted by API Gateway. Security policies protect your APIs and custom domain names from network security problems such as tampering and eavesdropping between a client and server.

API Gateway supports legacy security policies and enhanced security policies. `TLS_1_0` and `TLS_1_2` are legacy security policies. Use these security policies for generalized workloads, or to get started creating an API. Any policy that starts with `SecurityPolicy_` is an enhanced security policy. Use these policies for regulated workloads, advanced governance, or to use post-quantum cryptography. When you use an enhanced security policy, you must also set the endpoint access mode for additional governance. For more information, see [Endpoint access mode](apigateway-security-policies.md#apigateway-security-policies-endpoint-access-mode).

## Considerations
<a name="apigateway-custom-domain-tls-version-considerations"></a>

The following are considerations for security policies for custom domain names for REST APIs in API Gateway:
+ You can't enable mutual TLS on a domain name that uses an enhanced security policy.
+ You can't map an HTTP API to a domain name that uses an enhanced security policy.
+ If you enable multi-level base path mapping to a REST API that uses an enhanced security policy, you can’t create a base path mapping to an HTTP API for the same domain name.
+ Your API can be mapped to a custom domain name with a different security policy than your API. When you invoke that custom domain name, API Gateway uses the security policy of the API to negotiate the TLS handshake. If you disable your default API endpoint, this might affect how callers can invoke your API.
+ API Gateway supports security policies on all APIs. However, you can only choose a security policy for REST APIs. API Gateway only supports the `TLS_1_2` security policy for HTTP or WebSocket APIs.
+ API Gateway doesn't support updating a security policy for a domain name with multiple endpoint types. If you have multiple endpoint types for a domain name, delete one of them to update the security policy.

## How API Gateway applies security policies
<a name="apigateway-custom-domain-tls-version-understanding"></a>

The following example shows how API Gateway applies security policies using the `SecurityPolicy_TLS13_1_3_2025_09` security policy as an example.

The `SecurityPolicy_TLS13_1_3_2025_09` security policy accepts TLS 1.3 traffic and rejects TLS 1.2 and TLS 1.0 traffic. For TLS 1.3 traffic, the security policy accepts the following cipher suites:
+ `TLS_AES_128_GCM_SHA256`
+ `TLS_AES_256_GCM_SHA384`
+ `TLS_CHACHA20_POLY1305_SHA256`

API Gateway does not accept any other cipher suites. For instance, the security policy would reject any TLS 1.3 traffic that uses the `AES128-SHA` cipher suite.

To monitor which TLS protocol and ciphers clients used to access your API Gateway, you can use the `$context.tlsVersion` and `$context.cipherSuite` context variables in your access logs. For more information, see [Monitor REST APIs in API Gateway](rest-api-monitor.md).

To see the default security policies for all REST APIs and custom domain names, see [Default security policies](apigateway-security-policies-list.md#apigateway-security-policies-default). To see the supported security policies for all REST APIs and custom domain names, see [Supported security policies](apigateway-security-policies-list.md).

## Change your custom domain name's security policy
<a name="apigateway-security-policies-update-custom-domain-name"></a>

If you change your security policy, it takes about 15 minutes for the update to complete. You can monitor the `lastUpdateStatus` of your custom domain name. As your custom domain name updates, the `lastUpdateStatus` is `PENDING` and when it completes, it will be `AVAILABLE`.

When you use a security policy that starts with `SecurityPolicy_`, you must also turn on endpoint access mode. For more information, see [Endpoint access mode](apigateway-security-policies.md#apigateway-security-policies-endpoint-access-mode).

------
#### [ AWS Management Console ]

**To change the security policy of a custom domain name**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a custom domain name that sends traffic to REST APIs.

   Make sure there is only one endpoint type associated with your custom domain name.

1. Choose **Custom domain name settings**, and then choose **Edit**.

1. For **Security policy**, select a new policy.

1. For **Endpoint access mode**, choose **Strict**.

1. Choose **Save changes**.

------
#### [ AWS CLI ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command updates a domain name to use the `SecurityPolicy_TLS13_1_3_2025_09` security policy:

```
aws apigateway update-domain-name \
    --domain-name example.com \
    --patch-operations '[
        {
            "op": "replace",
            "path": "/securityPolicy",
            "value": "SecurityPolicy_TLS13_1_3_2025_09"
        }, 
        {
            "op": "replace",
            "path": "/endpointAccessMode",
            "value": "STRICT"
        }
    ]'
```

The output will look like the following:

```
{
   "domainName": "example.com",
   "endpointConfiguration": { 
      "types": [ "REGIONAL" ], 
      "ipAddressType": "dualstack" 
   },
   "regionalCertificateArn": "arn:aws:acm:us-west-2:111122223333:certificate/a1b2c3d4-5678-90ab-cdef",
   "securityPolicy": "SecurityPolicy_TLS13_1_3_2025_09",
   "endpointAccessMode": "STRICT"
}
```

------

## Information about HTTP APIs and WebSocket APIs
<a name="apigateway-rest-additional-apis"></a>

For more information about HTTP APIs and WebSocket APIs, see [Security policy for HTTP APIs in API Gateway](http-api-ciphers.md) and [Security policy for WebSocket APIs in API Gateway](websocket-api-ciphers.md).

# Disable the default endpoint for REST APIs
<a name="rest-api-disable-default-endpoint"></a>

By default, clients can invoke your API by using the `execute-api` endpoint that API Gateway generates for your API. To ensure that clients can access your API only by using a custom domain name, disable the default `execute-api` endpoint. Clients can still connect to your default endpoint, but they will receive a `403 Forbidden` status code. Disabling the default endpoint affects all stages of the API. This setting takes affect when you update any setting on any stage, such as updating the deployment on the stage.

The following procedure shows how to disable the default endpoint for a REST API.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. On the main navigation pane, choose **API settings**.

1. Choose an API.

1. On **API details**, choose **Edit**.

1. For **Default endpoint**, select **Inactive**.

1. Choose **Save changes**.

1. On the main navigation pane, choose **Resources**.

1. Choose **Deploy API**.

1. Redeploy your API to a stage or update any setting on a stage for the update to take effect.

------
#### [ AWS CLI ]

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command disables the default endpoint: 

```
aws apigateway update-rest-api \
    --rest-api-id abcdef123 \
    --patch-operations op=replace,path=/disableExecuteApiEndpoint,value='True'
```

After you disable the default endpoint, you must deploy your API for the change to take effect.

The following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command creates a deployment and associates it with a stage:

```
aws apigateway create-deployment \
    --rest-api-id abcdef123 \
    --stage-name dev
```

------

# Configure custom health checks for DNS failover for an API Gateway API
<a name="dns-failover"></a>

You can use Amazon Route 53 health checks to control DNS failover from an API Gateway API in a primary AWS Region to one in a secondary Region. This can help mitigate impacts in the event of a Regional issue. If you use a custom domain, you can perform failover without requiring clients to change API endpoints.

When you choose [Evaluate Target Health](https://docs.aws.amazon.com/Route53/latest/APIReference/API_AliasTarget.html#Route53-Type-AliasTarget-EvaluateTargetHealth>Evaluate Target Health) for an alias record, those records fail only when the API Gateway service is unavailable in the Region. In some cases, your own API Gateway APIs can experience interruption before that time. To control DNS failover directly, configure custom Route 53 health checks for your API Gateway APIs. For this example, you use a CloudWatch alarm that helps operators control DNS failover. For more examples and other considerations when you configure failover, see [Creating Disaster Recovery Mechanisms Using Route 53](https://aws.amazon.com/blogs/networking-and-content-delivery/creating-disaster-recovery-mechanisms-using-amazon-route-53/) and [Performing Route 53 health checks on private resources in a VPC with AWS Lambda and CloudWatch](https://aws.amazon.com/blogs/networking-and-content-delivery/performing-route-53-health-checks-on-private-resources-in-a-vpc-with-aws-lambda-and-amazon-cloudwatch/).

**Topics**
+ [Prerequisites](#dns-failover-prereqs)
+ [Step 1: Set up resources](#dns-failover-intial-setup)
+ [Step 2: Initiate failover to the secondary Region](#dns-failover-initiate)
+ [Step 3: Test the failover](#dns-failover-test)
+ [Step 4: Return to the primary region](#dns-failover-return)
+ [Next steps: Customize and test regularly](#dns-failover-next-steps)

## Prerequisites
<a name="dns-failover-prereqs"></a>

To complete this procedure, you must create and configure the following resources:
+ A domain name that you own.
+ An ACM certificate for that domain name in two AWS Regions. For more info, see [Prerequisites for custom domain names](how-to-custom-domains.md#how-to-custom-domains-prerequisites).
+ A Route 53 hosted zone for your domain name. For more information, see [Working with hosted zones](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-working-with.html) in the Amazon Route 53 Developer Guide.

For more information on how to create Route 53 failover DNS records for the domain names, see [Choose a routing policy](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html) in the Amazon Route 53 Developer Guide. For more information on how to monitor a CloudWatch alarm, see [Monitoring a CloudWatch alarm](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/health-checks-creating-values.html#health-checks-creating-values-cloudwatch) in the Amazon Route 53 Developer Guide.

## Step 1: Set up resources
<a name="dns-failover-intial-setup"></a>

In this example, you create the following resources to configure DNS failover for your domain name:
+ API Gateway APIs in two AWS Regions
+ API Gateway custom domain names with the same name in two AWS Regions
+ API Gateway API mappings that connect your API Gateway APIs to the custom domain names
+ Route 53 failover DNS records for the domain names
+ A CloudWatch alarm in the secondary Region
+ A Route 53 health check based on the CloudWatch alarm in the secondary Region

First, make sure that you have all of the required resources in the primary and secondary Regions. The secondary Region should contain the alarm and health check. This way, you don't depend on the primary Region to perform failover. For example CloudFormation templates that create these resources, see [samples/primary.zip](samples/primary.zip) and [samples/secondary.zip](samples/secondary.zip).

**Important**  
Before failover to the secondary Region, make sure that all required resources are available. Otherwise, your API won't be ready for traffic in the secondary Region. 

## Step 2: Initiate failover to the secondary Region
<a name="dns-failover-initiate"></a>

In the following example, the standby Region receives a CloudWatch metric and initiates failover. We use a custom metric that requires operator intervention to initiate failover.

```
aws cloudwatch put-metric-data \
    --metric-name Failover \
    --namespace HealthCheck \
    --unit Count \
    --value 1 \
    --region us-west-1
```

Replace the metric data with the corresponding data for the CloudWatch alarm you configured.

## Step 3: Test the failover
<a name="dns-failover-test"></a>

Invoke your API and verify that you get a response from the secondary Region. If you used the example templates in step 1, the response changes from `{"message": "Hello from the primary Region!"}` to `{"message": "Hello from the secondary Region!"}` after failover.

```
curl https://my-api.example.com

{"message": "Hello from the secondary Region!"}
```

## Step 4: Return to the primary region
<a name="dns-failover-return"></a>

To return to the primary Region, send a CloudWatch metric that causes the health check to pass.

```
aws cloudwatch put-metric-data \
    --metric-name Failover \
    --namespace HealthCheck \
    --unit Count \
    --value 0 \
    --region us-west-1
```

Replace the metric data with the corresponding data for the CloudWatch alarm you configured.

Invoke your API and verify that you get a response from the primary Region. If you used the example templates in step 1, the response changes from `{"message": "Hello from the secondary Region!"}` to `{"message": "Hello from the primary Region!"}`.

```
curl https://my-api.example.com

{"message": "Hello from the primary Region!"}
```

## Next steps: Customize and test regularly
<a name="dns-failover-next-steps"></a>

This example demonstrates one way to configure DNS failover. You can use a variety of CloudWatch metrics or HTTP endpoints for the health checks that manage failover. Regularly test your failover mechanisms to make sure that they work as expected, and that operators are familiar with your failover procedures.

# Optimize performance of REST APIs
<a name="rest-api-optimize"></a>

After you've made your API available to be called, you might realize that it needs to be optimized to improve responsiveness. API Gateway provides a few strategies for optimizing your API, like response caching and payload compression. In this section, you can learn how to enable these capabilities.

**Topics**
+ [Cache settings for REST APIs in API Gateway](api-gateway-caching.md)
+ [Payload compression for REST APIs in API Gateway](api-gateway-gzip-compression-decompression.md)

# Cache settings for REST APIs in API Gateway
<a name="api-gateway-caching"></a>

You can enable API caching in API Gateway to cache your endpoint's responses. With caching, you can reduce the number of calls made to your endpoint and also improve the latency of requests to your API.

When you enable caching for a stage, API Gateway caches responses from your endpoint for a specified time-to-live (TTL) period, in seconds. API Gateway then responds to the request by looking up the endpoint response from the cache instead of making a request to your endpoint. The default TTL value for API caching is 300 seconds. The maximum TTL value is 3600 seconds. TTL=0 means caching is disabled.

**Note**  
Caching is best-effort. You can use the `CacheHitCount` and `CacheMissCount` metrics in Amazon CloudWatch to monitor requests that API Gateway serves from the API cache.

The maximum size of a response that can be cached is 1048576 bytes. Cache data encryption may increase the size of the response when it is being cached.

This is a HIPAA Eligible Service. For more information about AWS, U.S. Health Insurance Portability and Accountability Act of 1996 (HIPAA), and using AWS services to process, store, and transmit protected health information (PHI), see [HIPAA Overview](https://aws.amazon.com/compliance/hipaa-compliance/).

**Important**  
When you enable caching for a stage, only `GET` methods have caching enabled by default. This helps to ensure the safety and availability of your API. You can enable caching for other methods by [overriding method settings](#override-api-gateway-stage-cache-for-method-cache).

**Important**  
Caching is charged by the hour based on the cache size that you select. Caching is not eligible for the AWS Free Tier. For more information, see [API Gateway Pricing](https://aws.amazon.com/api-gateway/pricing/).

## Enable Amazon API Gateway caching
<a name="enable-api-gateway-caching"></a>

In API Gateway, you can enable caching for a specific stage.

 When you enable caching, you must choose a cache capacity. In general, a larger capacity gives a better performance, but also costs more. For supported cache sizes, see [cacheClusterSize](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateStage.html#apigw-CreateStage-request-cacheClusterSize) in the *API Gateway API Reference*.

 API Gateway enables caching by creating a dedicated cache instance. This process can take up to 4 minutes. 

API Gateway changes caching capacity by removing the existing cache instance and creating a new one with a modified capacity. All existing cached data is deleted. 

**Note**  
The cache capacity affects the CPU, memory, and network bandwidth of the cache instance. As a result, the cache capacity can affect the performance of your cache.   
API Gateway recommends that you run a 10-minute load test to verify that your cache capacity is appropriate for your workload. Ensure that traffic during the load test mirrors production traffic. For example, include ramp up, constant traffic, and traffic spikes. The load test should include responses that can be served from the cache, as well as unique responses that add items to the cache. Monitor the latency, 4xx, 5xx, cache hit, and cache miss metrics during the load test. Adjust your cache capacity as needed based on these metrics. For more information about load testing, see [How do I select the best API Gateway cache capacity to avoid hitting a rate limit?](https://repost.aws/knowledge-center/api-gateway-cache-capacity).

------
#### [ AWS Management Console ]

 In the API Gateway console, you configure caching on the **Stages** page. You provision the stage cache and specify a default method-level cache setting. If you turn on the default method-level cache, method-level caching is turned on for all `GET` methods on your stage, unless that method has a method override. Any additional `GET` methods that you deploy to your stage will have a method-level cache. To configure method-level caching setting for specific methods of your stage, you can use method overrides. For more information about method overrides, see [Override API Gateway stage-level caching for method-level caching](#override-api-gateway-stage-cache-for-method-cache).

**To configure API caching for a given stage:**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Stages**.

1. In the **Stages** list for the API, choose the stage.

1. In the **Stage details** section, choose **Edit**.

1. Under **Additional settings**, for **Cache settings**, turn on **Provision API cache**.

   This provisions a cache cluster for your stage.

1. To activate caching for your stage, turn on **Default method-level caching**.

   This turns on method-level caching for all `GET` methods on your stage. Any additional `GET` methods that you deploy to this stage will have a method-level cache. 
**Note**  
If you have an existing setting for a method-level cache, changing the default method-level caching setting doesn't affect that existing setting.  
![\[Turn on provision API cache and default method-level caching.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-caching-stage-flow.png)

1. Choose **Save changes**.

------
#### [ AWS CLI ]

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command updates a stage to provision a cache and turns on method-level caching for all `GET` methods on your stage:

```
aws apigateway update-stage \
    --rest-api-id a1b2c3 \
    --stage-name 'prod' \
    --patch-operations file://patch.json
```

The contents of `patch.json` are the following:

```
[
     {
          "op": "replace",
          "path": "/cacheClusterEnabled",
          "value": "true"
     },
     {
          "op": "replace",
          "path": "/cacheClusterSize",
          "value": "0.5"
     },
     {
        "op": "replace",
        "path": "/*/*/caching/enabled",
        "value": "true"
     }
]
```

**Note**  
If you have an existing setting for a method-level cache, changing the default method-level caching setting doesn't affect that existing setting.

------

**Note**  
 Creating or deleting a cache takes about 4 minutes for API Gateway to complete.   
When a cache is created, the **Cache cluster** value changes from `Create in progress` to `Active`. When cache deletion is completed, the **Cache cluster** value changes from `Delete in progress` to `Inactive`.  
When you turn on method-level caching for all methods on your stage, the **Default method-level caching** value changes to `Active`. If you turn off method-level caching for all methods on your stage, the **Default method-level caching** value changes to `Inactive`. If you have an existing setting for a method-level cache, changing the status of the cache doesn't affect that setting. 

When you enable caching within a stage's **Cache settings**, only `GET` methods are cached. To ensure the safety and availability of your API, we recommend that you don't change this setting. However, you can enable caching for other methods by [overriding method settings](#override-api-gateway-stage-cache-for-method-cache).

 If you would like to verify if caching is functioning as expected, you have two general options: 
+  Inspect the CloudWatch metrics of **CacheHitCount** and **CacheMissCount** for your API and stage. 
+  Put a timestamp in the response. 

**Note**  
Don't use the `X-Cache` header from the CloudFront response to determine if your API is being served from your API Gateway cache instance.

## Override API Gateway stage-level caching for method-level caching
<a name="override-api-gateway-stage-cache-for-method-cache"></a>

You can override stage-level cache settings by turning on or turning off caching for a specific method. You can also modify the TTL period or turn encryption on or off for cached responses. 

If you anticipate that a method that you are caching will receive sensitive data in its responses, encrypt your cache data. You might need to do this to comply with various compliance frameworks. For more information, see [Amazon API Gateway controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html) in the *AWS Security Hub User Guide*.

------
#### [ AWS Management Console ]

If you change the default method-level caching setting in the **Stage details**, it doesn't affect the method-level cache settings that have overrides.

If you anticipate that a method that you are caching will receive sensitive data in its responses, in **Cache Settings**, choose **Encrypt cache data**.

**To configure API caching for individual methods using the console:**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose the API.

1. Choose **Stages**.

1. In the **Stages** list for the API, expand the stage and choose a method in the API.

1. In the **Method overrides** section, choose **Edit**.

1. In the **Method settings** section, turn on or off **Enable method cache** or customize any other desired options.
**Note**  
Caching is not active until you provision a cache cluster for your stage.

1. Choose **Save**.

------
#### [ AWS CLI ]

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command turns off the cache only for the `GET /pets` method:

```
aws apigateway update-stage /
    --rest-api-id a1b2c3 /
    --stage-name 'prod' /
    --patch-operations file://patch.json
```

The contents of `patch.json` are the following:

```
[{
        "op": "replace",
        "path": "/~1pets/GET/caching/enabled",
        "value": "false"
}]
```

------

## Use method or integration parameters as cache keys to index cached responses
<a name="enable-api-gateway-cache-keys"></a>

You can use a method or integration parameter as cache keys to index cached responses. This includes custom headers, URL paths, or query strings. You can specify some or all of these parameters as the cache key, but you must specify at least one value. When you have a cache key, API Gateway caches the responses from each key value separately, including when the cache key isn't present.

**Note**  
Cache keys are required when setting up caching on a resource.

 For example, suppose you have a request in the following format: 

```
GET /users?type=... HTTP/1.1
host: example.com
...
```

In this request, `type` can take a value of `admin` or `regular`. If you include the `type` parameter as part of the cache key, the responses from `GET /users?type=admin` are cached separately from those from `GET /users?type=regular`. 

 When a method or integration request takes more than one parameter, you can choose to include some or all of the parameters to create the cache key. For example, you can include only the `type` parameter in the cache key for the following request, made in the listed order within a TTL period: 

```
GET /users?type=admin&department=A HTTP/1.1
host: example.com
...
```

 The response from this request is cached and is used to serve the following request: 

```
GET /users?type=admin&department=B HTTP/1.1
host: example.com
...
```

------
#### [ AWS Management Console ]

To include a method or integration request parameter as part of a cache key in the API Gateway console, select **Caching** after you add the parameter. 

![\[Include method or integration parameters as cache keys to index cached response\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-caching-including-parameter-as-cache-key-new-console.png)


------
#### [ AWS CLI ]

The following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command creates a `GET` method and requires the `type` query string parameter:

```
aws apigateway put-method /
    --rest-api-id a1b2c3 /
    --resource-id aaa111 /
    --http-method GET /
    --authorization-type "NONE" /
    --request-parameters "method.request.querystring.type=true"
```

The following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) command creates an integration for the `GET` method with an HTTP endpoint and specifies that API Gateway caches the `type` method request parameter:

```
aws apigateway put-integration /
    --rest-api-id a1b2c3 /
    --resource-id aaa111 /
    --http-method GET /
    --type HTTP /
    --integration-http-method GET /
    --uri 'https://example.com' /
    --cache-key-parameters "method.request.querystring.type"
```

To specify API Gateway cache an integration request parameter, use `integration.request.location.name` as the cache key parameter.

------

## Flush the API stage cache in API Gateway
<a name="flush-api-caching"></a>

When API caching is enabled, you can flush your API stage's cache to ensure that your API's clients get the most recent responses from your integration endpoints.

------
#### [ AWS Management Console ]

**To flush the API stage cache**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose an API that has a stage with a cache.

1. In the main navigation pane, choose **Stages**, and then choose your stage with a cache.

1. Choose the **Stage actions** menu, and then select **Flush stage cache**.

------
#### [ AWS CLI ]

The following [flush-stage-cache](https://docs.aws.amazon.com/cli/latest/reference/apigateway/flush-stage-cache.html) command flushes the stage cache:

```
aws apigateway flush-stage-cache \
    --rest-api-id a1b2c3 \
    --stage-name prod
```

------

**Note**  
After the cache is flushed, responses are serviced from the integration endpoint until the cache is built up again. During this period, the number of requests sent to the integration endpoint may increase. This may temporarily increase the overall latency of your API. 

## Invalidate an API Gateway cache entry
<a name="invalidate-method-caching"></a>

A client of your API can invalidate an existing cache entry and reload it from the integration endpoint for individual requests. The client must send a request that contains the `Cache-Control: max-age=0` header. The client receives the response directly from the integration endpoint instead of the cache, provided that the client is authorized to do so. This replaces the existing cache entry with the new response, which is fetched from the integration endpoint. 

 To grant permission for a client, attach a policy of the following format to an IAM execution role for the user.

**Note**  
Cross-account cache invalidation is not supported.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:InvalidateCache"
            ],
            "Resource": [
                "arn:aws:execute-api:us-east-1:111111111111:api-id/stage-name/GET/resource-path-specifier"
            ]
        }
    ]
}
```

------

 This policy allows the API Gateway execution service to invalidate the cache for requests on the specified resource (or resources). To specify a group of targeted resources, use a wildcard (\$1) character for `account-id`, `api-id`, and other entries in the ARN value of `Resource`. For more information on how to set permissions for the API Gateway execution service, see [Control access to a REST API with IAM permissions](permissions.md). 

 If you don't impose an `InvalidateCache` policy (or choose the **Require authorization** check box in the console), any client can invalidate the API cache. If most or all of the clients invalidate the API cache, this could significantly increase the latency of your API. 

 When the policy is in place, caching is enabled and authorization is required.

You can specify how API Gateway handles unauthorized requests by choosing from the following options:

**Fail the request with 403 status code**  
API Gateway returns a `403 Unauthorized` response.  
 To set this option using the API, use `FAIL_WITH_403`.

**Ignore cache control header; Add a warning in response header**  
API Gateway processes the request and adds a warning header in the response.  
 To set this option using the API, use `SUCCEED_WITH_RESPONSE_HEADER`. 

**Ignore cache control header**  
API Gateway processes the request and doesn't add a warning header in the response.  
 To set this option using the API, use `SUCCEED_WITHOUT_RESPONSE_HEADER`.

You can set the unauthorized request handling behavior using the API Gateway console or AWS CLI.

------
#### [ AWS Management Console ]

**To specify how unauthorized requests are handled**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose an API that has a stage with a cache.

1. In the main navigation pane, choose **Stages**, and then choose your stage with a cache.

1. For **Stage details**, choose **Edit**.

1. For **Unauthorized request handling**, select an option.

1. Choose **Continue**.

1. Review your changes and choose **Save changes**.

------
#### [ AWS CLI ]

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command updates a stage to handle unauthorized requests by failing the request with 403 status code:

```
aws apigateway update-stage /
    --rest-api-id a1b2c3 /
    --stage-name 'prod' /
    --patch-operations 'op=replace,path=/*/*/caching/unauthorizedCacheControlHeaderStrategy,value="FAIL_WITH_403"'
```

------

## CloudFormation example of a stage with a cache
<a name="cfn-cache-example"></a>

The following CloudFormation template creates an example API, provisions a `0.5` GB cache for the `Prod` stage, and turns on method-level caching for all `GET` methods.

**Important**  
Caching is charged by the hour based on the cache size that you select. Caching is not eligible for the AWS Free Tier. For more information, see [API Gateway Pricing](https://aws.amazon.com/api-gateway/pricing/).

### Example CloudFormation template
<a name="cfn-cache-example-code"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: cache-example
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      ApiKeyRequired: true
      AuthorizationType: NONE
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
  ApiStage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
      StageName: Prod
      Description: Prod Stage with a cache
      RestApiId: !Ref Api
      DeploymentId: !Ref ApiDeployment
      CacheClusterEnabled: True
      CacheClusterSize: 0.5
      MethodSettings:
        - ResourcePath: /*
          HttpMethod: '*'
          CachingEnabled: True
```

# Payload compression for REST APIs in API Gateway
<a name="api-gateway-gzip-compression-decompression"></a>

 API Gateway allows your client to call your API with compressed payloads by using one of the [supported content codings](api-gateway-enable-compression.md#api-gateway-supported-content-encodings). By default, API Gateway supports decompression of the method request payload. However, you must configure your API to enable compression of the method response payload. 

 To enable compression on an [https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html), set the [https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#minimumCompressionSize](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html#minimumCompressionSize) property to a non-negative integer between 0 and 10485760 (10M bytes) when you create the API or after you've created the API. To disable compression on the API, set the `minimumCompressionSize` to null or remove it altogether. You can enable or disable compression for an API by using the API Gateway console, the AWS CLI, or the API Gateway REST API. 

If you want the compression applied on a payload of any size, set the `minimumCompressionSize` value to zero. However, compressing data of a small size might actually increase the final data size. Furthermore, compression in API Gateway and decompression in the client might increase overall latency and require more computing times. You should run test cases against your API to determine an optimal value.

The client can submit an API request with a compressed payload and an appropriate `Content-Encoding` header for API Gateway to decompress and apply applicable mapping templates, before passing the request to the integration endpoint. After the compression is enabled and the API is deployed, the client can receive an API response with a compressed payload if it specifies an appropriate `Accept-Encoding` header in the method request. 

When the integration endpoint expects and returns uncompressed JSON payloads, any mapping template that's configured for an uncompressed JSON payload is applicable to the compressed payload. For a compressed method request payload, API Gateway decompresses the payload, applies the mapping template, and passes the mapped request to the integration endpoint. For an uncompressed integration response payload, API Gateway applies the mapping template, compresses the mapped payload, and returns the compressed payload to the client. 

**Topics**
+ [Enable payload compression for an API in API Gateway](api-gateway-enable-compression.md)
+ [Call an API method with a compressed payload in API Gateway](api-gateway-make-request-with-compressed-payload.md)
+ [Receive an API response with a compressed payload in API Gateway](api-gateway-receive-response-with-compressed-payload.md)

# Enable payload compression for an API in API Gateway
<a name="api-gateway-enable-compression"></a>

You can enable compression for an API using the API Gateway console, the AWS CLI, or an AWS SDK.

For an existing API, you must deploy the API after enabling the compression in order for the change to take effect. For a new API, you can deploy the API after the API setup is complete.

**Note**  
The highest-priority content encoding must be one supported by API Gateway. If it is not, compression is not applied to the response payload.

**Topics**
+ [Enable payload compression for an API using the API Gateway console](#api-gateway-enable-compression-console)
+ [Enable payload compression for an API using the AWS CLI](#api-gateway-enable-compression-cli)
+ [Content codings supported by API Gateway](#api-gateway-supported-content-encodings)

## Enable payload compression for an API using the API Gateway console
<a name="api-gateway-enable-compression-console"></a>

The following procedure describes how to enable payload compression for an API. 

**To enable payload compression by using the API Gateway console**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose an existing API or create a new one.

1. In the main navigation pane, choose **API settings**. 

1. In the **API details** section, choose **Edit**.

1. Turn on **Content encoding** to enable payload compression. For **Minimum body size**, enter a number for the minimum compression size (in bytes). To turn off compression, turn off the **Content encoding** option.

1. Choose **Save changes**.

## Enable payload compression for an API using the AWS CLI
<a name="api-gateway-enable-compression-cli"></a>



The following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command creates an API with payload compression:

```
aws apigateway create-rest-api \
    --name "My test API" \
    --minimum-compression-size 0
```

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command enables payload compression for an existing API:

```
aws apigateway update-rest-api \
    --rest-api-id 1234567890 \
    --patch-operations op=replace,path=/minimumCompressionSize,value=0
```

The `minimumCompressionSize` property has a non-negative integer value between 0 and 10485760 (10M bytes). It measures the compression threshold. If the payload size is smaller than this value, compression or decompression are not applied on the payload. Setting it to zero allows compression for any payload size.

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command turns off payload compression:

```
aws apigateway update-rest-api \
    --rest-api-id 1234567890 \
    --patch-operations op=replace,path=/minimumCompressionSize,value=
```

You can also set `value` to an empty string `""` or omit the `value` property altogether in the preceding call.

## Content codings supported by API Gateway
<a name="api-gateway-supported-content-encodings"></a>

API Gateway supports the following content codings:
+ `deflate`
+ `gzip`
+ `identity`

API Gateway also supports the following `Accept-Encoding` header format, according to the [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.4) specification:
+ `Accept-Encoding:deflate,gzip`
+ `Accept-Encoding:`
+ `Accept-Encoding:*`
+ `Accept-Encoding:deflate;q=0.5,gzip;q=1.0`
+ `Accept-Encoding:gzip;q=1.0,identity;q=0.5,*;q=0`

# Call an API method with a compressed payload in API Gateway
<a name="api-gateway-make-request-with-compressed-payload"></a>

To make an API request with a compressed payload, the client must set the `Content-Encoding` header with one of the [supported content codings](api-gateway-enable-compression.md#api-gateway-supported-content-encodings). 

Suppose that you're an API client and want to call the PetStore API method (`POST /pets`). Don't call the method by using the following JSON output:

```
POST /pets
Host: {petstore-api-id}.execute-api.{region}.amazonaws.com
Content-Length: ...

{
  "type": "dog",
  "price": 249.99
}
```

Instead, you can call the method with the same payload compressed by using the GZIP coding:

```
POST /pets
Host: {petstore-api-id}.execute-api.{region}.amazonaws.com
Content-Encoding:gzip
Content-Length: ...

���RPP*�,HU�RPJ�OW��e&���L,�,-y�j
```

When API Gateway receives the request, it verifies if the specified content coding is supported. Then, it attempts to decompress the payload with the specified content coding. If the decompression is successful, it dispatches the request to the integration endpoint. If the specified coding isn't supported or the supplied payload isn't compressed with specified coding, API Gateway returns the `415 Unsupported Media Type` error response. The error is not logged to CloudWatch Logs, if it occurs in the early phase of decompression before your API and stage are identified. 

# Receive an API response with a compressed payload in API Gateway
<a name="api-gateway-receive-response-with-compressed-payload"></a>

When making a request on a compression-enabled API, the client can choose to receive a compressed response payload of a specific format by specifying an `Accept-Encoding` header with a [supported content coding](api-gateway-enable-compression.md#api-gateway-supported-content-encodings). 

API Gateway only compresses the response payload when the following conditions are satisfied:
+  The incoming request has the `Accept-Encoding` header with a supported content coding and format. 
**Note**  
If the header is not set, the default value is `*` as defined in [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.4). In such a case, API Gateway does not compress the payload. Some browser or client may add `Accept-Encoding` (for example, `Accept-Encoding:gzip, deflate, br`) automatically to compression-enabled requests. This can turn on the payload compression in API Gateway. Without an explicit specification of supported `Accept-Encoding` header values, API Gateway does not compress the payload. 
+  The `minimumCompressionSize` is set on the API to enable compression.
+  The integration response doesn't have a `Content-Encoding` header. 
+  The size of an integration response payload, after the applicable mapping template is applied, is greater than or equal to the specified `minimumCompressionSize` value.

API Gateway applies any mapping template that's configured for the integration response before compressing the payload. If the integration response contains a `Content-Encoding` header, API Gateway assumes that the integration response payload is already compressed and skips the compression processing.

An example is the PetStore API example and the following request:

```
GET /pets
Host: {petstore-api-id}.execute-api.{region}.amazonaws.com
Accept: application/json
```

The backend responds to the request with an uncompressed JSON payload that's similar to the following:

```
200 OK

[
  { 
    "id": 1, 
    "type": "dog", 
    "price": 249.99 
  }, 
  { 
    "id": 2, 
    "type": "cat", 
    "price": 124.99 
  }, 
  { 
    "id": 3, 
    "type": "fish", 
    "price": 0.99 
  } 
]
```

To receive this output as a compressed payload, your API client can submit a request as follows:

```
GET /pets
Host: {petstore-api-id}.execute-api.{region}.amazonaws.com
Accept-Encoding:gzip
```

The client receives the response with a `Content-Encoding` header and GZIP-encoded payload that are similar to the following: 

```
200 OK
Content-Encoding:gzip
...

���RP�

J�)JV
�:P^IeA*������+(�L	�X�YZ�ku0L0B7!9��C#�&����Y��a���^�X
```

When the response payload is compressed, only the compressed data size is billed for data transfer.

# Distribute your REST APIs to clients in API Gateway
<a name="rest-api-distribute"></a>

This section provides details about distributing your API Gateway APIs to your customers. Distributing your API includes generating SDKs for your customers to download and integrate with their client applications, documenting your API so customers know how to call it from their client applications, and making your API available as part of product offerings.



**Topics**
+ [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md)
+ [Documentation for REST APIs in API Gateway](api-gateway-documenting-api.md)
+ [Generate SDKs for REST APIs in API Gateway](how-to-generate-sdk.md)
+ [Sell your API Gateway APIs through AWS Marketplace](sell-api-as-saas-on-aws-marketplace.md)

# Usage plans and API keys for REST APIs in API Gateway
<a name="api-gateway-api-usage-plans"></a>

After you create, test, and deploy your APIs, you can use API Gateway usage plans to make them available as product offerings for your customers. You can configure usage plans and API keys to allow customers to access selected APIs, and begin throttling requests to those APIs based on defined limits and quotas. These can be set at the API, or API method level.

## What are usage plans and API keys?
<a name="api-gateway-api-usage-plans-overview"></a>

A *usage plan* specifies who can access one or more deployed API stages and methods—and optionally sets the target request rate to start throttling requests. The plan uses API keys to identify API clients and who can access the associated API stages for each key. 

*API keys* are alphanumeric string values that you distribute to application developer customers to grant access to your API. You can use API keys together with [Lambda authorizers](apigateway-use-lambda-authorizer.md), [IAM roles](permissions.md), or [Amazon Cognito](apigateway-integrate-with-cognito.md) to control access to your APIs. API Gateway can generate API keys on your behalf, or you can import them from a [CSV file](api-key-file-format.md). You can generate an API key in API Gateway, or import it into API Gateway from an external source. For more information, see [Set up API keys for REST APIs in API Gateway](api-gateway-setup-api-keys.md). 

An API key has a name and a value. (The terms "API key" and "API key value" are often used interchangeably.) The name cannot exceed 1024 characters. The value is an alphanumeric string between 20 and 128 characters, for example, `apikey1234abcdefghij0123456789`.

**Important**  
API key values must be unique. If you try to create two API keys with different names and the same value, API Gateway considers them to be the same API key.  
An API key can be associated with more than one usage plan. A usage plan can be associated with more than one stage. However, a given API key can only be associated with one usage plan for each stage of your API.

A *throttling limit* sets the target point at which request throttling should start. This can be set at the API or API method level.

A *quota limit* sets the target maximum number of requests with a given API key that can be submitted within a specified time interval. You can configure individual API methods to require API key authorization based on usage plan configuration.

Throttling and quota limits apply to requests for individual API keys that are aggregated across all API stages within a usage plan.

**Note**  
Usage plan throttling and quotas are not hard limits, and are applied on a best-effort basis. In some cases, clients can exceed the quotas that you set. Don’t rely on usage plan quotas or throttling to control costs or block access to an API. Consider using [AWS Budgets](https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-managing-costs.html) to monitor costs and [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) to manage API requests.

## Best practices for API keys and usage plans
<a name="apigateway-usage-plans-best-practices"></a>

The following are suggested best practices to follow when using API keys and usage plans.

**Important**  
Don't use API keys for authentication or authorization to control access to your APIs. If you have multiple APIs in a usage plan, a user with a valid API key for one API in that usage plan can access *all* APIs in that usage plan. Instead, to control access to your API, use an IAM role, a [Lambda authorizer](apigateway-use-lambda-authorizer.md), or an [Amazon Cognito user pool](apigateway-integrate-with-cognito.md).
Use API keys that API Gateway generates. API keys shouldn't include confidential information; clients typically transmit them in headers that can be logged.
+ If you're using a developer portal to publish your APIs, note that all your APIs in a given usage plan can be subscribed to by customers, even if you haven't made them visible to your customers.
+ In some cases, clients can exceed the quotas that you set. Don’t rely on usage plans to control costs. Consider using [AWS Budgets](https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-managing-costs.html) to monitor costs and [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) to manage API requests.
+ After you add an API key to a usage plan, the update operation might take a few minutes to complete.

# Choose an API key source in API Gateway
<a name="api-gateway-api-key-source"></a>

When you associate a usage plan with an API and enable API keys on API methods, every incoming request to the API must contain an [API key](api-gateway-basic-concept.md#apigateway-definition-api-key). API Gateway reads the key and compares it against the keys in the usage plan. If there is a match, API Gateway throttles the requests based on the plan's request limit and quota. Otherwise, it throws an `InvalidKeyParameter` exception. As a result, the caller receives a `403 Forbidden` response.

Your API Gateway API can receive API keys from one of two sources:

**`HEADER`**  
You distribute API keys to your customers and require them to pass the API key as the `X-API-Key` header of each incoming request. 

**`AUTHORIZER`**  
You have a Lambda authorizer return the API key as part of the authorization response. For more information on the authorization response, see [Output from an API Gateway Lambda authorizer](api-gateway-lambda-authorizer-output.md).

**Note**  
For best practices to consider, see [Best practices for API keys and usage plans](api-gateway-api-usage-plans.md#apigateway-usage-plans-best-practices).

The following procedure shows how to choose an API key source for an API.

------
#### [ AWS Management Console ]

**To choose an API key source for an API**

1. Sign in to the API Gateway console.

1. Choose an existing API or create a new one.

1. In the main navigation pane, choose **API settings**. 

1. In the **API details** section, choose **Edit**. 

1.  Under **API key source**, select `Header` or `Authorizer` from the dropdown list.

1. Choose **Save changes**.

------
#### [ AWS CLI ]

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command updates an API to set the API key source to `AUTHORIZER`:

```
aws apigateway update-rest-api --rest-api-id 1234123412 --patch-operations op=replace,path=/apiKeySource,value=AUTHORIZER
```

To have the client submit an API key, set the `value` to `HEADER` in the previous command.

------
#### [ REST API ]

To choose an API key source for an API by using the API Gateway REST API, call [https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateRestApi.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateRestApi.html) as follows:

```
PATCH /restapis/fugvjdxtri/ HTTP/1.1
Content-Type: application/json
Host: apigateway.us-east-1.amazonaws.com
X-Amz-Date: 20160603T205348Z
Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160603/us-east-1/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature={sig4_hash}

{
  "patchOperations" : [
    {
        "op" : "replace",
        "path" : "/apiKeySource",
        "value" : "HEADER"
    }
  ]
}
```

To have an authorizer return an API key, set the `value` to `AUTHORIZER` in the previous `patchOperations` input.

------

# API Gateway API key file format
<a name="api-key-file-format"></a>

API Gateway can import API keys from external files of a comma-separated value (CSV) format, and then associate the imported keys with one or more usage plans. The imported file must contain the `Name` and `Key` columns. The column header names aren't case sensitive, and columns can be in any order, as shown in the following example: 

```
Key,name
apikey1234abcdefghij0123456789,MyFirstApiKey
```

A `Key` value must be between 20 and 128 characters. A `Name` value cannot exceed 1024 characters. 

An API key file can also have the `Description`, `Enabled`, or `UsagePlanIds` column, as shown in the following example: 

```
Name,key,description,Enabled,usageplanIds
MyFirstApiKey,apikey1234abcdefghij0123456789,An imported key,TRUE,c7y23b
```

When a key is associated with more than one usage plan, the `UsagePlanIds` value is a comma-separated string of the usage plan IDs, enclosed with a pair of double or single quotes, as shown in the following example:

```
Enabled,Name,key,UsageplanIds
true,MyFirstApiKey,apikey1234abcdefghij0123456789,"c7y23b,glvrsr"
```

Unrecognized columns are permitted, but are ignored. The default value is an empty string or a `true` Boolean value. 

The same API key can be imported multiple times, with the most recent version overwriting the previous one. Two API keys are identical if they have the same `key` value. 

**Note**  
For best practices to consider, see [Best practices for API keys and usage plans](api-gateway-api-usage-plans.md#apigateway-usage-plans-best-practices).

# Set up API keys for REST APIs in API Gateway
<a name="api-gateway-setup-api-keys"></a>

To set up API keys, do the following:
+ Configure API methods to require an API key.
+ Create or import an API key for the API in a Region.

Before setting up API keys, you must have created an API and deployed it to a stage. After you create an API key value, it cannot be changed.

For instructions on how to create and deploy an API by using the API Gateway console, see [Develop REST APIs in API Gateway](rest-api-develop.md) and [Deploy REST APIs in API Gateway](how-to-deploy-api.md), respectively.

After you create an API key, you must associate it with a usage plan. For more information, see [Set up usage plans for REST APIs in API Gateway](api-gateway-create-usage-plans.md).

**Note**  
For best practices to consider, see [Best practices for API keys and usage plans](api-gateway-api-usage-plans.md#apigateway-usage-plans-best-practices).

**Topics**
+ [Require an API key on a method](#api-gateway-usage-plan-configure-apikey-on-method)
+ [Create an API key](#api-gateway-usage-plan-create-apikey)
+ [Import API keys](#api-gateway-usage-pan-import-apikey)

## Require an API key on a method
<a name="api-gateway-usage-plan-configure-apikey-on-method"></a>

The following procedure describes how to configure an API method to require an API key.

------
#### [ AWS Management Console ]

**To configure an API method to require an API key**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the API Gateway main navigation pane, choose **Resources**.

1. Under **Resources**, create a new method or choose an existing one.

1. On the **Method request** tab, under **Method request settings**, choose **Edit**.  
![\[Add an API key to a method\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-gateway-new-console-add-key-to-method.png)

1. Select **API key required**.

1. Choose **Save**.

1. Deploy or redeploy the API for the requirement to take effect.

If the **API key required** option is set to `false` and you don't execute the previous steps, any API key that's associated with an API stage isn't used for the method.

------
#### [ AWS CLI ]

The following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command creates a `PUT` method that requires an API key:

```
aws apigateway put-method \
    --rest-api-id 1234123412 \
    --resource-id a1b2c3 \
    --http-method PUT \
    --authorization-type "NONE" \
    --api-key-required
```

The following [update-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-method.html) command updates an existing method to require an API key:

```
aws apigateway update-method \
    --rest-api-id 1234123412 \
    --resource-id a1b2c3 \
    --http-method PUT \
    --patch-operations op="replace",path="/apiKeyRequired",value="true"
```

------
#### [ REST API ]

To require an API key on a method, do one of the following:
+ Call [https://docs.aws.amazon.com/apigateway/latest/api/API_PutMethod.html](https://docs.aws.amazon.com/apigateway/latest/api/API_PutMethod.html) to create a method. Set `apiKeyRequired` to `true` in the request payload.
+ Call [https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateMethod.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateMethod.html) to set `apiKeyRequired` to `true`.

------

## Create an API key
<a name="api-gateway-usage-plan-create-apikey"></a>

The following procedure shows how to create an API key. If you want to import your API key, skip this step.

------
#### [ AWS Management Console ]

**To create an API key**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the API Gateway main navigation pane, choose **API keys**.

1. Choose **Create API key**.  
![\[Create API keys for usage plans\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-gateway-new-console-usage-plan-keys-choose-create-api-key-from-actions-menu.png)

1. For **Name**, enter a name.

1. (Optional) For **Description**, enter a description.

1. For **API key**, choose **Auto generate** to have API Gateway generate the key value, or choose **Custom** to create your own key value.

1. Choose **Save**.

------
#### [ AWS CLI ]

The following [create-api-key](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-api-key.html) command creates an API key:

```
 aws apigateway create-api-key \
    --name 'Dev API key' \
    --description 'API key for Devs' \
    --enabled
```

------
#### [ REST API ]

Call [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateApiKey.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateApiKey.html) to create an API key.

------

## Import API keys
<a name="api-gateway-usage-pan-import-apikey"></a>

The following procedure describes how to import API keys. If you already created an API key, skip this step.

------
#### [ AWS Management Console ]

**To import API keys**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the main navigation pane, choose **API keys**.

1. Choose the **Actions** dropdown menu, and then choose **Import API keys**. 

1. To load a comma-separated key file, choose **Choose file**. You can also enter the keys in the text editor. For information about the file format, see [API Gateway API key file format](api-key-file-format.md).

1. Choose **Fail on warnings** to stop the import when there's an error, or choose **Ignore warnings** to continue to import valid key entries when there's an warning.

1. Choose **Import** to import your API keys.

------
#### [ AWS CLI ]

The following [import-api-keys](https://docs.aws.amazon.com/cli/latest/reference/apigateway/import-api-keys.html) command imports an API key:

```
aws apigateway import-api-key \
    a--body fileb://keys.csv \
    --format csv
```

------
#### [ REST API ]

Call [https://docs.aws.amazon.com/apigateway/latest/api/API_ImportApiKeys.html](https://docs.aws.amazon.com/apigateway/latest/api/API_ImportApiKeys.html) to import an API key from a file. For the file format, see [API Gateway API key file format](api-key-file-format.md).

------

You cannot change the value of the new API key. After you create your API, you configure a usage plan. For more information, see [Set up usage plans for REST APIs in API Gateway](api-gateway-create-usage-plans.md).

# Set up usage plans for REST APIs in API Gateway
<a name="api-gateway-create-usage-plans"></a>

Before you create a usage plan, make sure that you've set up the your API keys. For more information, see [Set up API keys for REST APIs in API Gateway](api-gateway-setup-api-keys.md).

**Topics**
+ [Migrate your API to default usage plans (if needed)](#api-gateway-usage-plan-migrate-to-default)
+ [Create a usage plan](#api-gateway-usage-plan-create)
+ [Add a stage to a usage plan](#api-gateway-usage-plan-add-stage)
+ [Add an API key to a usage plan](#api-gateway-usage-plan-add-key)

## Migrate your API to default usage plans (if needed)
<a name="api-gateway-usage-plan-migrate-to-default"></a>

If you started to use API Gateway *after* the usage plans feature was rolled out on August 11, 2016, you will automatically have usage plans enabled for you in all supported Regions.

If you started to use API Gateway before that date, you might need to migrate to default usage plans. You'll be prompted with the **Enable Usage Plans** option before using usage plans for the first time in the selected Region. When you enable this option, you have default usage plans created for every unique API stage that's associated with existing API keys. In the default usage plan, no throttle or quota limits are set initially, and the associations between the API keys and API stages are copied to the usage plans. The API behaves the same as before. However, you must use the [https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlan.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlan.html) `apiStages` property to associate specified API stage values (`apiId` and `stage`) with included API keys (via [https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlanKey.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlanKey.html)), instead of using the [ApiKey](https://docs.aws.amazon.com/apigateway/latest/api/API_ApiKey.html) `stageKeys` property.

To check whether you've already migrated to default usage plans, use the [https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-account.html](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-account.html) CLI command. In the command output, the `features` list includes an entry of `"UsagePlans"` when usage plans are enabled.

You can also migrate your APIs to default usage plans by using the AWS CLI as follows:

**To migrate to default usage plans using the AWS CLI**

1. Call this CLI command: [https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-account.html](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-account.html).

1. For the `cli-input-json` parameter, use the following JSON:

   ```
   [
       {
           "op": "add",
           "path": "/features",
           "value": "UsagePlans"
       }
   ]
   ```

## Create a usage plan
<a name="api-gateway-usage-plan-create"></a>

The following procedure describes how to create a usage plan.

------
#### [ AWS Management Console ]

**To create a usage plan**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the API Gateway main navigation pane, choose **Usage plans**, and then choose **Create usage plan**.  
![\[API usage plan entities\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-gateway-new-console-usage-plan-keys-create-setup.png)

1. For **Name**, enter a name.

1.  (Optional) For **Description**, enter a description. 

1. By default, usage plans enable throttling. Enter a **Rate** and a **Burst** for your usage plan. Choose **Throttling** to turn off throttling. 

1. By default, usage plans enable a quota for a time period. For **Requests**, enter the total number of requests that a user can make in the time period of your usage plan. Choose **Quota** to turn off the quota.

1. Choose **Create usage plan**.

------
#### [ AWS CLI ]

The following [create-usage-plan](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-usage-plan.html) command creates a usage plan that resets at the beginning of the month:

```
aws apigateway create-usage-plan \
    --name "New Usage Plan" \
    --description "A new usage plan" \
    --throttle burstLimit=10,rateLimit=5 \
    --quota limit=500,offset=0,period=MONTH
```

------
#### [ REST API ]

Call [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateUsagePlan.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateUsagePlan.html) to create a usage plan.

------

## Add a stage to a usage plan
<a name="api-gateway-usage-plan-add-stage"></a>

The following procedure describes how to add a stage to a usage plan.

------
#### [ AWS Management Console ]

**To add a stage to a usage plan**

1. Select your usage plan.

1.  Under the **Associated stages** tab, choose **Add stage**.  
![\[Add an API stage to a usage plan.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-gateway-new-console-usage-plan-keys-create-add-stage.png)

1.  For **API**, select an API. 

1.  For **Stage**, select a stage. 

1. (Optional) To turn on method-level throttling, do the following:

   1. Choose **Method-level throttling**, and then choose **Add method**.

   1. For **Resource**, select a resource from your API. 

   1. For **Method**, select a method from your API. 

   1.  Enter a **Rate** and a **Burst** for your usage plan. 

1. Choose **Add to usage plan**.

------
#### [ AWS CLI ]

The following [update-usage-plan](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-usage-plan.html) command adds the `Prod` stage of an API to a usage plan:

```
aws apigateway update-usage-plan \
    --usage-plan-id abc123 \
    --patch-operations op="add",path="/apiStages",value="a1b1c2:Prod"
```

------
#### [ REST API ]

Call [https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateUsagePlan.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateUsagePlan.html) to update a usage plan.

------

## Add an API key to a usage plan
<a name="api-gateway-usage-plan-add-key"></a>

The following procedure shows how to add an API key to a usage plan.

------
#### [ AWS Management Console ]

**To add a key to a usage plan**

1. Under the **Associated API keys** tab, choose **Add API key**.   
![\[API usage plan entities\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/api-gateway-new-console-usage-plan-keys-create-add-key.png)

1. 

   1.  To associate an existing key to your usage plan, select **Add existing key**, and then select your existing key from the dropdown menu.

   1. To create a new API key, select **Create and add new key**, and then create a new key. For more information on how to create a new key, see [Create an API key](api-gateway-setup-api-keys.md#api-gateway-usage-plan-create-apikey).

1. Choose **Add API key**.

------
#### [ AWS CLI ]

The following [create-usage-plan-key](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-usage-plan-key.html) command associates an existing API key with a usage plan:

```
aws apigateway create-usage-plan-key \
    --usage-plan-id a1b2c3 \
    --key-type "API_KEY" \
    --key-id aaa111bbb
```

------
#### [ REST API ]

Call [https://docs.aws.amazon.com/apigateway/latest/api/API_CreateUsagePlanKey.html](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateUsagePlanKey.html) to associate an existing API key with a usage plan.

You can also directly associate your APIs keys with a usage plan when you import them. Call [https://docs.aws.amazon.com/apigateway/latest/api/API_ImportApiKeys.html](https://docs.aws.amazon.com/apigateway/latest/api/API_ImportApiKeys.html) to add one or more API keys directly to the specified usage plan. The request payload should contain API key values, the associated usage plan identifier, the Boolean flags to indicate that the keys are enabled for the usage plan, and, possibly, the API key names and descriptions. 

The following example of the `apikey:import` request adds three API keys (as identified by `key`, `name`, and `description`) to one usage plan (as identified by `usageplanIds`): 

```
POST /apikeys?mode=import&format=csv&failonwarnings=fase HTTP/1.1
Host: apigateway.us-east-1.amazonaws.com
Content-Type: text/csv
Authorization: ...

key,name, description, enabled, usageplanIds
abcdef1234ghijklmnop8901234567, importedKey_1, firstone,  tRuE, n371pt 
abcdef1234ghijklmnop0123456789, importedKey_2, secondone, TRUE, n371pt
abcdef1234ghijklmnop9012345678, importedKey_3,          , true, n371pt
```

As a result, three `UsagePlanKey` resources are created and added to the `UsagePlan`.

You can also add API keys to more than one usage plan this way. To do this, change each `usageplanIds` column value to a comma-separated string that contains the selected usage plan identifiers, and is enclosed within a pair of quotes (`"n371pt,m282qs"` or `'n371pt,m282qs'`).

------

**Note**  
An API key can be associated with more than one usage plan. A usage plan can be associated with more than one stage. However, a given API key can only be associated with one usage plan for each stage of your API.

# Maintain a usage plan for REST APIs in API Gateway
<a name="api-gateway-usage-plan-manage-usage"></a>

Maintaining a usage plan involves monitoring the used and remaining quotas over a given time period and, if needed, extending the remaining quotas by a specified amount. The following procedures describe how to monitor quotas.

------
#### [ AWS Management Console ]

**To monitor used and remaining quotas**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the API Gateway main navigation pane, choose **Usage plans**.

1. Select a usage plan.

1. Choose the **Associated API keys** tab to see the number of request remaining for the time period for each key.

1. (Optional) Choose **Export usage data**, and then choose a **From** date and a **To** date. Then choose **JSON** or **CSV** for the exported data format, and then choose **Export**.

   The following example shows an exported file. 

   ```
   {
       "px1KW6...qBazOJH": [
         [
           0,
           5000
         ],
         [
           0,
           5000
         ],
         [
           0,
           10
         ]
       ]
     }
   ```

   The usage data in the example shows the daily usage data for an API client, as identified by the API key (`px1KW6...qBazOJH`), between August 1, 2016 and August 3, 2016. Each daily usage data shows used and remaining quotas. In this example, the subscriber hasn't used any allotted quotas yet, and the API owner or administrator has reduced the remaining quota from 5000 to 10 on the third day.

The following procedures describe how to modify quotas.

**To extend the remaining quotas**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the API Gateway main navigation pane, choose **Usage plans**.

1. Select a usage plan.

1. Choose the **Associated API keys** tab to see the number of request remaining for the time period for each key.

1. Select an API key, and then choose **Grant usage extension**.

1. Enter a number for the **Remaining requests** quota. You can increase the renaming requests or decrease the remaining requests for the time period of your usage plan. 

1. Choose **Update quota**.

------
#### [ AWS CLI ]

The following [update-usage-plan](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-usage-plan.html) examples add, remove, or modify the method-level throttling settings in a usage plan.

**Note**  
Be sure to change `us-east-1` to the appropriate Region value for your API.

To add or replace a rate limit for throttling an individual resource and method:

```
aws apigateway --region us-east-1 update-usage-plan --usage-plan-id planId --patch-operations op="replace",path="/apiStages/apiId:stage/throttle/resourcePath/httpMethod/rateLimit",value="0.1"
```

To add or replace a burst limit for throttling an individual resource and method:

```
aws apigateway --region us-east-1 update-usage-plan --usage-plan-id planId --patch-operations op="replace",path="/apiStages/apiId:stage/throttle/resourcePath/httpMethod/burstLimit",value="1"
```

To remove the method-level throttling settings for an individual resource and method:

```
aws apigateway --region us-east-1 update-usage-plan --usage-plan-id planId --patch-operations op="remove",path="/apiStages/apiId:stage/throttle/resourcePath/httpMethod",value=""
```

To remove all method-level throttling settings for an API:

```
aws apigateway --region us-east-1 update-usage-plan --usage-plan-id planId --patch-operations op="remove",path="/apiStages/apiId:stage/throttle ",value=""
```

Here is an example using the Pet Store sample API:

```
aws apigateway --region us-east-1 update-usage-plan --usage-plan-id planId --patch-operations op="replace",path="/apiStages/apiId:stage/throttle",value='"{\"/pets/GET\":{\"rateLimit\":1.0,\"burstLimit\":1},\"//GET\":{\"rateLimit\":1.0,\"burstLimit\":1}}"'
```

------
#### [ REST API ]

Call [https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateUsagePlan.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateUsagePlan.html) to maintain a usage plan.

------

# Create and configure API keys and usage plans with CloudFormation
<a name="api-key-usage-plan-cfn"></a>

 You can use CloudFormation to require API keys on API methods and create a usage plan for an API. The example CloudFormation template does the following:
+ Creates an API Gateway API with `GET` and `POST` methods.
+ Requires an API key for the `GET` and `POST` methods. This API receives keys from the `X-API-KEY` header of each incoming request. 
+ Creates an API key.
+ Creates a usage plan to specify a monthly quota of 1,000 request each month, a throttling rate limit of 100 request each second, and a throttling burst limit of 200 request each second. 
+ Specifies a method-level throttling rate limit of 50 requests each second and a method-level throttling burst limit of 100 requests per second for the `GET` method.
+ Associates the API stage and API key with the usage plan. 

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
  KeyName:
    Type: String
    Default: MyKeyName
    Description: Name of an API key
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: keys-api
      ApiKeySourceType: HEADER
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      ApiKeyRequired: true
      AuthorizationType: NONE
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  PetsMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: POST
      ApiKeyRequired: true
      AuthorizationType: NONE
      Integration:
        Type: HTTP_PROXY
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
  UsagePlan:
    Type: AWS::ApiGateway::UsagePlan
    DependsOn:
      - ApiDeployment
    Properties:
      Description: Example usage plan with a monthly quota of 1000 calls and method-level throttling for /pets GET 
      ApiStages:
        - ApiId: !Ref Api
          Stage: !Sub '${StageName}'
          Throttle:
            "/pets/GET": 
              RateLimit: 50.0
              BurstLimit: 100
      Quota:
        Limit: 1000
        Period: MONTH
      Throttle:
        RateLimit: 100.0
        BurstLimit: 200
      UsagePlanName: "My Usage Plan"
  ApiKey:
    Type: AWS::ApiGateway::ApiKey
    Properties: 
      Description: API Key
      Name: !Sub '${KeyName}'
      Enabled: True
  UsagePlanKey:
    Type: AWS::ApiGateway::UsagePlanKey
    Properties:
      KeyId: !Ref ApiKey
      KeyType: API_KEY
      UsagePlanId: !Ref UsagePlan
Outputs:
  ApiRootUrl:
    Description: Root Url of the API
    Value: !Sub 'https://${Api}.execute-api.${AWS::Region}.amazonaws.com/${StageName}'
```

# Configure a method to use API keys with an OpenAPI definition
<a name="api-key-usage-plan-oas"></a>

You can use an OpenAPI definition to require API keys on a method.

For each method, create a security requirement object to require an API key to invoke that method. Then, define `api_key` in the security definition. After you create your API, add the new API stage to your usage plan.

The following example creates an API and requires an API key for the `POST` and `GET` methods:

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger" : "2.0",
  "info" : {
    "version" : "2024-03-14T20:20:12Z",
    "title" : "keys-api"
  },
  "basePath" : "/v1",
  "schemes" : [ "https" ],
  "paths" : {
    "/pets" : {
      "get" : {
        "responses" : { },
        "security" : [ {
          "api_key" : [ ]
        } ],
        "x-amazon-apigateway-integration" : {
          "type" : "http_proxy",
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets/",
          "passthroughBehavior" : "when_no_match"
        }
      },
      "post" : {
        "responses" : { },
        "security" : [ {
          "api_key" : [ ]
        } ],
        "x-amazon-apigateway-integration" : {
          "type" : "http_proxy",
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets/",
          "passthroughBehavior" : "when_no_match"
        }
      }
    }
  },
  "securityDefinitions" : {
    "api_key" : {
      "type" : "apiKey",
      "name" : "x-api-key",
      "in" : "header"
    }
  }
}
```

------
#### [ OpenAPI 3.0 ]

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "keys-api",
    "version" : "2024-03-14T20:20:12Z"
  },
  "servers" : [ {
    "url" : "{basePath}",
    "variables" : {
      "basePath" : {
        "default" : "v1"
      }
    }
  } ],
  "paths" : {
    "/pets" : {
      "get" : {
        "security" : [ {
          "api_key" : [ ]
        } ],
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets/",
          "passthroughBehavior" : "when_no_match",
          "type" : "http_proxy"
        }
      },
      "post" : {
        "security" : [ {
          "api_key" : [ ]
        } ],
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets/",
          "passthroughBehavior" : "when_no_match",
          "type" : "http_proxy"
        }
      }
    }
  },
  "components" : {
    "securitySchemes" : {
      "api_key" : {
        "type" : "apiKey",
        "name" : "x-api-key",
        "in" : "header"
      }
    }
  }
}
```

------

# Test usage plans for REST APIs in API Gateway
<a name="api-gateway-usage-plan-test-with-postman"></a>

As an example, let's use the PetStore API, which was created in [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md). Assume that the API is configured to use an API key of `Hiorr45VR...c4GJc`. The following steps describe how to test a usage plan.

**To test your usage plan**
+ Make a `GET` request on the Pets resource (`/pets`), with the `?type=...&page=...` query parameters, of the API (for example, `xbvxlpijch`) in a usage plan:

  ```
  GET /testStage/pets?type=dog&page=1 HTTP/1.1
  x-api-key: Hiorr45VR...c4GJc
  Content-Type: application/x-www-form-urlencoded
  Host: xbvxlpijch.execute-api.ap-southeast-1.amazonaws.com
  X-Amz-Date: 20160803T001845Z
  Authorization: AWS4-HMAC-SHA256 Credential={access_key_ID}/20160803/ap-southeast-1/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date;x-api-key, Signature={sigv4_hash}
  ```
**Note**  
You must submit this request to the `execute-api` component of API Gateway and provide the required API key (for example, `Hiorr45VR...c4GJc`) in the required `x-api-key` header.

  The successful response returns a `200 OK` status code and a payload that contains the requested results from the backend. If you forget to set the `x-api-key` header or set it with an incorrect key, you get a `403 Forbidden` response. However, if you didn't configure the method to require an API key, you will likely get a `200 OK` response whether you set the `x-api-key` header correctly or not, and the throttle and quota limits of the usage plan are bypassed. 

  Occasionally, when an internal error occurs where API Gateway is unable to enforce usage plan throttling limits or quotas for the request, API Gateway serves the request without applying the throttling limits or quotas as specified in the usage plan. But, it logs an error message of `Usage Plan check failed due to an internal error` in CloudWatch. You can ignore such occasional errors. 

# Call a method using an API key
<a name="api-gateway-api-key-call"></a>

Depending on the API key source type you choose, use one of the following procedures to use header-sourced API keys or authorizer-returned API keys in method invocation: 

**To use header-sourced API keys:**

1.  Create an API with desired API methods, and then deploy the API to a stage.

1.  Create a new usage plan or choose an existing one. Add the deployed API stage to the usage plan. Attach an API key to the usage plan or choose an existing API key in the plan. Note the chosen API key value.

1.  Set up API methods to require an API key. 

1.  Redeploy the API to the same stage. If you deploy the API to a new stage, make sure to update the usage plan to attach the new API stage. 

1. Call the API using the API key. The following example curl command invokes the `GET` method on the `getUsers` resource of the `prod` stage of an API using an API key.

   ```
   curl -H "X-API-Key: abcd1234" 'https://b123abcde4.execute-api.us-west-2.amazonaws.com/prod/getUsers' 
   ```

The client can now call the API methods while supplying the `x-api-key` header with the chosen API key as the header value. A call might look like the following:

**To use authorizer-sourced API keys:**

1.  Create an API with desired API methods, and then deploy the API to a stage.

1.  Create a new usage plan or choose an existing one. Add the deployed API stage to the usage plan. Attach an API key to the usage plan or choose an existing API key in the plan. Note the chosen API key value.

1.  Create a token-based Lambda authorizer. Include, `usageIdentifierKey:{api-key}` as a root-level property of the authorization response. For instructions on creating a token-based authorizer, see [Example `TOKEN` authorizer Lambda function](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-token-lambda-function-create).

1.  Set up API methods to require an API key and enable the Lambda authorizer on the methods as well. 

1.  Redeploy the API to the same stage. If you deploy the API to a new stage, make sure to update the usage plan to attach the new API stage. 

The client can now call the API key-required methods without explicitly supplying any API key. The authorizer-returned API key is used automatically.

# Documentation for REST APIs in API Gateway
<a name="api-gateway-documenting-api"></a>

 To help customers understand and use your API, you should document the API. To help you document your API, API Gateway lets you add and update the help content for individual API entities as an integral part of your API development process. API Gateway stores the source content and enables you to archive different versions of the documentation. You can associate a documentation version with an API stage, export a stage-specific documentation snapshot to an external OpenAPI file, and distribute the file as a publication of the documentation. 

To document your API, you can call the [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/api/), use one of the [AWS SDKs](https://aws.amazon.com/developer/tools/), use the [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/apigateway/) for API Gateway, or use the API Gateway console. In addition, you can import or export the documentation parts that are defined in an external OpenAPI file.

To share API documentation with developers, you can use a developer portal. For an example, see [Integrating ReadMe with API Gateway to Keep Your Developer Hub Up to Date](https://aws.amazon.com/blogs/apn/integrating-readme-with-amazon-api-gateway-to-keep-your-developer-hub-up-to-date/) or [How to Streamline API Development on Amazon API Gateway Using SmartBear’s SwaggerHub](https://aws.amazon.com/blogs/apn/how-to-streamline-api-development-on-amazon-api-gateway-using-smartbear-swaggerhub/) on the AWS Partner Network (APN) blog.

**Topics**
+ [Representation of API documentation in API Gateway](api-gateway-documenting-api-content-representation.md)
+ [Document an API using the API Gateway console](api-gateway-documenting-api-quick-start-with-console.md)
+ [Publish API documentation using the API Gateway console](apigateway-documenting-api-with-console.md)
+ [Document an API using the API Gateway REST API](api-gateway-documenting-api-quick-start-with-restapi.md)
+ [Publish API documentation using the API Gateway REST API](api-gateway-documenting-api-quick-start-publishing.md)
+ [Import API documentation](api-gateway-documenting-api-quick-start-import-export.md)
+ [Control access to API documentation in API Gateway](api-gateway-documenting-api-content-provision-and-consumption.md)

# Representation of API documentation in API Gateway
<a name="api-gateway-documenting-api-content-representation"></a>

API Gateway API documentation consists of individual documentation parts associated with specific API entities that include API, resource, method, request, response, message parameters (i.e., path, query, header), as well as authorizers and models. 

In API Gateway, a documentation part is represented by a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource. The API documentation as a whole is represented by the [DocumentationParts](https://docs.aws.amazon.com/apigateway/latest/api/API_GetDocumentationParts.html) collection. 

Documenting an API involves creating `DocumentationPart` instances, adding them to the `DocumentationParts` collection, and maintaining versions of the documentation parts as your API evolves.

**Topics**
+ [Documentation parts](#api-gateway-documenting-api-content-representation-documentation-parts)
+ [Documentation versions](#api-gateway-documenting-api-content-representation-documentation-versions)

## Documentation parts
<a name="api-gateway-documenting-api-content-representation-documentation-parts"></a>

A [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource is a JSON object that stores the documentation content applicable to an individual API entity. This includes any UTF-8 content and all major localization languages for your documentation. Its `properties` field contains the documentation content as a map of key-value pairs. Its `location` property identifies the associated API entity. 

The shape of a content map is determined by you, the API developer. The value of a key-value pair can be a string, number, boolean, object, or array. The shape of the `location` object depends on the targeted entity type. 

The `DocumentationPart` resource supports content inheritance: the documentation content of an API entity is applicable to children of that API entity. For more information about the definition of child entities and content inheritance, see [Inherit Content from an API Entity of More General Specification](#api-gateway-documenting-api-content-inheritance). 

### Location of a documentation part
<a name="api-gateway-documenting-api-content-representation-documentation-parts-target"></a>

The [location](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html#location) property of a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) instance identifies an API entity to which the associated content applies. The API entity can be an API Gateway REST API resource, such as [RestApi](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html), [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html), [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html), [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html), [Authorizer](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html), or [Model](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html). The entity can also be a message parameter, such as a URL path parameter, a query string parameter, a request or response header parameter, a request or response body, or response status code. 

To specify an API entity, set the [type](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html#type) attribute of the `location` object to be one of `API`, `AUTHORIZER`, `MODEL`, `RESOURCE`, `METHOD`, `PATH_PARAMETER`, `QUERY_PARAMETER`, `REQUEST_HEADER`, `REQUEST_BODY`, `RESPONSE`, `RESPONSE_HEADER`, or `RESPONSE_BODY`. 

Depending on the `type` of an API entity, you might specify other `location` attributes, including [method](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html#method), [name](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html#name), [path](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html#path), and [statusCode](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html#statusCode). Not all of these attributes are valid for a given API entity. For example, `type`, `path`, `name`, and `statusCode` are valid attributes of the `RESPONSE` entity; only `type` and `path` are valid location attributes of the `RESOURCE` entity. It is an error to include an invalid field in the `location` of a `DocumentationPart` for a given API entity.

Not all valid `location` fields are required. For example, `type` is both the valid and required `location` field of all API entities. However, `method`, `path`, and `statusCode` are valid but not required attributes for the `RESPONSE` entity. When not explicitly specified, a valid `location` field assumes its default value. The default `path` value is `/`, i.e., the root resource of an API. The default value of `method`, or `statusCode` is `*`, meaning any method, or status code values, respectively.

### Content of a documentation part
<a name="api-gateway-documenting-api-content-representation-documentation-parts-content"></a>

The `properties` value is encoded as a JSON string. The `properties` value contains any information you choose to meet your documentation requirements. For example, the following is a valid content map: 

```
{
  "info": {
    "description": "My first API with Amazon API Gateway."
  },
  "x-custom-info" : "My custom info, recognized by OpenAPI.",
  "my-info" : "My custom info not recognized by OpenAPI."
}
```

Although API Gateway accepts any valid JSON string as the content map, the content attributes are treated as two categories: those that can be recognized by OpenAPI and those that cannot. In the preceding example, `info`, `description`, and `x-custom-info` are recognized by OpenAPI as a standard OpenAPI object, property, or extension. In contrast, `my-info` is not compliant with the OpenAPI specification. API Gateway propagates OpenAPI-compliant content attributes into the API entity definitions from the associated `DocumentationPart` instances. API Gateway does not propagate the non-compliant content attributes into the API entity definitions. 

As another example, here is `DocumentationPart` targeted for a `Resource` entity:

```
{
    "location" : {
        "type" : "RESOURCE",
        "path": "/pets"
    },
    "properties" : {
        "summary" : "The /pets resource represents a collection of pets in PetStore.",
        "description": "... a child resource under the root...",
    }
}
```

Here, both `type` and `path` are valid fields to identify the target of the `RESOURCE` type. For the root resource (`/`), you can omit the `path` field.

```
{
    "location" : {
        "type" : "RESOURCE"
    },
    "properties" : {
        "description" : "The root resource with the default path specification."
    }
}
```

This is the same as the following `DocumentationPart` instance:

```
{
    "location" : {
        "type" : "RESOURCE",
        "path": "/"
    },
    "properties" : {
        "description" : "The root resource with an explicit path specification"
    }
}
```



### Inherit content from an API entity of more general specifications
<a name="api-gateway-documenting-api-content-inheritance"></a>

The default value of an optional `location` field provides a patterned description of an API entity. Using the default value in the `location` object, you can add a general description in the `properties` map to a `DocumentationPart` instance with this type of `location` pattern. API Gateway extracts the applicable OpenAPI documentation attributes from the `DocumentationPart` of the generic API entity and injects them into a specific API entity with the `location` fields matching the general `location` pattern, or matching the exact value, unless the specific entity already has a `DocumentationPart` instance associated with it. This behavior is also known as content inheritance from an API entity of more general specifications. 

Content inheritance does not apply to certain API entity types. See the table below for details.

When an API entity matches more than one `DocumentationPart`'s location pattern, the entity will inherit the documentation part with the location fields of the highest precedence and specificities. The order of precedence is `path` > `statusCode`. For matching with the `path` field, API Gateway chooses the entity with the most specific path value. The following table shows this with a few examples.


| Case | `path` | `statusCode` | `name` | Remarks | 
| --- | --- | --- | --- | --- | 
| 1 | /pets | \$1 | id |  Documentation associated with this location pattern will be inherited by entities matching the location pattern.  | 
| 2 | /pets | 200 | id |  Documentation associated with this location pattern will be inherited by entities matching the location pattern when both Case 1 and Case 2 are matched, because Case 2 is more specific than Case 1.   | 
| 3 | /pets/petId | \$1 | id |  Documentation associated with this location pattern will be inherited by entities matching the location pattern when Cases 1, 2, and 3 are matched, because Case 3 has a higher precedence than Case 2 and is more specific than Case 1.  | 

Here is another example to contrast a more generic `DocumentationPart` instance to a more specific one. The following general error message of `"Invalid request error"` is injected into the OpenAPI definitions of the `400` error responses, unless overridden. 

```
{
    "location" : {
        "type" : "RESPONSE",
        "statusCode": "400"
    },
    "properties" : {
        "description" : "Invalid request error."
    }"
}
```

With the following overwrite, the `400` responses to any methods on the `/pets` resource has a description of `"Invalid petId specified"` instead. 

```
{
    "location" : {
        "type" : "RESPONSE",
        "path": "/pets",
        "statusCode": "400"
    },
    "properties" : "{
        "description" : "Invalid petId specified."
    }"
}
```

### Valid location fields of `DocumentationPart`
<a name="api-gateway-documenting-api-content-representation-target-specification"></a>

The following table shows the valid and required fields as well as applicable default values of a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource that is associated with a given type of API entities.


| API entity | Valid location fields | Required location fields | Default field values | Inheritable content | 
| --- | --- | --- | --- | --- | 
| [API](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html) |  <pre>{<br />    "location": {<br />        "type": "API" <br />    }, <br />    ... <br />}</pre>  | type | N/A | No | 
| [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) |  <pre>{ <br />    "location": { <br />        "type": "RESOURCE", <br />        "path": "resource_path" <br />    }, <br />    ... <br />}</pre>  | type | The default value of path is /.  | No | 
| [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) |  <pre>{ <br />    "location": { <br />        "type": "METHOD", <br />        "path": "resource_path", <br />        "method": "http_verb" <br />    }, <br />    ... <br />}</pre>  | type | The default values of path and method are / and \$1, respectively.  | Yes, matching path by prefix and matching method of any values.  | 
| Query parameter |  <pre>{ <br />    "location": { <br />        "type": "QUERY_PARAMETER", <br />        "path": "resource_path", <br />        "method": "HTTP_verb",<br />        "name": "query_parameter_name" <br />    }, <br />    ... <br />}</pre>  | type | The default values of path and method are / and \$1, respectively.  | Yes, matching path by prefix and matching method by exact values. | 
| Request body |  <pre>{ <br />    "location": { <br />        "type": "REQUEST_BODY", <br />        "path": "resource_path", <br />        "method": "http_verb" <br />    }, <br />    ... <br />}</pre>  | type | The default values of path, and method are /and \$1, respectively.  | Yes, matching path by prefix, and matching method by exact values. | 
| Request header parameter |  <pre>{ <br />    "location": { <br />        "type": "REQUEST_HEADER", <br />        "path": "resource_path", <br />        "method": "HTTP_verb",<br />        "name": "header_name" <br />    }, <br />    ... <br />}</pre>  | type, name | The default values of path and method are / and \$1, respectively.  | Yes, matching path by prefix and matching method by exact values. | 
| Request path parameter |  <pre>{ <br />    "location": { <br />        "type": "PATH_PARAMETER", <br />        "path": "resource/{path_parameter_name}", <br />        "method": "HTTP_verb",<br />        "name": "path_parameter_name" <br />    }, <br />    ... <br />}</pre>  | type, name | The default values of path and method are / and \$1, respectively.  | Yes, matching path by prefix and matching method by exact values. | 
| Response |  <pre>{ <br />    "location": { <br />        "type": "RESPONSE", <br />        "path": "resource_path", <br />        "method": "http_verb", <br />        "statusCode": "status_code" <br />    }, <br />    ... <br />}</pre>  | type | The default values of path, method, and statusCode are /, \$1 and \$1, respectively.  | Yes, matching path by prefix and matching method and statusCode by exact values. | 
| Response header |  <pre>{ <br />    "location": { <br />        "type": "RESPONSE_HEADER", <br />        "path": "resource_path", <br />        "method": "http_verb", <br />        "statusCode": "status_code", <br />        "name": "header_name" <br />    }, <br />    ... <br />}</pre>  | type, name | The default values of path, method and statusCode are /, \$1 and \$1, respectively.  | Yes, matching path by prefix and matching method, and statusCode by exact values. | 
| Response body |  <pre>{ <br />    "location": { <br />        "type": "RESPONSE_BODY", <br />        "path": "resource_path", <br />        "method": "http_verb", <br />        "statusCode": "status_code" <br />    }, <br />    ... <br />}</pre>  | type | The default values of path, method and statusCode are /, \$1 and \$1, respectively.  | Yes, matching path by prefix and matching method, and statusCode by exact values. | 
| [Authorizer](https://docs.aws.amazon.com/apigateway/latest/api/API_Authorizer.html) |  <pre>{ <br />    "location": { <br />        "type": "AUTHORIZER", <br />        "name": "authorizer_name" <br />    }, <br />    ... <br />}</pre>  | type | N/A | No | 
| [Model](https://docs.aws.amazon.com/apigateway/latest/api/API_Model.html) |  <pre>{ <br />    "location": { <br />        "type": "MODEL", <br />        "name": "model_name" <br />    }, <br />    ... <br />}</pre>  | type | N/A | No | 

## Documentation versions
<a name="api-gateway-documenting-api-content-representation-documentation-versions"></a>

A documentation version is a snapshot of the [DocumentationParts](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) collection of an API and is tagged with a version identifier. Publishing the documentation of an API involves creating a documentation version, associating it with an API stage, and exporting that stage-specific version of the API documentation to an external OpenAPI file. In API Gateway, a documentation snapshot is represented as a [DocumentationVersion](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationVersion.html) resource. 

As you update an API, you create new versions of the API. In API Gateway, you maintain all the documentation versions using the [DocumentationVersions](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationVersion.html) collection.

# Document an API using the API Gateway console
<a name="api-gateway-documenting-api-quick-start-with-console"></a>

In this section, we describe how to create and maintain documentation parts of an API using the API Gateway console. 

A prerequisite for creating and editing the documentation of an API is that you must have already created the API. In this section, we use the [PetStore](http://petstore-demo-endpoint.execute-api.com/petstore/pets) API as an example. To create an API using the API Gateway console, follow the instructions in [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md). 

**Topics**
+ [Document the `API` entity](#api-gateway-document-api-add-document-part-for-api-entity-with-console)
+ [Document a `RESOURCE` entity](#api-gateway-document-api-add-document-part-for-resource-entity-with-console)
+ [Document a `METHOD` entity](#api-gateway-document-api-add-document-part-for-method-entity-with-console)
+ [Document a `QUERY_PARAMETER` entity](#api-gateway-document-api-add-document-part-for-request-query-entity-with-console)
+ [Document a `PATH_PARAMETER` entity](#api-gateway-document-api-add-document-part-for-path-parameter-entity-with-console)
+ [Document a `REQUEST_HEADER` entity](#api-gateway-document-api-add-document-part-for-request-header-entity-with-console)
+ [Document a `REQUEST_BODY` entity](#api-gateway-document-api-add-document-part-for-request-body-entity-with-console)
+ [Document a `RESPONSE` entity](#api-gateway-document-api-add-document-part-for-response-with-console)
+ [Document a `RESPONSE_HEADER` entity](#api-gateway-document-api-add-document-part-for-response-header-entity-with-console)
+ [Document a `RESPONSE_BODY` entity](#api-gateway-document-api-add-document-part-for-response-body-entity-with-console)
+ [Document a `MODEL` entity](#api-gateway-document-api-add-document-part-for-model-entity-with-console)
+ [Document an `AUTHORIZER` entity](#api-gateway-document-api-add-document-part-for-authorizer-entity-with-console)

## Document the `API` entity
<a name="api-gateway-document-api-add-document-part-for-api-entity-with-console"></a>

To add a new documentation part for the `API` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **API**.

   If a documentation part was not created for the `API`, you get the documentation part's `properties` map editor. Enter the following `properties` map in the text editor. 

   ```
   {
     "info": {
       "description": "Your first API Gateway API.",
       "contact": {
           "name": "John Doe",
           "email": "john.doe@api.com"
       }
     }
   }
   ```
**Note**  
 You do not need to encode the `properties` map into a JSON string. The API Gateway console stringifies the JSON object for you. 

1. Choose **Create documentation part**.

To add a new documentation part for the `API` entity in the **Resources** pane, do the following:

1. In the main navigation pane, choose **Resources**.

1. Choose the **API actions** menu, and then choose **Update API documentation**.

      
![\[Edit documentation for the API entity in the API Gateway console\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/document-api-entity-using-new-console.png)

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. Select the name of your API, and then on the API card, choose **Edit**.

## Document a `RESOURCE` entity
<a name="api-gateway-document-api-add-document-part-for-resource-entity-with-console"></a>

 To add a new documentation part for a `RESOURCE` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Resource**.

1. For **Path**, enter a path.

1. Enter a description in the text editor, for example:

   ```
   {
       "description": "The PetStore's root resource."
   }
   ```

1. Choose **Create documentation part**. You can create documentation for an unlisted resource.

1.  If required, repeat these steps to add or edit another documentation part.

To add a new documentation part for a `RESOURCE` entity in the **Resources** pane, do the following:

1. In the main navigation pane, choose **Resources**.

1. Choose the resource, and then choose **Update documentation**.

      
![\[Edit documentation for the resource entity in the API Gateway console\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/document-resource-entity-using-new-console.png)

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. Select the resource containing your documentation part, and then choose **Edit**.

## Document a `METHOD` entity
<a name="api-gateway-document-api-add-document-part-for-method-entity-with-console"></a>

 To add a new documentation part for a `METHOD` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Method**.

1. For **Path**, enter a path.

1. For **Method**, select an HTTP verb.

1. Enter a description in the text editor, for example:

   ```
   {
     "tags" : [ "pets" ],
     "summary" : "List all pets"
   }
   ```

1. Choose **Create documentation part**. You can create documentation for an unlisted method.

1.  If required, repeat these steps to add or edit another documentation part.

To add a new documentation part for a `METHOD` entity in the **Resources** pane, do the following:

1. In the main navigation pane, choose **Resources**.

1. Choose the method, and then choose **Update documentation**.

      
![\[Edit documentation for the method entity in the API Gateway console\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/document-method-entity-using-new-console.png)

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the method or select the resource containing the method, and then use the search bar to find and select your documentation part.

1.  Choose **Edit**.

## Document a `QUERY_PARAMETER` entity
<a name="api-gateway-document-api-add-document-part-for-request-query-entity-with-console"></a>

 To add a new documentation part for a `QUERY_PARAMETER` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Query parameter**.

1. For **Path**, enter a path.

1. For **Method**, select an HTTP verb.

1. For **Name**, enter a name.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for an unlisted query parameter.

1.  If required, repeat these steps to add or edit another documentation part.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the query parameter or select the resource containing the query parameter, and then use the search bar to find and select your documentation part.

1. Choose **Edit**.

## Document a `PATH_PARAMETER` entity
<a name="api-gateway-document-api-add-document-part-for-path-parameter-entity-with-console"></a>

 To add a new documentation part for a `PATH_PARAMETER` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Path parameter**.

1. For **Path**, enter a path.

1. For **Method**, select an HTTP verb.

1. For **Name**, enter a name.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for an unlisted path parameter.

1.  If required, repeat these steps to add or edit another documentation part.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the path parameter or select the resource containing the path parameter, and then use the search bar to find and select your documentation part.

1. Choose **Edit**.

## Document a `REQUEST_HEADER` entity
<a name="api-gateway-document-api-add-document-part-for-request-header-entity-with-console"></a>

 To add a new documentation part for a `REQUEST_HEADER` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Request header**.

1. For **Path**, enter a path for the request header.

1. For **Method**, select an HTTP verb.

1. For **Name**, enter a name.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for an unlisted request header.

1.  If required, repeat these steps to add or edit another documentation part.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the request header or select the resource containing the request header, and then use the search bar to find and select your documentation part.

1. Choose **Edit**.

## Document a `REQUEST_BODY` entity
<a name="api-gateway-document-api-add-document-part-for-request-body-entity-with-console"></a>

 To add a new documentation part for a `REQUEST_BODY` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Request body**.

1. For **Path**, enter a path for the request body.

1. For **Method**, select an HTTP verb.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for an unlisted request body.

1.  If required, repeat these steps to add or edit another documentation part.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the request body or select the resource containing the request body, and then use the search bar to find and select your documentation part.

1. Choose **Edit**.

## Document a `RESPONSE` entity
<a name="api-gateway-document-api-add-document-part-for-response-with-console"></a>

 To add a new documentation part for a `RESPONSE` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Response (status code)**.

1. For **Path**, enter a path for the response.

1. For **Method**, select an HTTP verb.

1. For **Status code**, enter an HTTP status code.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for an unlisted response status code.

1.  If required, repeat these steps to add or edit another documentation part.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the response status code or select the resource containing the response status code, and then use the search bar to find and select your documentation part.

1. Choose **Edit**.

## Document a `RESPONSE_HEADER` entity
<a name="api-gateway-document-api-add-document-part-for-response-header-entity-with-console"></a>

 To add a new documentation part for a `RESPONSE_HEADER` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Response header**.

1. For **Path**, enter a path for the response header.

1. For **Method**, select an HTTP verb.

1. For **Status code**, enter an HTTP status code.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for an unlisted response header.

1.  If required, repeat these steps to add or edit another documentation part.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the response header or select the resource containing the response header, and then use the search bar to find and select your documentation part.

1. Choose **Edit**.

## Document a `RESPONSE_BODY` entity
<a name="api-gateway-document-api-add-document-part-for-response-body-entity-with-console"></a>

 To add a new documentation part for a `RESPONSE_BODY` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Response body**.

1. For **Path**, enter a path for the response body.

1. For **Method**, select an HTTP verb.

1. For **Status code**, enter an HTTP status code.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for an unlisted response body.

1.  If required, repeat these steps to add or edit another documentation part.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Resources and methods** tab.

1. You can select the response body or select the resource containing the response body, and then use the search bar to find and select your documentation part.

1. Choose **Edit**.

## Document a `MODEL` entity
<a name="api-gateway-document-api-add-document-part-for-model-entity-with-console"></a>

Documenting a `MODEL` entity involves creating and managing `DocumentPart` instances for the model and each of the model's `properties`'. For example, for the `Error` model that comes with every API by default has the following schema definition,

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "Error Schema",
  "type" : "object",
  "properties" : {
    "message" : { "type" : "string" }
  }
}
```

 and requires two `DocumentationPart` instances, one for the `Model` and the other for its `message` property:

```
{
  "location": {
    "type": "MODEL",
    "name": "Error"
  },
  "properties": {
    "title": "Error Schema",
    "description": "A description of the Error model"
  }
}
```

and

```
{
  "location": {
    "type": "MODEL",
    "name": "Error.message"
  },
  "properties": {
    "description": "An error message."
  }
}
```

When the API is exported, the `DocumentationPart`'s properties will override the values in the original schema.

 To add a new documentation part for a `MODEL` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Model**.

1. For **Name**, enter a name for the model.

1. Enter a description in the text editor.

1. Choose **Create documentation part**. You can create documentation for unlisted models.

1.  If required, repeat these steps to add or edit a documentation part to other models.

To add a new documentation part for a `MODEL` entity in the **Models** pane, do the following:

1. In the main navigation pane, choose **Models**.

1. Choose the model, and then choose **Update documentation**.

      
![\[Edit documentation for the model entity in the API Gateway console\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/document-model-entity-using-new-console.png)

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Models** tab.

1. Use the search bar or select the model, and then choose **Edit**.

## Document an `AUTHORIZER` entity
<a name="api-gateway-document-api-add-document-part-for-authorizer-entity-with-console"></a>

 To add a new documentation part for an `AUTHORIZER` entity, do the following:

1. In the main navigation pane, choose **Documentation**, and then choose **Create documentation part**.

1. For **Documentation type**, select **Authorizer**.

1. For **Name**, enter the name of your authorizer.

1. Enter a description in the text editor. Specify a value for the valid `location` field for the authorizer.

1. Choose **Create documentation part**. You can create documentation for unlisted authorizers.

1.  If required, repeat these steps to add or edit a documentation part to other authorizers.

To edit an existing documentation part, do the following:

1. In the **Documentation** pane, choose the **Authorizers** tab.

1. Use the search bar or select the authorizer, and then choose **Edit**.

# Publish API documentation using the API Gateway console
<a name="apigateway-documenting-api-with-console"></a>

The following procedure describes how to publish a documentation version.

**To publish a documentation version using the API Gateway console**

1. In the main navigation pane, choose **Documentation**.

1. Choose **Publish documentation**.

1. Set up the publication:

   1. For **Stage**, select a stage.

   1. For **Version**, enter a version identifier, e.g., `1.0.0`.

   1. (Optional) For **Description**, enter a description.

1. Choose **Publish**.

You can now proceed to download the published documentation by exporting the documentation to an external OpenAPI file. To learn more, see [Export a REST API from API Gateway](api-gateway-export-api.md).

# Document an API using the API Gateway REST API
<a name="api-gateway-documenting-api-quick-start-with-restapi"></a>

In this section, we describe how to create and maintain documentation parts of an API using the API Gateway REST API.

Before creating and editing the documentation of an API, first create the API. In this section, we use the [PetStore](http://petstore-demo-endpoint.execute-api.com/petstore/pets) API as an example. To create an API using the API Gateway console, follow the instructions in [Tutorial: Create a REST API by importing an example](api-gateway-create-api-from-example.md). 

**Topics**
+ [Document the `API` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-api)
+ [Document a `RESOURCE` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-resource)
+ [Document a `METHOD` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-method)
+ [Document a `QUERY_PARAMETER` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-query-parameter)
+ [Document a `PATH_PARAMETER` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-path-parameter)
+ [Document a `REQUEST_BODY` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-request-body)
+ [Document a `REQUEST_HEADER` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-request-header)
+ [Document a `RESPONSE` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-response)
+ [Document a `RESPONSE_HEADER` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-response-header)
+ [Document an `AUTHORIZER` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-authorizer)
+ [Document a `MODEL` entity](#api-gateway-documenting-api-quick-start-with-restapi-add-content-to-model)
+ [Update documentation parts](#api-gateway-documenting-api-quick-start-with-restapi-update-content)
+ [List documentation parts](#api-gateway-documenting-api-quick-start-with-restapi-list-parts)

## Document the `API` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-api"></a>

To add documentation for an [API](https://docs.aws.amazon.com/apigateway/latest/api/API_RestApi.html), add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource for the API entity:

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret   

{
    "location" : {
         "type" : "API"
    },
    "properties": "{\n\t\"info\": {\n\t\t\"description\" : \"Your first API with Amazon API Gateway.\"\n\t}\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  ...
  "id": "s2e5xf",
  "location": {
    "path": null,
    "method": null,
    "name": null,
    "statusCode": null,
    "type": "API"
  },
  "properties": "{\n\t\"info\": {\n\t\t\"description\" : \"Your first API with Amazon API Gateway.\"\n\t}\n}"
}
```

If the documentation part has already been added, a `409 Conflict` response returns, containing the error message of `Documentation part already exists for the specified location: type 'API'."` In this case, you must call the [documentationpart:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateDocumentationPart.html) operation.

```
PATCH /restapis/4wk1k4onj3/documentation/parts/part_id HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
  "patchOperations" : [ {
    "op" : "replace",
    "path" : "/properties",
    "value" : "{\n\t\"info\": {\n\t\t\"description\" : \"Your first API with Amazon API Gateway.\"\n\t}\n}"
  } ]
}
```

The successful response returns a `200 OK` status code with the payload containing the updated `DocumentationPart` instance in the payload.

## Document a `RESOURCE` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-resource"></a>

To add documentation for the root resource of an API, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the corresponding [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) resource:

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret   

{
    "location" : {
       "type" : "RESOURCE",
    },
    "properties" : "{\n\t\"description\" : \"The PetStore root resource.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example: 

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/p76vqo"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/p76vqo"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/p76vqo"
    }
  },
  "id": "p76vqo",
  "location": {
    "path": "/",
    "method": null,
    "name": null,
    "statusCode": null,
    "type": "RESOURCE"
  },
  "properties": "{\n\t\"description\" : \"The PetStore root resource.\"\n}"
}
```

When the resource path is not specified, the resource is assumed to be the root resource. You can add `"path": "/"` to `properties` to make the specification explicit.

To create documentation for a child resource of an API, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the corresponding [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) resource:

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "RESOURCE",
         "path" : "/pets"
    },
    "properties": "{\n\t\"description\" : \"A child resource under the root of PetStore.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/qcht86"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/qcht86"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/qcht86"
    }
  },
  "id": "qcht86",
  "location": {
    "path": "/pets",
    "method": null,
    "name": null,
    "statusCode": null,
    "type": "RESOURCE"
  },
  "properties": "{\n\t\"description\" : \"A child resource under the root of PetStore.\"\n}"
}
```

To add documentation for a child resource specified by a path parameter, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) resource:

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "RESOURCE",
         "path" : "/pets/{petId}"
    },
    "properties": "{\n\t\"description\" : \"A child resource specified by the petId path parameter.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/k6fpwb"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/k6fpwb"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/k6fpwb"
    }
  },
  "id": "k6fpwb",
  "location": {
    "path": "/pets/{petId}",
    "method": null,
    "name": null,
    "statusCode": null,
    "type": "RESOURCE"
  },
  "properties": "{\n\t\"description\" : \"A child resource specified by the petId path parameter.\"\n}"
}
```

**Note**  
The [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) instance of a `RESOURCE` entity cannot be inherited by any of its child resources.

## Document a `METHOD` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-method"></a>

To add documentation for a method of an API, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the corresponding [Method](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html) resource:

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "METHOD",
         "path" : "/pets",
         "method" : "GET"
    },
    "properties": "{\n\t\"summary\" : \"List all pets.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example: 

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    }
  },
  "id": "o64jbj",
  "location": {
    "path": "/pets",
    "method": "GET",
    "name": null,
    "statusCode": null,
    "type": "METHOD"
  },
  "properties": "{\n\t\"summary\" : \"List all pets.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    }
  },
  "id": "o64jbj",
  "location": {
    "path": "/pets",
    "method": "GET",
    "name": null,
    "statusCode": null,
    "type": "METHOD"
  },
  "properties": "{\n\t\"summary\" : \"List all pets.\"\n}"
}
```

If the `location.method` field is not specified in the preceding request, it is assumed to be `ANY` method that is represented by a wild card `*` character.

To update the documentation content of a `METHOD` entity, call the [documentationpart:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateDocumentationPart.html) operation, supplying a new `properties` map:

```
PATCH /restapis/4wk1k4onj3/documentation/parts/part_id HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
  "patchOperations" : [ {
    "op" : "replace",
    "path" : "/properties",
    "value" : "{\n\t\"tags\" : [ \"pets\" ], \n\t\"summary\" : \"List all pets.\"\n}"
  } ]
}
```

The successful response returns a `200 OK` status code with the payload containing the updated `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/o64jbj"
    }
  },
  "id": "o64jbj",
  "location": {
    "path": "/pets",
    "method": "GET",
    "name": null,
    "statusCode": null,
    "type": "METHOD"
  },
  "properties": "{\n\t\"tags\" : [ \"pets\" ], \n\t\"summary\" : \"List all pets.\"\n}"
}
```

## Document a `QUERY_PARAMETER` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-query-parameter"></a>

To add documentation for a request query parameter, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the `QUERY_PARAMETER` type, with the valid fields of `path` and `name`.

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "QUERY_PARAMETER",
         "path" : "/pets",
         "method" : "GET",
         "name" : "page"
    },
    "properties": "{\n\t\"description\" : \"Page number of results to return.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/h9ht5w"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/h9ht5w"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/h9ht5w"
    }
  },
  "id": "h9ht5w",
  "location": {
    "path": "/pets",
    "method": "GET",
    "name": "page",
    "statusCode": null,
    "type": "QUERY_PARAMETER"
  },
  "properties": "{\n\t\"description\" : \"Page number of results to return.\"\n}"
}
```

The documentation part's `properties` map of a `QUERY_PARAMETER` entity can be inherited by one of its child `QUERY_PARAMETER` entities. For example, if you add a `treats` resource after `/pets/{petId}`, enable the `GET` method on `/pets/{petId}/treats`, and expose the `page` query parameter, this child query parameter inherits the `DocumentationPart`'s `properties` map from the like-named query parameter of the `GET /pets` method, unless you explicitly add a `DocumentationPart` resource to the `page` query parameter of the `GET /pets/{petId}/treats` method.

## Document a `PATH_PARAMETER` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-path-parameter"></a>

To add documentation for a path parameter, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource for the `PATH_PARAMETER` entity.

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "PATH_PARAMETER",
         "path" : "/pets/{petId}",
         "method" : "*",
         "name" : "petId"
    },
    "properties": "{\n\t\"description\" : \"The id of the pet to retrieve.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/ckpgog"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/ckpgog"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/ckpgog"
    }
  },
  "id": "ckpgog",
  "location": {
    "path": "/pets/{petId}",
    "method": "*",
    "name": "petId",
    "statusCode": null,
    "type": "PATH_PARAMETER"
  },
  "properties": "{\n  \"description\" : \"The id of the pet to retrieve\"\n}"
}
```

## Document a `REQUEST_BODY` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-request-body"></a>

To add documentation for a request body, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource for the request body.

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "REQUEST_BODY",
         "path" : "/pets",
         "method" : "POST"
    },
    "properties": "{\n\t\"description\" : \"A Pet object to be added to PetStore.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/kgmfr1"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/kgmfr1"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/kgmfr1"
    }
  },
  "id": "kgmfr1",
  "location": {
    "path": "/pets",
    "method": "POST",
    "name": null,
    "statusCode": null,
    "type": "REQUEST_BODY"
  },
  "properties": "{\n\t\"description\" : \"A Pet object to be added to PetStore.\"\n}"
}
```

## Document a `REQUEST_HEADER` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-request-header"></a>

To add documentation for a request header, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource for the request header.

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "REQUEST_HEADER",
         "path" : "/pets",
         "method" : "GET",
         "name" : "x-my-token"
    },
    "properties": "{\n\t\"description\" : \"A custom token used to authorization the method invocation.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/h0m3uf"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/h0m3uf"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/h0m3uf"
    }
  },
  "id": "h0m3uf",
  "location": {
    "path": "/pets",
    "method": "GET",
    "name": "x-my-token",
    "statusCode": null,
    "type": "REQUEST_HEADER"
  },
  "properties": "{\n\t\"description\" : \"A custom token used to authorization the method invocation.\"\n}"
}
```

## Document a `RESPONSE` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-response"></a>

To add documentation for a response of a status code, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the corresponding [MethodResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_MethodResponse.html) resource.

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location": {
      "path": "/",
      "method": "*",
      "name": null,
      "statusCode": "200",
      "type": "RESPONSE"
    },
    "properties": "{\n  \"description\" : \"Successful operation.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example:

```
{
    "_links": {
        "self": {
            "href": "/restapis/4wk1k4onj3/documentation/parts/lattew"
        },
        "documentationpart:delete": {
            "href": "/restapis/4wk1k4onj3/documentation/parts/lattew"
        },
        "documentationpart:update": {
            "href": "/restapis/4wk1k4onj3/documentation/parts/lattew"
        }
    },
    "id": "lattew",
    "location": {
        "path": "/",
        "method": "*",
        "name": null,
        "statusCode": "200",
        "type": "RESPONSE"
    },
    "properties": "{\n  \"description\" : \"Successful operation.\"\n}"
}
```

## Document a `RESPONSE_HEADER` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-response-header"></a>

To add documentation for a response header, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource for the response header.

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

  "location": {
    "path": "/",
    "method": "GET",
    "name": "Content-Type",
    "statusCode": "200",
    "type": "RESPONSE_HEADER"
  },
  "properties": "{\n  \"description\" : \"Media type of request\"\n}"
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example: 

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/fev7j7"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/fev7j7"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/fev7j7"
    }
  },
  "id": "fev7j7",
  "location": {
    "path": "/",
    "method": "GET",
    "name": "Content-Type",
    "statusCode": "200",
    "type": "RESPONSE_HEADER"
  },
  "properties": "{\n  \"description\" : \"Media type of request\"\n}"
}
```

The documentation of this `Content-Type` response header is the default documentation for the `Content-Type` headers of any responses of the API. 

## Document an `AUTHORIZER` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-authorizer"></a>

To add documentation for an API authorizer, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the specified authorizer.

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "AUTHORIZER",
         "name" : "myAuthorizer"
    },
    "properties": "{\n\t\"description\" : \"Authorizes invocations of configured methods.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example: 

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/pw3qw3"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/pw3qw3"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/pw3qw3"
    }
  },
  "id": "pw3qw3",
  "location": {
    "path": null,
    "method": null,
    "name": "myAuthorizer",
    "statusCode": null,
    "type": "AUTHORIZER"
  },
  "properties": "{\n\t\"description\" : \"Authorizes invocations of configured methods.\"\n}"
}
```

**Note**  
The [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) instance of an `AUTHORIZER` entity cannot be inherited by any of its child resources.

## Document a `MODEL` entity
<a name="api-gateway-documenting-api-quick-start-with-restapi-add-content-to-model"></a>

 Documenting a `MODEL` entity involves creating and managing `DocumentPart` instances for the model and each of the model's `properties`'. For example, for the `Error` model that comes with every API by default has the following schema definition, 

```
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "Error Schema",
  "type" : "object",
  "properties" : {
    "message" : { "type" : "string" }
  }
}
```

 and requires two `DocumentationPart` instances, one for the `Model` and the other for its `message` property: 

```
{
  "location": {
    "type": "MODEL",
    "name": "Error"
  },
  "properties": {
    "title": "Error Schema",
    "description": "A description of the Error model"
  }
}
```

and

```
{
  "location": {
    "type": "MODEL",
    "name": "Error.message"
  },
  "properties": {
    "description": "An error message."
  }
}
```

When the API is exported, the `DocumentationPart`'s properties will override the values in the original schema. 

 To add documentation for an API model, add a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) resource targeted for the specified model. 

```
POST /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "location" : {
         "type" : "MODEL",
         "name" : "Pet"
    },
    "properties": "{\n\t\"description\" : \"Data structure of a Pet object.\"\n}"
}
```

If successful, the operation returns a `201 Created` response containing the newly created `DocumentationPart` instance in the payload. For example: 

```
{
  "_links": {
    "curies": {
      "href": "http://docs.aws.amazon.com/apigateway/latest/developerguide/restapi-documentationpart-{rel}.html",
      "name": "documentationpart",
      "templated": true
    },
    "self": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/lkn4uq"
    },
    "documentationpart:delete": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/lkn4uq"
    },
    "documentationpart:update": {
      "href": "/restapis/4wk1k4onj3/documentation/parts/lkn4uq"
    }
  },
  "id": "lkn4uq",
  "location": {
    "path": null,
    "method": null,
    "name": "Pet",
    "statusCode": null,
    "type": "MODEL"
  },
  "properties": "{\n\t\"description\" : \"Data structure of a Pet object.\"\n}"
}
```

Repeat the same step to create a DocumentationPart instance for any of the model's properties.

**Note**  
The [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) instance of a `MODEL` entity cannot be inherited by any of its child resources.

## Update documentation parts
<a name="api-gateway-documenting-api-quick-start-with-restapi-update-content"></a>

 To update the documentation parts of any type of API entities, submit a PATCH request on a [DocumentationPart](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) instance of a specified part identifier to replace the existing `properties` map with a new one. 

```
PATCH /restapis/4wk1k4onj3/documentation/parts/part_id HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret
                
{
  "patchOperations" : [ {
    "op" : "replace",
    "path" : "RESOURCE_PATH",
    "value" : "NEW_properties_VALUE_AS_JSON_STRING"
  } ]
}
```

The successful response returns a `200 OK` status code with the payload containing the updated `DocumentationPart` instance in the payload.

You can update multiple documentation parts in a single `PATCH` request.

## List documentation parts
<a name="api-gateway-documenting-api-quick-start-with-restapi-list-parts"></a>

 To list the documentation parts of any type of API entities, submit a GET request on a [DocumentationParts](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) collection. 

```
GET /restapis/restapi_id/documentation/parts HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret
```

The successful response returns a `200 OK` status code with the payload containing the available `DocumentationPart` instances in the payload.

# Publish API documentation using the API Gateway REST API
<a name="api-gateway-documenting-api-quick-start-publishing"></a>

To publish the documentation for an API, create, update, or get a documentation snapshot, and then associate the documentation snapshot with an API stage. When creating a documentation snapshot, you can also associate it with an API stage at the same time.

**Topics**
+ [Create a documentation snapshot and associate it with an API stage](#api-gateway-documenting-api-publishing-create-documentation-version-with-stage)
+ [Create a documentation snapshot](#api-gateway-documenting-api-publishing-create-documentation-version)
+ [Update a documentation snapshot](#api-gateway-documenting-api-publishing-update-documentation-version)
+ [Get a documentation snapshot](#api-gateway-documenting-api-publishing-get-documentation-version)
+ [Associate a documentation snapshot with an API stage](#api-gateway-documenting-api-publishing-stage-association)
+ [Download a documentation snapshot associated with a stage](#api-gateway-documenting-api-publishing-export-documentation-version)

## Create a documentation snapshot and associate it with an API stage
<a name="api-gateway-documenting-api-publishing-create-documentation-version-with-stage"></a>

To create a snapshot of an API's documentation parts and associate it with an API stage at the same time, submit the following `POST` request:

```
POST /restapis/restapi_id/documentation/versions HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "documentationVersion" : "1.0.0",
    "stageName": "prod",
    "description" : "My API Documentation v1.0.0"
}
```

If successful, the operation returns a `200 OK` response, containing the newly created `DocumentationVersion` instance as the payload.

Alternatively, you can create a documentation snapshot without associating it with an API stage first and then call [restapi:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateRestApi.html) to associate the snapshot with a specified API stage. You can also update or query an existing documentation snapshot and then update its stage association. We show the steps in the next four sections.

## Create a documentation snapshot
<a name="api-gateway-documenting-api-publishing-create-documentation-version"></a>

To create a snapshot of an API's documentation parts, create a new [DocumentationVersion](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationVersion.html) resource and add it to the [DocumentationVersions](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationVersion.html) collection of the API:

```
POST /restapis/restapi_id/documentation/versions HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "documentationVersion" : "1.0.0",
    "description" : "My API Documentation v1.0.0"
}
```

If successful, the operation returns a `200 OK` response, containing the newly created `DocumentationVersion` instance as the payload.

## Update a documentation snapshot
<a name="api-gateway-documenting-api-publishing-update-documentation-version"></a>

You can only update a documentation snapshot by modifying the `description` property of the corresponding [DocumentationVersion](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationVersion.html) resource. The following example shows how to update the description of the documentation snapshot as identified by its version identifier, `version`, e.g., `1.0.0`.

```
PATCH /restapis/restapi_id/documentation/versions/version HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "patchOperations": [{
        "op": "replace",
        "path": "/description",
        "value": "My API for testing purposes."
    }]
}
```

If successful, the operation returns a `200 OK` response, containing the updated `DocumentationVersion` instance as the payload. 

## Get a documentation snapshot
<a name="api-gateway-documenting-api-publishing-get-documentation-version"></a>

To get a documentation snapshot, submit a `GET` request against the specified [DocumentationVersion](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationVersion.html) resource. The following example shows how to get a documentation snapshot of a given version identifier, 1.0.0.

```
GET /restapis/<restapi_id>/documentation/versions/1.0.0 HTTP/1.1
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret
```

## Associate a documentation snapshot with an API stage
<a name="api-gateway-documenting-api-publishing-stage-association"></a>

To publish the API documentation, associate a documentation snapshot with an API stage. You must have already created an API stage before associating the documentation version with the stage.

To associate a documentation snapshot with an API stage using the [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/api/), call the [stage:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html) operation to set the desired documentation version on the `stage.documentationVersion` property:

```
PATCH /restapis/RESTAPI_ID/stages/STAGE_NAME
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
    "patchOperations": [{
        "op": "replace",
        "path": "/documentationVersion",
        "value": "VERSION_IDENTIFIER"
    }]
}
```

## Download a documentation snapshot associated with a stage
<a name="api-gateway-documenting-api-publishing-export-documentation-version"></a>

After a version of the documentation parts is associated with a stage, you can export the documentation parts together with the API entity definitions, to an external file, using the API Gateway console, the API Gateway REST API, one of its SDKs, or the AWS CLI for API Gateway. The process is the same as for exporting the API. The exported file format can be JSON or YAML. 

Using the API Gateway REST API, you can also explicitly set the `extension=documentation,integrations,authorizers` query parameter to include the API documentation parts, API integrations and authorizers in an API export. By default, documentation parts are included, but integrations and authorizers are excluded, when you export an API. The default output from an API export is suited for distribution of the documentation.

To export the API documentation in an external JSON OpenAPI file using the API Gateway REST API, submit the following `GET` request:

```
GET /restapis/restapi_id/stages/stage_name/exports/swagger?extensions=documentation HTTP/1.1
Accept: application/json
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret
```

Here, the `x-amazon-apigateway-documentation` object contains the documentation parts and the API entity definitions contains the documentation properties supported by OpenAPI. The output does not include details of integration or Lambda authorizers (formerly known as custom authorizers). To include both details, set `extensions=integrations,authorizers,documentation`. To include details of integrations but not of authorizers, set `extensions=integrations,documentation`. 

You must set the `Accept:application/json` header in the request to output the result in a JSON file. To produce the YAML output, change the request header to `Accept:application/yaml`. 

As an example, we will look at an API that exposes a simple `GET` method on the root resource (`/`). This API has four API entities defined in an OpenAPI definition file, one for each of the `API`, `MODEL`, `METHOD`, and `RESPONSE` types. A documentation part has been added to each of the `API`, `METHOD`, and `RESPONSE` entities. Calling the preceding documentation-exporting command, we get the following output, with the documentation parts listed within the `x-amazon-apigateway-documentation` object as an extension to a standard OpenAPI file.

------
#### [ OpenAPI 3.0 ]

```
{
   "openapi": "3.0.0",
   "info": {
      "description": "API info description",
      "version": "2016-11-22T22:39:14Z",
      "title": "doc",
      "x-bar": "API info x-bar"
   },
   "paths": {
      "/": {
         "get": {
            "description": "Method description.",
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               }
            },
            "x-example": "x- Method example"
         },
         "x-bar": "resource x-bar"
      }
   },
   "x-amazon-apigateway-documentation": {
      "version": "1.0.0",
      "createdDate": "2016-11-22T22:41:40Z",
      "documentationParts": [
         {
            "location": {
               "type": "API"
            },
            "properties": {
               "description": "API description",
               "foo": "API foo",
               "x-bar": "API x-bar",
               "info": {
                  "description": "API info description",
                  "version": "API info version",
                  "foo": "API info foo",
                  "x-bar": "API info x-bar"
               }
            }
         },
         {
            "location": {
               "type": "METHOD",
               "method": "GET"
            },
            "properties": {
               "description": "Method description.",
               "x-example": "x- Method example",
               "foo": "Method foo",
               "info": {
                  "version": "method info version",
                  "description": "method info description",
                  "foo": "method info foo"
               }
            }
         },
         {
            "location": {
               "type": "RESOURCE"
            },
            "properties": {
               "description": "resource description",
               "foo": "resource foo",
               "x-bar": "resource x-bar",
               "info": {
                  "description": "resource info description",
                  "version": "resource info version",
                  "foo": "resource info foo",
                  "x-bar": "resource info x-bar"
               }
            }
         }
      ]
   },
   "x-bar": "API x-bar",
   "servers": [
      {
         "url": "https://rznaap68yi.execute-api.ap-southeast-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/test"
            }
         }
      }
   ],
   "components": {
      "schemas": {
         "Empty": {
            "type": "object",
            "title": "Empty Schema"
         }
      }
   }
}
```

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger" : "2.0",
  "info" : {
    "description" : "API info description",
    "version" : "2016-11-22T22:39:14Z",
    "title" : "doc",
    "x-bar" : "API info x-bar"
  },
  "host" : "rznaap68yi.execute-api.ap-southeast-1.amazonaws.com",
  "basePath" : "/test",
  "schemes" : [ "https" ],
  "paths" : {
    "/" : {
      "get" : {
        "description" : "Method description.",
        "produces" : [ "application/json" ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "schema" : {
              "$ref" : "#/definitions/Empty"
            }
          }
        },
        "x-example" : "x- Method example"
      },
      "x-bar" : "resource x-bar"
    }
  },
  "definitions" : {
    "Empty" : {
      "type" : "object",
      "title" : "Empty Schema"
    }
  },
  "x-amazon-apigateway-documentation" : {
    "version" : "1.0.0",
    "createdDate" : "2016-11-22T22:41:40Z",
    "documentationParts" : [ {
      "location" : {
        "type" : "API"
      },
      "properties" : {
        "description" : "API description",
        "foo" : "API foo",
        "x-bar" : "API x-bar",
        "info" : {
          "description" : "API info description",
          "version" : "API info version",
          "foo" : "API info foo",
          "x-bar" : "API info x-bar"
        }
      }
    }, {
      "location" : {
        "type" : "METHOD",
        "method" : "GET"
      },
      "properties" : {
        "description" : "Method description.",
        "x-example" : "x- Method example",
        "foo" : "Method foo",
        "info" : {
          "version" : "method info version",
          "description" : "method info description",
          "foo" : "method info foo"
        }
      }
    }, {
      "location" : {
        "type" : "RESOURCE"
      },
      "properties" : {
        "description" : "resource description",
        "foo" : "resource foo",
        "x-bar" : "resource x-bar",
        "info" : {
          "description" : "resource info description",
          "version" : "resource info version",
          "foo" : "resource info foo",
          "x-bar" : "resource info x-bar"
        }
      }
    } ]
  },
  "x-bar" : "API x-bar"
}
```

------

For an OpenAPI-compliant attribute defined in the `properties` map of a documentation part, API Gateway inserts the attribute into the associated API entity definition. An attribute of `x-something` is a standard OpenAPI extension. This extension gets propagated into the API entity definition. For example, see the `x-example` attribute for the `GET` method. An attribute like `foo` is not part of the OpenAPI specification and is not injected into its associated API entity definitions. 

If a documentation-rendering tool (e.g., [OpenAPI UI](https://swagger.io/tools/swagger-ui/)) parses the API entity definitions to extract documentation attributes, any non OpenAPI-compliant `properties` attributes of a `DocumentationPart`' instance are not available for the tool. However, if a documentation-rendering tool parses the `x-amazon-apigateway-documentation` object to get content, or if the tool calls [restapi:documentation-parts](https://docs.aws.amazon.com/apigateway/latest/api/API_DocumentationPart.html) and [documenationpart:by-id](https://docs.aws.amazon.com/apigateway/latest/api/API_GetDocumentationPart.html) to retrieve documentation parts from API Gateway, all the documentation attributes are available for the tool to display.

To export the documentation with API entity definitions containing integration details to a JSON OpenAPI file, submit the following `GET` request:

 

```
GET /restapis/restapi_id/stages/stage_name/exports/swagger?extensions=integrations,documentation HTTP/1.1
Accept: application/json
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret
```

To export the documentation with API entity definitions containing details of integrations and authorizers to a YAML OpenAPI file, submit the following `GET` request:

 

```
GET /restapis/restapi_id/stages/stage_name/exports/swagger?extensions=integrations,authorizers,documentation HTTP/1.1
Accept: application/yaml
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret
```

To use the API Gateway console to export and download the published documentation of an API, follow the instructions in [Export REST API using the API Gateway console](api-gateway-export-api.md#api-gateway-export-api-from-console). 

# Import API documentation
<a name="api-gateway-documenting-api-quick-start-import-export"></a>

 As with importing API entity definitions, you can import documentation parts from an external OpenAPI file into an API in API Gateway. You specify the to-be-imported documentation parts within the [x-amazon-apigateway-documentation object](api-gateway-swagger-extensions-documentation.md) extension in a valid OpenAPI definition file. Importing documentation does not alter the existing API entity definitions.

You have an option to merge the newly specified documentation parts into existing documentation parts in API Gateway or to overwrite the existing documentation parts. In the `MERGE` mode, a new documentation part defined in the OpenAPI file is added to the `DocumentationParts` collection of the API. If an imported `DocumentationPart` already exists, an imported attribute replaces the existing one if the two are different. Other existing documentation attributes remain unaffected. In the `OVERWRITE` mode, the entire `DocumentationParts` collection is replaced according to the imported OpenAPI definition file.

## Importing documentation parts using the API Gateway REST API
<a name="api-gateway-importing-api-with-swagger-file-using-rest-api"></a>

To import API documentation using the API Gateway REST API, call the [documentationpart:import](https://docs.aws.amazon.com/apigateway/latest/api/API_ImportDocumentationParts.html) operation. The following example shows how to overwrite existing documentation parts of an API with a single `GET / ` method, returning a `200 OK` response when successful.

------
#### [ OpenAPI 3.0 ]

```
PUT /restapis/<restapi_id>/documentation/parts&mode=overwrite&failonwarnings=true
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
   "openapi": "3.0.0",
   "info": {
      "description": "description",
      "version": "1",
      "title": "doc"
   },
   "paths": {
      "/": {
         "get": {
            "description": "Method description.",
            "responses": {
               "200": {
                  "description": "200 response",
                  "content": {
                     "application/json": {
                        "schema": {
                           "$ref": "#/components/schemas/Empty"
                        }
                     }
                  }
               }
            }
         }
      }
   },
   "x-amazon-apigateway-documentation": {
      "version": "1.0.3",
      "documentationParts": [
         {
            "location": {
               "type": "API"
            },
            "properties": {
               "description": "API description",
               "info": {
                  "description": "API info description 4",
                  "version": "API info version 3"
               }
            }
         },
         {
            "location": {
               "type": "METHOD",
               "method": "GET"
            },
            "properties": {
               "description": "Method description."
            }
         },
         {
            "location": {
               "type": "MODEL",
               "name": "Empty"
            },
            "properties": {
               "title": "Empty Schema"
            }
         },
         {
            "location": {
               "type": "RESPONSE",
               "method": "GET",
               "statusCode": "200"
            },
            "properties": {
               "description": "200 response"
            }
         }
      ]
   },
   "servers": [
      {
         "url": "/"
      }
   ],
   "components": {
      "schemas": {
         "Empty": {
            "type": "object",
            "title": "Empty Schema"
         }
      }
   }
}
```

------
#### [ OpenAPI 2.0 ]

```
PUT /restapis/<restapi_id>/documentation/parts&mode=overwrite&failonwarnings=true
Host: apigateway.region.amazonaws.com
Content-Type: application/json
X-Amz-Date: YYYYMMDDTttttttZ
Authorization: AWS4-HMAC-SHA256 Credential=access_key_id/YYYYMMDD/region/apigateway/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date, Signature=sigv4_secret

{
  "swagger": "2.0",
  "info": {
    "description": "description",
    "version": "1",
    "title": "doc"
  },
  "host": "",
  "basePath": "/",
  "schemes": [
    "https"
  ],
  "paths": {
    "/": {
      "get": {
        "description": "Method description.",
        "produces": [
          "application/json"
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Empty"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "Empty": {
      "type": "object",
      "title": "Empty Schema"
    }
  },
  "x-amazon-apigateway-documentation": {
    "version": "1.0.3",
    "documentationParts": [
      {
        "location": {
          "type": "API"
        },
        "properties": {
          "description": "API description",
          "info": {
            "description": "API info description 4",
            "version": "API info version 3"
          }
        }
      },
      {
        "location": {
          "type": "METHOD",
          "method": "GET"
        },
        "properties": {
          "description": "Method description."
        }
      },
      {
        "location": {
          "type": "MODEL",
          "name": "Empty"
        },
        "properties": {
          "title": "Empty Schema"
        }
      },
      {
        "location": {
          "type": "RESPONSE",
          "method": "GET",
          "statusCode": "200"
        },
        "properties": {
          "description": "200 response"
        }
      }
    ]
  }
}
```

------

When successful, this request returns a 200 OK response containing the imported `DocumentationPartId` in the payload.

```
{
  "ids": [
    "kg3mth",
    "796rtf",
    "zhek4p",
    "5ukm9s"
  ]
}
```

In addition, you can also call [restapi:import](https://docs.aws.amazon.com/apigateway/latest/api/API_ImportRestApi.html) or [restapi:put](https://docs.aws.amazon.com/apigateway/latest/api/API_PutRestApi.html), supplying the documentation parts in the `x-amazon-apigateway-documentation` object as part of the input OpenAPI file of the API definition. To exclude the documentation parts from the API import, set `ignore=documentation` in the request query parameters.

## Importing documentation parts using the API Gateway console
<a name="api-gateway-importing-api-with-swagger-file-using-console"></a>

The following instructions describe how to import documentation parts.

**To use the console to import documentation parts of an API from an external file**

1. In the main navigation pane, choose **Documentation**.

1. Choose **Import**.

1. If you have existing documentation, select to either **Overwrite** or **Merge** your new documentation.

1. Choose **Choose file** to load a file from a drive, or enter file contents into the file view. For an example, see the payload of the example request in [Importing documentation parts using the API Gateway REST API](#api-gateway-importing-api-with-swagger-file-using-rest-api).

1. Choose how to handle warnings on import. Select either **Fail on warnings** or **Ignore warnings**. For more information, see [Errors and warnings from importing your API into API Gateway](api-gateway-import-api-errors-warnings.md). 

1. Choose **Import**.

# Control access to API documentation in API Gateway
<a name="api-gateway-documenting-api-content-provision-and-consumption"></a>

If you have a dedicated documentation team to write and edit your API documentation, you can configure separate access permissions for your developers (for API development) and for your writers or editors (for content development). This is especially appropriate when a third-party vendor is involved in creating the documentation for you. 

 To grant your documentation team the access to create, update, and publish your API documentation, you can assign the documentation team an IAM role with the following IAM policy, where *account\$1id* is the AWS account ID of your documentation team. 

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [

    {
      "Sid": "StmtDocPartsAddEditViewDelete",
      "Effect": "Allow",
      "Action": [
        "apigateway:GET",
        "apigateway:PUT",
        "apigateway:POST",
        "apigateway:PATCH",
        "apigateway:DELETE"
      ],
      "Resource": [
        "arn:aws:apigateway:us-east-1:111111111111:/restapis/*/documentation/*"
      ]
    }
  ]
}
```

------

 For information on setting permissions to access API Gateway resources, see [How Amazon API Gateway works with IAM](security_iam_service-with-iam.md). 

# Generate SDKs for REST APIs in API Gateway
<a name="how-to-generate-sdk"></a>

To call your REST API in a platform- or language-specific way, you must generate the platform- or language-specific SDK of the API. You generate your SDK after you create, test, and deploy your API to a stage. Currently, API Gateway supports generating an SDK for an API in Java, JavaScript, Java for Android, Objective-C or Swift for iOS, and Ruby.

This section explains how to generate an SDK of an API Gateway API. It also demonstrates how to use the generated SDK in a Java app, a Java for Android app, Objective-C and Swift for iOS apps, and a JavaScript app. 

To facilitate the discussion, we use this API Gateway [API](simple-calc-lambda-api.md), which exposes this [Simple Calculator](simple-calc-nodejs-lambda-function.md) Lambda function. 

Before proceeding, create or import the API and deploy it at least once in API Gateway. For instructions, see [Deploy REST APIs in API Gateway](how-to-deploy-api.md).

**Topics**
+ [Simple calculator Lambda function](simple-calc-nodejs-lambda-function.md)
+ [Simple calculator API in API Gateway](simple-calc-lambda-api.md)
+ [Simple calculator API OpenAPI definition](simple-calc-lambda-api-swagger-definition.md)
+ [Generate the Java SDK of an API in API Gateway](generate-java-sdk-of-an-api.md)
+ [Generate the Android SDK of an API in API Gateway](generate-android-sdk-of-an-api.md)
+ [Generate the iOS SDK of an API in API Gateway](generate-ios-sdk-of-an-api.md)
+ [Generate the JavaScript SDK of a REST API in API Gateway](generate-javascript-sdk-of-an-api.md)
+ [Generate the Ruby SDK of an API in API Gateway](generate-ruby-sdk-of-an-api.md)
+ [Generate SDKs for an API using AWS CLI commands in API Gateway](how-to-generate-sdk-cli.md)

# Simple calculator Lambda function
<a name="simple-calc-nodejs-lambda-function"></a>

As an illustration, we will use a Node.js Lambda function that performs the binary operations of addition, subtraction, multiplication and division. 

**Topics**
+ [Simple calculator Lambda function input format](#simple-calc-lambda-function-input-format)
+ [Simple calculator Lambda function output format](#simple-calc-lambda-function-output-format)
+ [Simple calculator Lambda function implementation](#simple-calc-lambda-function-implementation)

## Simple calculator Lambda function input format
<a name="simple-calc-lambda-function-input-format"></a>

This function takes an input of the following format:

```
{ "a": "Number", "b": "Number", "op": "string"}
```

where `op` can be any of `(+, -, *, /, add, sub, mul, div)`.

## Simple calculator Lambda function output format
<a name="simple-calc-lambda-function-output-format"></a>

When an operation succeeds, it returns the result of the following format:

```
{ "a": "Number", "b": "Number", "op": "string", "c": "Number"}
```

where `c` holds the result of the calculation.

## Simple calculator Lambda function implementation
<a name="simple-calc-lambda-function-implementation"></a>

The implementation of the Lambda function is as follows:

```
export const handler = async function (event, context) {
  console.log("Received event:", JSON.stringify(event));

  if (
    event.a === undefined ||
    event.b === undefined ||
    event.op === undefined
  ) {
    return "400 Invalid Input";
  }

  const res = {};
  res.a = Number(event.a);
  res.b = Number(event.b);
  res.op = event.op;
  if (isNaN(event.a) || isNaN(event.b)) {
    return "400 Invalid Operand";
  }
  switch (event.op) {
    case "+":
    case "add":
      res.c = res.a + res.b;
      break;
    case "-":
    case "sub":
      res.c = res.a - res.b;
      break;
    case "*":
    case "mul":
      res.c = res.a * res.b;
      break;
    case "/":
    case "div":
      if (res.b == 0) {
        return "400 Divide by Zero";
      } else {
        res.c = res.a / res.b;
      }
      break;
    default:
      return "400 Invalid Operator";
  }

  return res;
};
```

# Simple calculator API in API Gateway
<a name="simple-calc-lambda-api"></a>

Our simple calculator API exposes three methods (GET, POST, GET) to invoke the [Simple calculator Lambda function](simple-calc-nodejs-lambda-function.md). A graphical representation of this API is shown as follows:

![\[Simple calculator API for generated SDK\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/simple-calc-api-console-hierarchy-new-console.png)


These three methods show different ways to supply the input for the backend Lambda function to perform the same operation: 
+ The `GET /?a=...&b=...&op=...` method uses the query parameters to specify the input.
+ The `POST /` method uses a JSON payload of `{"a":"Number", "b":"Number", "op":"string"}` to specify the input.
+ The `GET /{a}/{b}/{op}` method uses the path parameters to specify the input.

If not defined, API Gateway generates the corresponding SDK method name by combining the HTTP method and path parts. The root path part (`/`) is referred to as `Api Root`. For example, the default Java SDK method name for the API method of `GET /?a=...&b=...&op=...` is `getABOp`, the default SDK method name for `POST /` is `postApiRoot`, and the default SDK method name for `GET /{a}/{b}/{op}` is `getABOp`. Individual SDKs may customize the convention. Consult the documentation in the generated SDK source for SDK specific method names. 

You can, and should, override the default SDK method names by specifying the [operationName](https://docs.aws.amazon.com/apigateway/latest/api/API_Method.html#operationName) property on each API method. You can do so when [creating the API method](https://docs.aws.amazon.com/apigateway/latest/api/API_PutMethod.html) or [updating the API method](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateMethod.html) using the API Gateway REST API. In the API Swagger definition, you can set the `operationId` to achieve the same result.

Before showing how to call these methods using an SDK generated by API Gateway for this API, let's recall briefly how to set them up. For detailed instructions, see [Develop REST APIs in API Gateway](rest-api-develop.md). If you're new to API Gateway, see [Choose an AWS Lambda integration tutorial](getting-started-with-lambda-integration.md) first.

## Create models for input and output
<a name="simple-calc-lambda-api-create-models-for-input-and-output"></a>

To specify strongly typed input in the SDK, we create an `Input` model for the API. To describe the response body data type, we create an `Output` model and a `Result` model.

**To create models for the input, output, and result**

1. In the main navigation pane, choose **Models**.

1. Choose **Create model**.

1. For **Name**, enter **input**.

1. For **Content type**, enter **application/json**. 

   If no matching content type is found, request validation is not performed. To use the same model regardless of the content type, enter **\$1default**.

1. For **Model schema**, enter the following model:

   ```
   {
       "$schema" : "$schema": "http://json-schema.org/draft-04/schema#",
       "type":"object",
       "properties":{
           "a":{"type":"number"},
           "b":{"type":"number"},
           "op":{"type":"string"}
       },
       "title":"Input"
   }
   ```

1. Choose **Create model**.

1. Repeat the following steps to create an `Output` model and a `Result` model.

   For the `Output` model, enter the following for the **Model schema**:

   ```
   {
       "$schema": "http://json-schema.org/draft-04/schema#",
       "type": "object",
       "properties": {
           "c": {"type":"number"}
       },
       "title": "Output"
   }
   ```

   For the `Result` model, enter the following for the **Model schema**. Replace the API ID `abc123` with your API ID.

   ```
   {
       "$schema": "http://json-schema.org/draft-04/schema#",
       "type":"object",
       "properties":{
           "input":{
               "$ref":"https://apigateway.amazonaws.com/restapis/abc123/models/Input"
           },
           "output":{
               "$ref":"https://apigateway.amazonaws.com/restapis/abc123/models/Output"
           }
       },
       "title":"Result"
   }
   ```

## Set up GET / method query parameters
<a name="simple-calc-lambda-api-set-up-get-method-query-parameters"></a>

For the `GET /?a=..&b=..&op=..` method, the query parameters are declared in **Method Request**:

**To set up GET / URL query string parameters**

1. In the **Method request** section for the `GET` method on the root (`/`) resource, choose **Edit**.

1. Choose **URL query string parameters** and do the following:

   1. Choose **Add query string**.

   1. For **Name**, enter **a**.

   1. Keep **Required** and **Caching** turned off. 

   1. Keep **Caching** turned off.

   Repeat the same steps and create a query string named **b** and a query string named **op**.

1. Choose **Save**.

## Set up data model for the payload as input to the backend
<a name="simple-calc-lambda-api-set-up-post-method-body-data-type"></a>

For the `POST /` method, we create the `Input` model and add it to the method request to define the shape of input data. 

**To set up the data model for the payload as input to the backend**

1. In the **Method request** section, for the `POST` method on the root (`/`) resource choose **Edit**.

1. Choose **Request body**.

1. Choose **Add model**.

1. For **Content type**, enter **application/json**.

1. For **Model**, select **Input**.

1. Choose **Save**.

With this model, your API customers can call the SDK to specify the input by instantiating an `Input` object. Without this model, your customers would be required to create dictionary object to represent the JSON input to the Lambda function. 

## Set up data model for the result output from the backend
<a name="simple-calc-lambda-api-set-up-all-methods-result-data-type"></a>

For all three methods, we create the `Result` model and add it to the method's `Method Response` to define the shape of output returned by the Lambda function.

**To set up the data model for the result output from the backend**

1. Select the **/\$1a\$1/\$1b\$1/\$1op\$1** resource, and then choose the **GET** method.

1. On the **Method response** tab, under **Response 200**, choose **Edit**.

1. Under **Response body**, choose **Add model**.

1. For **Content type**, enter **application/json**.

1. For **Model**, select **Result**.

1. Choose **Save**.

With this model, your API customers can parse a successful output by reading properties of a `Result` object. Without this model, customers would be required to create dictionary object to represent the JSON output. 

# Simple calculator API OpenAPI definition
<a name="simple-calc-lambda-api-swagger-definition"></a>

The following is the OpenAPI definition of the simple calculator API. You can import it into your account. However, you need to reset the resource-based permissions on the [Lambda function](simple-calc-nodejs-lambda-function.md) after the import. To do so, re-select the Lambda function that you created in your account from the **Integration Request** in the API Gateway console. This will cause the API Gateway console to reset the required permissions. Alternatively, you can use AWS Command Line Interface for Lambda command of [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html).

------
#### [ OpenAPI 2.0 ]

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-09-29T20:27:30Z",
    "title": "SimpleCalc"
  },
  "host": "t6dve4zn25.execute-api.us-west-2.amazonaws.com",
  "basePath": "/demo",
  "schemes": [
    "https"
  ],
  "paths": {
    "/": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "op",
            "in": "query",
            "required": false,
            "type": "string"
          },
          {
            "name": "a",
            "in": "query",
            "required": false,
            "type": "string"
          },
          {
            "name": "b",
            "in": "query",
            "required": false,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "requestTemplates": {
            "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"a\" : $input.params('a'),\n  \"b\" : $input.params('b'),\n  \"op\" : \"$input.params('op')\"\n}"
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_templates",
          "httpMethod": "POST",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "type": "aws"
        }
      },
      "post": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "Input",
            "required": true,
            "schema": {
              "$ref": "#/definitions/Input"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "type": "aws"
        }
      }
    },
    "/{a}": {
      "x-amazon-apigateway-any-method": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "a",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "404": {
            "description": "404 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "requestTemplates": {
            "application/json": "{\"statusCode\": 200}"
          },
          "passthroughBehavior": "when_no_match",
          "responses": {
            "default": {
              "statusCode": "404",
              "responseTemplates": {
                "application/json": "{ \"Message\" : \"Can't $context.httpMethod $context.resourcePath\" }"
              }
            }
          },
          "type": "mock"
        }
      }
    },
    "/{a}/{b}": {
      "x-amazon-apigateway-any-method": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "a",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "b",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "404": {
            "description": "404 response"
          }
        },
        "x-amazon-apigateway-integration": {
          "requestTemplates": {
            "application/json": "{\"statusCode\": 200}"
          },
          "passthroughBehavior": "when_no_match",
          "responses": {
            "default": {
              "statusCode": "404",
              "responseTemplates": {
                "application/json": "{ \"Message\" : \"Can't $context.httpMethod $context.resourcePath\" }"
              }
            }
          },
          "type": "mock"
        }
      }
    },
    "/{a}/{b}/{op}": {
      "get": {
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "a",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "b",
            "in": "path",
            "required": true,
            "type": "string"
          },
          {
            "name": "op",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "schema": {
              "$ref": "#/definitions/Result"
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "requestTemplates": {
            "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"a\" : $input.params('a'),\n  \"b\" : $input.params('b'),\n  \"op\" : \"$input.params('op')\"\n}"
          },
          "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:Calc/invocations",
          "passthroughBehavior": "when_no_templates",
          "httpMethod": "POST",
          "responses": {
            "default": {
              "statusCode": "200",
              "responseTemplates": {
                "application/json": "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "type": "aws"
        }
      }
    }
  },
  "definitions": {
    "Input": {
      "type": "object",
      "properties": {
        "a": {
          "type": "number"
        },
        "b": {
          "type": "number"
        },
        "op": {
          "type": "string"
        }
      },
      "title": "Input"
    },
    "Output": {
      "type": "object",
      "properties": {
        "c": {
          "type": "number"
        }
      },
      "title": "Output"
    },
    "Result": {
      "type": "object",
      "properties": {
        "input": {
          "$ref": "#/definitions/Input"
        },
        "output": {
          "$ref": "#/definitions/Output"
        }
      },
      "title": "Result"
    }
  }
}
```

------
#### [ OpenAPI 3.0 ]

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "SimpleCalc",
    "version" : "2016-09-29T20:27:30Z"
  },
  "servers" : [ {
    "url" : "https://t6dve4zn25.execute-api.us-west-2.amazonaws.com/{basePath}",
    "variables" : {
      "basePath" : {
        "default" : "demo"
      }
    }
  } ],
  "paths" : {
    "/{a}/{b}" : {
      "x-amazon-apigateway-any-method" : {
        "parameters" : [ {
          "name" : "a",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "b",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "404" : {
            "description" : "404 response",
            "content" : { }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "mock",
          "responses" : {
            "default" : {
              "statusCode" : "404",
              "responseTemplates" : {
                "application/json" : "{ \"Message\" : \"Can't $context.httpMethod $context.resourcePath\" }"
              }
            }
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_match"
        }
      }
    },
    "/{a}/{b}/{op}" : {
      "get" : {
        "parameters" : [ {
          "name" : "a",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "b",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "op",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Result"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "aws",
          "httpMethod" : "POST",
          "uri" : "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:111122223333:function:Calc/invocations",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseTemplates" : {
                "application/json" : "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "requestTemplates" : {
            "application/json" : "#set($inputRoot = $input.path('$'))\n{\n  \"a\" : $input.params('a'),\n  \"b\" : $input.params('b'),\n  \"op\" : \"$input.params('op')\"\n}"
          },
          "passthroughBehavior" : "when_no_templates"
        }
      }
    },
    "/" : {
      "get" : {
        "parameters" : [ {
          "name" : "op",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "a",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "b",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Result"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "aws",
          "httpMethod" : "POST",
          "uri" : "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:111122223333:function:Calc/invocations",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseTemplates" : {
                "application/json" : "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "requestTemplates" : {
            "application/json" : "#set($inputRoot = $input.path('$'))\n{\n  \"a\" : $input.params('a'),\n  \"b\" : $input.params('b'),\n  \"op\" : \"$input.params('op')\"\n}"
          },
          "passthroughBehavior" : "when_no_templates"
        }
      },
      "post" : {
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/Input"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "description" : "200 response",
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/Result"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "aws",
          "httpMethod" : "POST",
          "uri" : "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:111122223333:function:Calc/invocations",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseTemplates" : {
                "application/json" : "#set($inputRoot = $input.path('$'))\n{\n  \"input\" : {\n    \"a\" : $inputRoot.a,\n    \"b\" : $inputRoot.b,\n    \"op\" : \"$inputRoot.op\"\n  },\n  \"output\" : {\n    \"c\" : $inputRoot.c\n  }\n}"
              }
            }
          },
          "passthroughBehavior" : "when_no_match"
        }
      }
    },
    "/{a}" : {
      "x-amazon-apigateway-any-method" : {
        "parameters" : [ {
          "name" : "a",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "404" : {
            "description" : "404 response",
            "content" : { }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "mock",
          "responses" : {
            "default" : {
              "statusCode" : "404",
              "responseTemplates" : {
                "application/json" : "{ \"Message\" : \"Can't $context.httpMethod $context.resourcePath\" }"
              }
            }
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_match"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "Input" : {
        "title" : "Input",
        "type" : "object",
        "properties" : {
          "a" : {
            "type" : "number"
          },
          "b" : {
            "type" : "number"
          },
          "op" : {
            "type" : "string"
          }
        }
      },
      "Output" : {
        "title" : "Output",
        "type" : "object",
        "properties" : {
          "c" : {
            "type" : "number"
          }
        }
      },
      "Result" : {
        "title" : "Result",
        "type" : "object",
        "properties" : {
          "input" : {
            "$ref" : "#/components/schemas/Input"
          },
          "output" : {
            "$ref" : "#/components/schemas/Output"
          }
        }
      }
    }
  }
}
```

------

# Generate the Java SDK of an API in API Gateway
<a name="generate-java-sdk-of-an-api"></a>

The following procedure shows how to generate the Java SDK of an API in API Gateway.

**To generate the Java SDK of an API in API Gateway**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **Stages**. 

1. In the **Stages** pane, select the name of the stage.

1. Open the **Stage actions** menu, and then choose **Generate SDK**.

1. For **Platform**, choose the **Java** platform and do the following:

   1.  For **Service Name**, specify the name of your SDK. For example, **SimpleCalcSdk**. This becomes the name of your SDK client class. The name corresponds to the `<name>` tag under `<project>` in the pom.xml file, which is in the SDK's project folder. Do not include hyphens.

   1.  For **Java Package Name**, specify a package name for your SDK. For example, **examples.aws.apig.simpleCalc.sdk**. This package name is used as the namespace of your SDK library. Do not include hyphens.

   1.  For **Java Build System**, enter **maven** or **gradle** to specify the build system.

   1.  For **Java Group Id**, enter a group identifier for your SDK project. For example, enter **my-apig-api-examples**. This identifier corresponds to the `<groupId>` tag under `<project>` in the `pom.xml` file, which is in the SDK's project folder.

   1.  For **Java Artifact Id**, enter an artifact identifier for your SDK project. For example, enter **simple-calc-sdk**. This identifier corresponds to the `<artifactId>` tag under `<project>` in the `pom.xml` file, which is in the SDK's project folder.

   1.  For **Java Artifact Version**, enter a version identifier string. For example, **1.0.0**. This version identifier corresponds to the `<version>` tag under `<project>` in the `pom.xml` file, which is in the SDK's project folder.

   1. For **Source Code License Text**, enter the license text of your source code, if any.

1. Choose **Generate SDK**, and then follow the on-screen directions to download the SDK generated by API Gateway.

Follow the instructions in [Use a Java SDK generated by API Gateway for a REST API](how-to-call-apigateway-generated-java-sdk.md) to use the generated SDK.

 Every time you update an API, you must redeploy the API and regenerate the SDK to have the updates included. 

# Generate the Android SDK of an API in API Gateway
<a name="generate-android-sdk-of-an-api"></a>

The following procedure shows how to generate the Android SDK of an API in API Gateway.

**To generate the Android SDK of an API in API Gateway**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **Stages**. 

1. In the **Stages** pane, select the name of the stage.

1. Open the **Stage actions** menu, and then choose **Generate SDK**.

1. For **Platform**, choose the Android platform and do the following: 

   1.  For **Group ID**, enter the unique identifier for the corresponding project. This is used in the `pom.xml` file (for example, **com.mycompany**).

   1.  For **Invoker package**, enter the namespace for the generated client classes (for example, **com.mycompany.clientsdk**).

   1.  For **Artifact ID**, enter the name of the compiled .jar file without the version. This is used in the `pom.xml` file (for example, **aws-apigateway-api-sdk**).

   1. For **Artifact version**, enter the artifact version number for the generated client. This is used in the `pom.xml` file and should follow a *major*.*minor*.*patch* pattern (for example, **1.0.0**).

1. Choose **Generate SDK**, and then follow the on-screen directions to download the SDK generated by API Gateway.

Follow the instructions in [Use an Android SDK generated by API Gateway for a REST API](how-to-generate-sdk-android.md) to use the generated SDK. 

 Every time you update an API, you must redeploy the API and regenerate the SDK to have the updates included. 

# Generate the iOS SDK of an API in API Gateway
<a name="generate-ios-sdk-of-an-api"></a>

The following procedure shows how to generate the iOS SDK of an API in API Gateway.

**To generate the iOS SDK of an API in API Gateway**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **Stages**. 

1. In the **Stages** pane, select the name of the stage.

1. Open the **Stage actions** menu, and then choose **Generate SDK**.

1. For **Platform**, choose the **iOS (Objective-C) or iOS (Swift)** platform and do the following: 

   1. Type a unique prefix in the **Prefix** box.

     The effect of prefix is as follows: if you assign, for example, **SIMPLE\$1CALC** as the prefix for the SDK of the [SimpleCalc](simple-calc-lambda-api.md) API with `input`, `output`, and `result` models, the generated SDK will contain the `SIMPLE_CALCSimpleCalcClient` class that encapsulates the API, including the method requests/responses. In addition, the generated SDK will contain the `SIMPLE_CALCinput`, `SIMPLE_CALCoutput`, and `SIMPLE_CALCresult` classes to represent the input, output, and results, respectively, to represent the request input and response output. For more information, see [Use iOS SDK generated by API Gateway for a REST API in Objective-C or Swift](how-to-generate-sdk-ios.md). 

1. Choose **Generate SDK**, and then follow the on-screen directions to download the SDK generated by API Gateway.

Follow the instructions in [Use iOS SDK generated by API Gateway for a REST API in Objective-C or Swift](how-to-generate-sdk-ios.md) to use the generated SDK.

 Every time you update an API, you must redeploy the API and regenerate the SDK to have the updates included. 

# Generate the JavaScript SDK of a REST API in API Gateway
<a name="generate-javascript-sdk-of-an-api"></a>

The following procedure shows how to generate the JaveScript SDK of an API in API Gateway.

**To generate the JavaScript SDK of an API in API Gateway**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **Stages**. 

1. In the **Stages** pane, select the name of the stage.

1. Open the **Stage actions** menu, and then choose **Generate SDK**.

1. For **Platform**, choose the **JavaScript** platform. 

1. Choose **Generate SDK**, and then follow the on-screen directions to download the SDK generated by API Gateway.

Follow the instructions in [Use a JavaScript SDK generated by API Gateway for a REST API](how-to-generate-sdk-javascript.md) to use the generated SDK.

 Every time you update an API, you must redeploy the API and regenerate the SDK to have the updates included. 

# Generate the Ruby SDK of an API in API Gateway
<a name="generate-ruby-sdk-of-an-api"></a>

The following procedure shows how to generate the Ruby SDK of an API in API Gateway.

**To generate the Ruby SDK of an API in API Gateway**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. Choose **Stages**. 

1. In the **Stages** pane, select the name of the stage.

1. Open the **Stage actions** menu, and then choose **Generate SDK**.

1. For **Platform**, choose the **Ruby** platform and do the following: 

   1.  For **Service Name**, specify the name of your SDK. For example, **SimpleCalc**. This is used to generate the Ruby Gem namespace of your API. The name must be all letters, (`a-zA-Z`), without any other special characters or numbers.

   1.  For **Ruby Gem Name**, specify the name of the Ruby Gem to contain the generated SDK source code for your API. By default, it is the lower-cased service name plus the `-sdk` suffix—for example, **simplecalc-sdk**.

   1.  For **Ruby Gem Version**, specify a version number for the generated Ruby Gem. By default, it is set to `1.0.0`.

1. Choose **Generate SDK**, and then follow the on-screen directions to download the SDK generated by API Gateway.

Follow the instructions in [Use a Ruby SDK generated by API Gateway for a REST API](how-to-call-sdk-ruby.md) to use the generated SDK.

 Every time you update an API, you must redeploy the API and regenerate the SDK to have the updates included. 

# Generate SDKs for an API using AWS CLI commands in API Gateway
<a name="how-to-generate-sdk-cli"></a>

You can use AWS CLI to generate and download an SDK of an API for a supported platform by calling the [get-sdk](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-sdk.html) command. We demonstrate this for some of the supported platforms in the following.

**Topics**
+ [Generate and download the Java for Android SDK using the AWS CLI](#how-to-generate-sdk-cli-android)
+ [Generate and download the JavaScript SDK using the AWS CLI](#how-to-generate-sdk-cli-js)
+ [Generate and download the Ruby SDK using the AWS CLI](#how-to-generate-sdk-cli-ruby)

## Generate and download the Java for Android SDK using the AWS CLI
<a name="how-to-generate-sdk-cli-android"></a>

To generate and download a Java for Android SDK generated by API Gateway of an API (`udpuvvzbkc`) at a given stage (`test`), call the command as follows:

```
aws apigateway get-sdk \
            --rest-api-id udpuvvzbkc \
            --stage-name test \
            --sdk-type android \
            --parameters groupId='com.mycompany',\
                invokerPackage='com.mycompany.myApiSdk',\ 
                artifactId='myApiSdk',\
                artifactVersion='0.0.1' \
            ~/apps/myApi/myApi-android-sdk.zip
```

The last input of `~/apps/myApi/myApi-android-sdk.zip` is the path to the downloaded SDK file named `myApi-android-sdk.zip`.

## Generate and download the JavaScript SDK using the AWS CLI
<a name="how-to-generate-sdk-cli-js"></a>

To generate and download a JavaScript SDK generated by API Gateway of an API (`udpuvvzbkc`) at a given stage (`test`), call the command as follows:

```
aws apigateway get-sdk \
            --rest-api-id udpuvvzbkc \
            --stage-name test \
            --sdk-type javascript \
            ~/apps/myApi/myApi-js-sdk.zip
```

The last input of `~/apps/myApi/myApi-js-sdk.zip` is the path to the downloaded SDK file named `myApi-js-sdk.zip`.

## Generate and download the Ruby SDK using the AWS CLI
<a name="how-to-generate-sdk-cli-ruby"></a>

To generate and download a Ruby SDK of an API (`udpuvvzbkc`) at a given stage (`test`), call the command as follows:

```
aws apigateway get-sdk \
            --rest-api-id udpuvvzbkc \
            --stage-name test  \
            --sdk-type ruby \
            --parameters service.name=myApiRubySdk,ruby.gem-name=myApi,ruby.gem-version=0.01 \
            ~/apps/myApi/myApi-ruby-sdk.zip
```

The last input of `~/apps/myApi/myApi-ruby-sdk.zip` is the path to the downloaded SDK file named `myApi-ruby-sdk.zip`.

 Next, we show how to use the generated SDK to call the underlying API. For more information, see [Invoke REST APIs in API Gateway](how-to-call-api.md). 

# Sell your API Gateway APIs through AWS Marketplace
<a name="sell-api-as-saas-on-aws-marketplace"></a>

After you build, test, and deploy your APIs, you can package them in an API Gateway [usage plan](api-gateway-api-usage-plans.md) and sell the plan as a Software as a Service (SaaS) product through AWS Marketplace. API buyers subscribing to your product offering are billed by AWS Marketplace based on the number of requests made to the usage plan.

To sell your APIs on AWS Marketplace, you must set up the sales channel to integrate AWS Marketplace with API Gateway. Generally speaking, this involves listing your product on AWS Marketplace, setting up an IAM role with appropriate policies to allow API Gateway to send usage metrics to AWS Marketplace, associating an AWS Marketplace product with an API Gateway usage plan, and associating an AWS Marketplace buyer with an API Gateway API key. Details are discussed in the following sections.

For more information about selling your API as a SaaS product on AWS Marketplace, see the [AWS Marketplace User Guide](https://docs.aws.amazon.com/marketplace/latest/userguide/).

**Topics**
+ [Initialize AWS Marketplace integration with API Gateway](#sell-api-as-saas-on-aws-marketplace-initial-setup)
+ [Handle customer subscription to usage plans](#sell-api-as-saas-on-aws-marketplace-subscription-unsubscription)

## Initialize AWS Marketplace integration with API Gateway
<a name="sell-api-as-saas-on-aws-marketplace-initial-setup"></a>

The following tasks are for one-time initialization of AWS Marketplace integration with API Gateway, which enables you to sell your APIs as a SaaS product.

### List a product on AWS Marketplace
<a name="sell-api-as-saas-on-aws-marketplace-inital-setup-list-product"></a>

To list your usage plan as a SaaS product, submit a product load form through [AWS Marketplace](https://aws.amazon.com/marketplace/partners/management-tour). The product must contain a dimension named `apigateway` of the `requests` type. This dimension defines the price-per-request and is used by API Gateway to meter requests to your APIs.

### Create the metering role
<a name="sell-api-as-saas-on-aws-marketplace-inital-setup-create-metering-role"></a>

Create an IAM role named `ApiGatewayMarketplaceMeteringRole` with the following execution policy and trust policy. This role allows API Gateway to send usage metrics to AWS Marketplace on your behalf.

#### Execution policy of the metering role
<a name="sell-api-as-saas-on-aws-marketplace-inital-setup-create-metering-role-execution-policy"></a>

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Action": [
        "aws-marketplace:BatchMeterUsage",
        "aws-marketplace:ResolveCustomer"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
```

------

#### Trusted relationship policy of the metering role
<a name="sell-api-as-saas-on-aws-marketplace-inital-setup-create-metering-role-trusted-policy"></a>

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

### Associate usage plan with AWS Marketplace product
<a name="sell-api-as-saas-on-aws-marketplace-associate-usage-plan-with-saas-product"></a>

When you list a product on AWS Marketplace, you receive an AWS Marketplace product code. To integrate API Gateway with AWS Marketplace, associate your usage plan with the AWS Marketplace product code. You enable the association by setting the API Gateway `UsagePlan`'s [https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlan.html#productCode](https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlan.html#productCode) field to your AWS Marketplace product code, using the API Gateway console, the API Gateway REST API, the AWS CLI for API Gateway, or AWS SDK for API Gateway. The following code example uses the API Gateway REST API:

```
PATCH /usageplans/USAGE_PLAN_ID
Host: apigateway.region.amazonaws.com
Authorization: ...

{
    "patchOperations" : [{
        "path" : "/productCode",
        "value" : "MARKETPLACE_PRODUCT_CODE",
        "op" : "replace"
    }]
}
```

## Handle customer subscription to usage plans
<a name="sell-api-as-saas-on-aws-marketplace-subscription-unsubscription"></a>

The following tasks are handled by your developer portal application.

When a customer subscribes to your product through AWS Marketplace, AWS Marketplace forwards a `POST` request to the SaaS subscriptions URL that you registered when listing your product on AWS Marketplace. The `POST` request comes with an `x-amzn-marketplace-token` parameter containing buyer information. Follow the instructions in [SaaS customer onboarding](https://docs.aws.amazon.com/marketplace/latest/userguide/saas-product-customer-setup.html#in-your-application) to handle this redirect in your developer portal application.

Responding to a customer's subscribing request, AWS Marketplace sends a `subscribe-success` notification to an Amazon SNS topic that you can subscribe to. (See [SaaS customer onboarding](https://docs.aws.amazon.com/marketplace/latest/userguide/saas-product-customer-setup.html#in-your-application)). To accept the customer subscription request, you handle the `subscribe-success` notification by creating or retrieving an API Gateway API key for the customer, associating the customer's AWS Marketplace-provisioned `customerId` with the API keys, and then adding the API key to your usage plan.

When the customer's subscription request completes, the developer portal application should present the customer with the associated API key and inform the customer that the API key must be included in the `x-api-key` header in requests to the APIs.

When a customer cancels a subscription to a usage plan, AWS Marketplace sends an `unsubscribe-success` notification to the SNS topic. To complete the process of unsubscribing the customer, you handle the `unsubscribe-success` notification by removing the customer's API keys from the usage plan.

### Authorize a customer to access a usage plan
<a name="sell-api-as-saas-on-aws-marketplace-subscription-unsubscription-authorize-access-to-usage-plan"></a>

To authorize access to your usage plan for a given customer, use the API Gateway API to fetch or create an API key for the customer and add the API key to the usage plan. 

The following example shows how to call the API Gateway REST API to create a new API key with a specific AWS Marketplace `customerId` value (*MARKETPLACE\$1CUSTOMER\$1ID*).

```
POST apikeys HTTP/1.1
Host: apigateway.region.amazonaws.com
Authorization: ...

{
  "name" : "my_api_key",
  "description" : "My API key",
  "enabled" : "false",
  "stageKeys" : [ {
    "restApiId" : "uycll6xg9a",
    "stageName" : "prod"
  } ],
  "customerId" : "MARKETPLACE_CUSTOMER_ID"
}
```

The following example shows how to get an API key with a specific AWS Marketplace `customerId` value (*MARKETPLACE\$1CUSTOMER\$1ID*).

```
GET apikeys?customerId=MARKETPLACE_CUSTOMER_ID HTTP/1.1
Host: apigateway.region.amazonaws.com
Authorization: ...
```

To add an API key to a usage plan, create a [https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlanKey.html](https://docs.aws.amazon.com/apigateway/latest/api/API_UsagePlanKey.html) with the API key for the relevant usage plan. The following example shows how to accomplish this using the API Gateway REST API, where `n371pt` is the usage plan ID and `q5ugs7qjjh` is an example API `keyId` returned from the preceding examples.

```
POST /usageplans/n371pt/keys HTTP/1.1
Host: apigateway.region.amazonaws.com
Authorization: ...

{
    "keyId": "q5ugs7qjjh",
    "keyType": "API_KEY"
}
```

### Associate a customer with an API key
<a name="sell-api-as-saas-on-aws-marketplace-subscription-unsubscription-associate-marketplace"></a>

You must update the [https://docs.aws.amazon.com/apigateway/latest/api/API_ApiKey.html](https://docs.aws.amazon.com/apigateway/latest/api/API_ApiKey.html)'s `customerId` field to the AWS Marketplace customer ID of the customer. This associates the API key with the AWS Marketplace customer, which enables metering and billing for the buyer. The following code example calls the API Gateway REST API to do that.

```
PATCH /apikeys/q5ugs7qjjh
Host: apigateway.region.amazonaws.com
Authorization: ...
        
{
    "patchOperations" : [{
        "path" : "/customerId",
        "value" : "MARKETPLACE_CUSTOMER_ID",
        "op" : "replace"
    }]
}
```

# Protect your REST APIs in API Gateway
<a name="rest-api-protect"></a>

API Gateway provides a number of ways to protect your API from certain threats, like malicious users or spikes in traffic. You can protect your API using strategies like generating SSL certificates, configuring a web application firewall, setting throttling targets, and only allowing access to your API from a Virtual Private Cloud (VPC). In this section you can learn how to enable these capabilities using API Gateway.

**Topics**
+ [How to turn on mutual TLS authentication for your REST APIs in API Gateway](rest-api-mutual-tls.md)
+ [Generate and configure an SSL certificate for backend authentication in API Gateway](getting-started-client-side-ssl-authentication.md)
+ [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md)
+ [Throttle requests to your REST APIs for better throughput in API Gateway](api-gateway-request-throttling.md)
+ [Private REST APIs in API Gateway](apigateway-private-apis.md)

# How to turn on mutual TLS authentication for your REST APIs in API Gateway
<a name="rest-api-mutual-tls"></a>

Mutual TLS authentication requires two-way authentication between the client and the server. With mutual TLS, clients must present X.509 certificates to verify their identity to access your API. Mutual TLS is a common requirement for Internet of Things (IoT) and business-to-business applications. 

You can use mutual TLS along with other [authorization and authentication operations](apigateway-control-access-to-api.md) that API Gateway supports. API Gateway forwards the certificates that clients provide to Lambda authorizers and to backend integrations.

**Important**  
By default, clients can invoke your API by using the `execute-api` endpoint that API Gateway generates for your API. To ensure that clients can access your API only by using a custom domain name with mutual TLS, disable the default `execute-api` endpoint. To learn more, see [Disable the default endpoint for REST APIs](rest-api-disable-default-endpoint.md). 

**Topics**
+ [Prerequisites for mutual TLS](#rest-api-mutual-tls-prerequisites)
+ [Configuring mutual TLS for a custom domain name](#rest-api-mutual-tls-configure)
+ [Invoke an API by using a custom domain name that requires mutual TLS](#rest-api-mutual-tls-invoke)
+ [Updating your truststore](#rest-api-mutual-tls-update-truststore)
+ [Disable mutual TLS](#rest-api-mutual-tls-disable)
+ [Troubleshoot mutual TLS for your REST API](#rest-api-mutual-tls-troubleshooting)

## Prerequisites for mutual TLS
<a name="rest-api-mutual-tls-prerequisites"></a>

To configure mutual TLS you need:
+ A Regional custom domain name
+ At least one certificate configured in AWS Certificate Manager for your custom domain name
+ A truststore configured and uploaded to Amazon S3

### Custom domain names
<a name="rest-api-mutual-tls-custom-domain-name"></a>

 To enable mutual TLS for a REST API, you must configure a custom domain name for your API. You can enable mutual TLS for a custom domain name, and then provide the custom domain name to clients. To access an API by using a custom domain name that has mutual TLS enabled, clients must present certificates that you trust in API requests. You can find more information at [Custom domain name for public REST APIs in API Gateway](how-to-custom-domains.md).

### Using AWS Certificate Manager issued certificates
<a name="rest-api-mutual-tls-using-acm-issued-certs"></a>

You can request a publicly trusted certificate directly from ACM or import public or self-signed certificates. To setup a certificate in ACM, go to [ACM](https://console.aws.amazon.com/acm/). If you would like to import a certificate, continue reading in the following section.

### Using an imported or AWS Private Certificate Authority certificate
<a name="rest-api-mutual-tls-non-acm-certs"></a>

To use a certificate imported into ACM or a certificate from AWS Private Certificate Authority with mutual TLS, API Gateway needs an `ownershipVerificationCertificate` issued by ACM. This ownership certificate is only used to verify that you have permissions to use the domain name. It is not used for the TLS handshake. If you don't already have a `ownershipVerificationCertificate`, go to [https://console.aws.amazon.com/acm/](https://console.aws.amazon.com/acm/) to set one up.

You will need to keep this certificate valid for the lifetime of your domain name. If a certificate expires and auto-renew fails, all updates to the domain name will be locked. You will need to update the `ownershipVerificationCertificateArn` with a valid `ownershipVerificationCertificate` before you can make any other changes. The `ownershipVerificationCertificate` cannot be used as a server certificate for another mutual TLS domain in API Gateway. If a certificate is directly re-imported into ACM, the issuer must stay the same.

### Configuring your truststore
<a name="rest-api-mutual-tls-create-trust-store"></a>

Truststores are text files with a `.pem` file extension. They are a trusted list of certificates from Certificate Authorities. To use mutual TLS, create a truststore of X.509 certificates that you trust to access your API.

You must include the complete chain of trust, starting from the issuing CA certificate, up to the root CA certificate, in your truststore. API Gateway accepts client certificates issued by any CA present in the chain of trust. The certificates can be from public or private certificate authorities. Certificates can have a maximum chain length of four. You can also provide self-signed certificates. The following algorithms are supported in the truststore:
+ SHA-256 or stronger
+ RSA-2048 or stronger
+ ECDSA-256 or ECDSA-384

API Gateway validates a number of certificate properties. You can use Lambda authorizers to perform additional checks when a client invokes an API, including checking whether a certificate has been revoked. API Gateway validates the following properties:


| Validation | Description | 
| --- | --- | 
|  X.509 syntax  |  The certificate must meet X.509 syntax requirements.  | 
|  Integrity  |  The certificate's content must not have been altered from that signed by the certificate authority from the truststore.  | 
|  Validity  |  The certificate's validity period must be current.  | 
|  Name chaining / key chaining  |  The names and subjects of certificates must form an unbroken chain. Certificates can have a maximum chain length of four.  | 

### Upload the truststore to an Amazon S3 bucket in a single file
<a name="w2aac15c20b7c11c13"></a>

The following is an example of what a .pem file might look like.

**Example certificates.pem**  

```
-----BEGIN CERTIFICATE-----
<Certificate contents>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<Certificate contents>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<Certificate contents>
-----END CERTIFICATE-----
...
```

The following [cp](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html) AWS CLI command uploads `certificates.pem` to your Amazon S3 bucket:

```
aws s3 cp certificates.pem s3://bucket-name
```

## Configuring mutual TLS for a custom domain name
<a name="rest-api-mutual-tls-configure"></a>

To configure mutual TLS for a REST API, you must use a Regional custom domain name for your API, with a `TLS_1_2` security policy. For more information about choosing a security policy, see [Choose a security policy for your custom domain in API Gateway](apigateway-custom-domain-tls-version.md).

**Note**  
Mutual TLS isn't supported for private APIs.

After you've uploaded your truststore to Amazon S3, you can configure your custom domain name to use mutual TLS. The following [create-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-domain-name.html) creates a custom domain name with mutual TLS:

```
aws apigateway create-domain-name --region us-east-2 \
    --domain-name api.example.com \
    --regional-certificate-arn arn:aws:acm:us-east-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --endpoint-configuration types=REGIONAL \
    --security-policy TLS_1_2 \
    --mutual-tls-authentication truststoreUri=s3://bucket-name/key-name
```

After you create the domain name, you must configure DNS records and basepath mappings for API operations. To learn more, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md).

## Invoke an API by using a custom domain name that requires mutual TLS
<a name="rest-api-mutual-tls-invoke"></a>

To invoke an API with mutual TLS enabled, clients must present a trusted certificate in the API request. When a client attempts to invoke your API, API Gateway looks for the client certificate's issuer in your truststore. For API Gateway to proceed with the request, the certificate's issuer and the complete chain of trust up to the root CA certificate must be in your truststore.

The following example `curl` command sends a request to `api.example.com,` that includes `my-cert.pem` in the request. `my-key.key` is the private key for the certificate.

```
curl -v --key ./my-key.key --cert ./my-cert.pem api.example.com
```

Your API is invoked only if your truststore trusts the certificate. The following conditions will cause API Gateway to fail the TLS handshake and deny the request with a `403` status code. If your certificate:
+ isn't trusted
+ is expired
+ doesn't use a supported algorithm

**Note**  
API Gateway doesn't verify if a certificate has been revoked.

## Updating your truststore
<a name="rest-api-mutual-tls-update-truststore"></a>

To update the certificates in your truststore, upload a new certificate bundle to Amazon S3. Then, you can update your custom domain name to use the updated certificate.

Use [Amazon S3 versioning](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html) to maintain multiple versions of your truststore. When you update your custom domain name to use a new truststore version, API Gateway returns warnings if certificates are invalid.

API Gateway produces certificate warnings only when you update your domain name. API Gateway doesn’t notify you if a previously uploaded certificate expires.

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command updates a custom domain name to use a new truststore version:

```
aws apigateway update-domain-name \
    --domain-name api.example.com \
    --patch-operations op='replace',path='/mutualTlsAuthentication/truststoreVersion',value='abcdef123'
```

## Disable mutual TLS
<a name="rest-api-mutual-tls-disable"></a>

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) disables mutual TLS:

```
aws apigateway update-domain-name \
    --domain-name api.example.com \
    --patch-operations op='replace',path='/mutualTlsAuthentication/truststoreUri',value=''
```

## Troubleshoot mutual TLS for your REST API
<a name="rest-api-mutual-tls-troubleshooting"></a>

The following provides troubleshooting advice for errors and issues that you might encounter when turning on mutual TLS.

### Troubleshooting certificate warnings
<a name="rest-api-mutual-tls-troubleshooting-certificate"></a>

 When creating a custom domain name with mutual TLS, API Gateway returns warnings if certificates in the truststore are not valid. This can also occur when updating a custom domain name to use a new truststore. The warnings indicate the issue with the certificate and the subject of the certificate that produced the warning. Mutual TLS is still enabled for your API, but some clients might not be able to access your API.

You'll need to decode the certificates in your truststore in order to identify which certificate produced the warning. You can use tools such as `openssl` to decode the certificates and identify their subjects.

The following command displays the contents of a certificate, including its subject:

```
openssl x509 -in certificate.crt -text -noout
```

Update or remove the certificates that produced warnings, and then upload a new truststore to Amazon S3. After uploading the new truststore, update your custom domain name to use the new truststore.

### Troubleshooting domain name conflicts
<a name="w2aac15c20b7c21b7"></a>

The error `"The certificate subject <certSubject> conflicts with an existing certificate from a different issuer."` means multiple Certificate Authorities have issued a certificate for this domain. For each subject in the certificate, there can only be one issuer in API Gateway for mutual TLS domains. You will need to get all of your certificates for that subject through a single issuer. If the problem is with a certificate you don't have control of but you can prove ownership of the domain name, [contact Support](https://console.aws.amazon.com/support/cases#/create) to open a ticket.

### Troubleshooting domain name status messages
<a name="w2aac15c20b7c21b9"></a>

`PENDING_CERTIFICATE_REIMPORT`: This means you reimported a certificate to ACM and it failed validation because the new certificate has a SAN (subject alternative name) that is not covered by the `ownershipVerificationCertificate` or the subject or SANs in the certificate don't cover the domain name. Something might be configured incorrectly or an invalid certificate was imported. You need to reimport a valid certificate into ACM. For more information about validation see [Validating domain ownership](https://docs.aws.amazon.com/acm/latest/userguide/domain-ownership-validation.html).

`PENDING_OWNERSHIP_VERIFICATION`: This means your previously verified certificate has expired and ACM was unable to auto-renew it. You will need to renew the certificate or request a new certificate. More information about certificate renewal can be found at [ACM's troubleshooting managed certificate renewal](https://docs.aws.amazon.com/acm/latest/userguide/troubleshooting-renewal.html) guide.

### Troubleshoot incorrect returned certificate
<a name="w2aac15c20b7c21c11"></a>

When migrating a dedicated certificate from a fully qualified domain name (FQDN) to a wildcard customer domain name, API Gateway might return the certificate for the FQDN instead of the wildcard domain name.

The following command displays which certificate is being returned by API Gateway:

```
openssl s_client -connect hostname:port
```

If the resulting certificate is for the FQDN, [contact Support](https://console.aws.amazon.com/support/cases#/create) to open a ticket.

# Generate and configure an SSL certificate for backend authentication in API Gateway
<a name="getting-started-client-side-ssl-authentication"></a>

 You can use API Gateway to generate an SSL certificate and then use its public key in the backend to verify that HTTP requests to your backend system are from API Gateway. This allows your HTTP backend to control and accept only requests that originate from Amazon API Gateway, even if the backend is publicly accessible. 

**Note**  
 Some backend servers might not support SSL client authentication as API Gateway does and could return an SSL certificate error. For a list of incompatible backend servers, see [Amazon API Gateway important notes](api-gateway-known-issues.md). 

 The SSL certificates that are generated by API Gateway are self-signed, and only the public key of a certificate is visible in the API Gateway console or through the APIs. 

**Topics**
+ [Generate a client certificate using the API Gateway console](#generate-client-certificate)
+ [Configure an API to use SSL certificates](#configure-api)
+ [Test invoke to verify the client certificate configuration](#test-invoke)
+ [Configure a backend HTTPS server to verify the client certificate](#certificate-validation)
+ [Rotate an expiring client certificate](#certificate-rotation)
+ [API Gateway-supported certificate authorities for HTTP and HTTP proxy integrations in API Gateway](api-gateway-supported-certificate-authorities-for-http-endpoints.md)

## Generate a client certificate using the API Gateway console
<a name="generate-client-certificate"></a>

1. Open the API Gateway console at [https://console.aws.amazon.com/apigateway/](https://console.aws.amazon.com/apigateway/). 

1. Choose a REST or WebSocket API.

1. In the main navigation pane, choose **Client certificates**.

1. From the **Client certificates** page, choose **Generate certificate**.

1.  (Optional) For **Description**, enter a description. 

1. Choose **Generate certificate** to generate the certificate. API Gateway generates a new certificate and returns the new certificate GUID, along with the PEM-encoded public key. 

You're now ready to configure an API to use the certificate.

## Configure an API to use SSL certificates
<a name="configure-api"></a>

These instructions assume that you already completed [Generate a client certificate using the API Gateway console](#generate-client-certificate).

1.  In the API Gateway console, create or open an REST or WebSocket API for which you want to use the client certificate. Make sure that the API has been deployed to a stage. 

1. In the main navigation pane, choose **Stages**.

1. In the **Stage details** section, choose **Edit**.

1. For **Client certificate**, select a certificate.

1. Choose **Save changes**.

After a certificate is selected for the API and saved, API Gateway uses the certificate for all calls to HTTP integrations in your API. 

## Test invoke to verify the client certificate configuration
<a name="test-invoke"></a>

1. Choose a REST API method. Choose the **Test** tab. You might need to choose the right arrow button to show the **Test** tab.

1. For **Client certificate**, select a certificate. 

1. Choose **Test**. 

 API Gateway presents the chosen SSL certificate for the HTTP backend to authenticate the API. 

## Configure a backend HTTPS server to verify the client certificate
<a name="certificate-validation"></a>

These instructions assume that you already completed [Generate a client certificate using the API Gateway console](#generate-client-certificate) and downloaded a copy of the client certificate. You can download a client certificate by calling [https://docs.aws.amazon.com/apigateway/latest/api/API_GetClientCertificate.html](https://docs.aws.amazon.com/apigateway/latest/api/API_GetClientCertificate.html) of the API Gateway REST API or [https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-client-certificate.html](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-client-certificate.html) of AWS CLI. 

 Before configuring a backend HTTPS server to verify the client SSL certificate of API Gateway, you must have obtained the PEM-encoded private key and a server-side certificate that is provided by a trusted certificate authority. 

If the server domain name is `myserver.mydomain.com`, the server certificate's CNAME value must be `myserver.mydomain.com` or `*.mydomain.com`. 

Supported certificate authorities include [Let's Encrypt](https://letsencrypt.org/) or one of [API Gateway-supported certificate authorities for HTTP and HTTP proxy integrations in API Gateway](api-gateway-supported-certificate-authorities-for-http-endpoints.md). 

As an example, suppose that the client certificate file is `apig-cert.pem` and the server private key and certificate files are `server-key.pem` and `server-cert.pem`, respectively. For a Node.js server in the backend, you can configure the server similar to the following:

```
var fs = require('fs'); 
var https = require('https');
var options = { 
    key: fs.readFileSync('server-key.pem'), 
    cert: fs.readFileSync('server-cert.pem'), 
    ca: fs.readFileSync('apig-cert.pem'), 
    requestCert: true, 
    rejectUnauthorized: true
};
https.createServer(options, function (req, res) { 
    res.writeHead(200); 
    res.end("hello world\n"); 
}).listen(443);
```



For a node-[express](http://expressjs.com/) app, you can use the [client-certificate-auth](https://www.npmjs.com/package/client-certificate-auth) modules to authenticate client requests with PEM-encoded certificates. 

For other HTTPS server, see the documentation for the server.

## Rotate an expiring client certificate
<a name="certificate-rotation"></a>

The client certificate generated by API Gateway is valid for 365 days. You must rotate the certificate before a client certificate on an API stage expires to avoid any downtime for the API.

### Rotate an expiring client certificate using the AWS Management Console
<a name="certification-rotation-console"></a>

The following procedure shows how to rotate a client certificate in the console for a previously deployed API.

1. In the main navigation pane, choose **Client certificates**.

1. From the **Client certificates** pane, choose **Generate certificate**.

1.  Open the API for which you want to use the client certificate. 

1. Choose **Stages** under the selected API and then choose a stage.

1. In the **Stage details** section, choose **Edit**.

1. For **Client certificate**, select the new certificate.

1. To save the settings, choose **Save changes**.

### Rotate an expiring client certificate using the AWS CLI
<a name="certificate-rotation-cli"></a>

 You can check the expiration date of certificate by calling [clientCertificate:by-id](https://docs.aws.amazon.com/apigateway/latest/api/API_GetClientCertificate.html) of the API Gateway REST API or the AWS CLI command of [get-client-certificate](https://docs.aws.amazon.com/cli/latest/reference/apigateway/get-client-certificate.html) and inspecting the returned [expirationDate](https://docs.aws.amazon.com/apigateway/latest/api/API_ClientCertificate.html#expirationDate) property.

To rotate a client certificate, do the following:

1. Generate a new client certificate by calling [clientcertificate:generate](https://docs.aws.amazon.com/apigateway/latest/api/API_GenerateClientCertificate.html) of the API Gateway REST API or the AWS CLI command of [generate-client-certificate](https://docs.aws.amazon.com/cli/latest/reference/apigateway/generate-client-certificate.html). In this tutorial, we assume that the new client certificate ID is `ndiqef`.

1.  Update the backend server to include the new client certificate. Don't remove the existing client certificate yet.

   Some servers might require a restart to finish the update. Consult the server documentation to see if you must restart the server during the update.

1.  Update the API stage to use the new client certificate by calling [stage:update](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateStage.html) of the API Gateway REST API, with the new client certificate ID (`ndiqef`):

   ```
   PATCH /restapis/{restapi-id}/stages/stage1 HTTP/1.1
   Content-Type: application/json
   Host: apigateway.us-east-1.amazonaws.com
   X-Amz-Date: 20170603T200400Z
   Authorization: AWS4-HMAC-SHA256 Credential=...
   
   {
     "patchOperations" : [
       {
           "op" : "replace",
           "path" : "/clientCertificateId",
           "value" : "ndiqef"
       }
     ]
   }
   ```

   You can also use the [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) command.

   If you are using a WebSocket API, use the `apigatewayv2` [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) command.

1.  Update the backend server to remove the old certificate.

1.  Delete the old certificate from API Gateway by calling the [clientcertificate:delete](https://docs.aws.amazon.com/apigateway/latest/api/API_DeleteClientCertificate.html) of the API Gateway REST API, specifying the clientCertificateId (`a1b2c3`) of the old certificate:

   ```
   DELETE /clientcertificates/a1b2c3 
   ```

   You can also call the [delete-client-certificate](https://docs.aws.amazon.com/cli/latest/reference/apigateway/delete-client-certificate.html) command:

   ```
   aws apigateway delete-client-certificate --client-certificate-id a1b2c3
   ```

# API Gateway-supported certificate authorities for HTTP and HTTP proxy integrations in API Gateway
<a name="api-gateway-supported-certificate-authorities-for-http-endpoints"></a>

 The following list shows the certificate authorities supported by API Gateway for HTTP, HTTP proxy, and private integrations. 

```
Alias name: accvraiz1
	 SHA1: 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17
	 SHA256: 9A:6E:C0:12:E1:A7:DA:9D:BE:34:19:4D:47:8A:D7:C0:DB:18:22:FB:07:1D:F1:29:81:49:6E:D1:04:38:41:13
Alias name: acraizfnmtrcm
	 SHA1: EC:50:35:07:B2:15:C4:95:62:19:E2:A8:9A:5B:42:99:2C:4C:2C:20
	 SHA256: EB:C5:57:0C:29:01:8C:4D:67:B1:AA:12:7B:AF:12:F7:03:B4:61:1E:BC:17:B7:DA:B5:57:38:94:17:9B:93:FA
Alias name: actalis
	 SHA1: F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC
	 SHA256: 55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66
Alias name: actalisauthenticationrootca
	 SHA1: F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC
	 SHA256: 55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66
Alias name: addtrustclass1ca
	 SHA1: CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D
	 SHA256: 8C:72:09:27:9A:C0:4E:27:5E:16:D0:7F:D3:B7:75:E8:01:54:B5:96:80:46:E3:1F:52:DD:25:76:63:24:E9:A7
Alias name: addtrustexternalca
	 SHA1: 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68
	 SHA256: 68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2
Alias name: addtrustqualifiedca
	 SHA1: 4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF
	 SHA256: 80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16
Alias name: affirmtrustcommercial
	 SHA1: F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7
	 SHA256: 03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7
Alias name: affirmtrustcommercialca
	 SHA1: F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7
	 SHA256: 03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7
Alias name: affirmtrustnetworking
	 SHA1: 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F
	 SHA256: 0A:81:EC:5A:92:97:77:F1:45:90:4A:F3:8D:5D:50:9F:66:B5:E2:C5:8F:CD:B5:31:05:8B:0E:17:F3:F0:B4:1B
Alias name: affirmtrustnetworkingca
	 SHA1: 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F
	 SHA256: 0A:81:EC:5A:92:97:77:F1:45:90:4A:F3:8D:5D:50:9F:66:B5:E2:C5:8F:CD:B5:31:05:8B:0E:17:F3:F0:B4:1B
Alias name: affirmtrustpremium
	 SHA1: D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27
	 SHA256: 70:A7:3F:7F:37:6B:60:07:42:48:90:45:34:B1:14:82:D5:BF:0E:69:8E:CC:49:8D:F5:25:77:EB:F2:E9:3B:9A
Alias name: affirmtrustpremiumca
	 SHA1: D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27
	 SHA256: 70:A7:3F:7F:37:6B:60:07:42:48:90:45:34:B1:14:82:D5:BF:0E:69:8E:CC:49:8D:F5:25:77:EB:F2:E9:3B:9A
Alias name: affirmtrustpremiumecc
	 SHA1: B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB
	 SHA256: BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23
Alias name: affirmtrustpremiumeccca
	 SHA1: B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB
	 SHA256: BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23
Alias name: amazon-ca-g4-acm1
	 SHA1: F2:0D:28:B6:29:C2:2C:5E:84:05:E6:02:4D:97:FE:8F:A0:84:93:A0
	 SHA256: B0:11:A4:F7:29:6C:74:D8:2B:F5:62:DF:87:D7:28:C7:1F:B5:8C:F4:E6:73:F2:78:FC:DA:F3:FF:83:A6:8C:87
Alias name: amazon-ca-g4-acm2
	 SHA1: A7:E6:45:32:1F:7A:B7:AD:C0:70:EA:73:5F:AB:ED:C3:DA:B4:D0:C8
	 SHA256: D7:A8:7C:69:95:D0:E2:04:2A:32:70:A7:E2:87:FE:A7:E8:F4:C1:70:62:F7:90:C3:EB:BB:53:F2:AC:39:26:BE
Alias name: amazon-ca-g4-acm3
	 SHA1: 7A:DB:56:57:5F:D6:EE:67:85:0A:64:BB:1C:E9:E4:B0:9A:DB:9D:07
	 SHA256: 6B:EB:9D:20:2E:C2:00:70:BD:D2:5E:D3:C0:C8:33:2C:B4:78:07:C5:82:94:4E:7E:23:28:22:71:A4:8E:0E:C2
Alias name: amazon-ca-g4-legacy
	 SHA1: EA:E7:DE:F9:0A:BE:9F:0B:68:CE:B7:24:0D:80:74:03:BF:6E:B1:6E
	 SHA256: CD:72:C4:7F:B4:AD:28:A4:67:2B:E1:86:47:D4:40:E9:3B:16:2D:95:DB:3C:2F:94:BB:81:D9:09:F7:91:24:5E
Alias name: amazon-root-ca-ecc-384-1
	 SHA1: F9:5E:4A:AB:9C:2D:57:61:63:3D:B2:57:B4:0F:24:9E:7B:E2:23:7D
	 SHA256: C6:BD:E5:66:C2:72:2A:0E:96:E9:C1:2C:BF:38:92:D9:55:4D:29:03:57:30:72:40:7F:4E:70:17:3B:3C:9B:63
Alias name: amazon-root-ca-rsa-2k-1
	 SHA1: 8A:9A:AC:27:FC:86:D4:50:23:AD:D5:63:F9:1E:AE:2C:AF:63:08:6C
	 SHA256: 0F:8F:33:83:FB:70:02:89:49:24:E1:AA:B0:D7:FB:5A:BF:98:DF:75:8E:0F:FE:61:86:92:BC:F0:75:35:CC:80
Alias name: amazon-root-ca-rsa-4k-1
	 SHA1: EC:BD:09:61:F5:7A:B6:A8:76:BB:20:8F:14:05:ED:7E:70:ED:39:45
	 SHA256: 36:AE:AD:C2:6A:60:07:90:6B:83:A3:73:2D:D1:2B:D4:00:5E:C7:F2:76:11:99:A9:D4:DA:63:2F:59:B2:8B:CF
Alias name: amazon1
	 SHA1: 8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16
	 SHA256: 8E:CD:E6:88:4F:3D:87:B1:12:5B:A3:1A:C3:FC:B1:3D:70:16:DE:7F:57:CC:90:4F:E1:CB:97:C6:AE:98:19:6E
Alias name: amazon2
	 SHA1: 5A:8C:EF:45:D7:A6:98:59:76:7A:8C:8B:44:96:B5:78:CF:47:4B:1A
	 SHA256: 1B:A5:B2:AA:8C:65:40:1A:82:96:01:18:F8:0B:EC:4F:62:30:4D:83:CE:C4:71:3A:19:C3:9C:01:1E:A4:6D:B4
Alias name: amazon3
	 SHA1: 0D:44:DD:8C:3C:8C:1A:1A:58:75:64:81:E9:0F:2E:2A:FF:B3:D2:6E
	 SHA256: 18:CE:6C:FE:7B:F1:4E:60:B2:E3:47:B8:DF:E8:68:CB:31:D0:2E:BB:3A:DA:27:15:69:F5:03:43:B4:6D:B3:A4
Alias name: amazon4
	 SHA1: F6:10:84:07:D6:F8:BB:67:98:0C:C2:E2:44:C2:EB:AE:1C:EF:63:BE
	 SHA256: E3:5D:28:41:9E:D0:20:25:CF:A6:90:38:CD:62:39:62:45:8D:A5:C6:95:FB:DE:A3:C2:2B:0B:FB:25:89:70:92
Alias name: amazonrootca1
	 SHA1: 8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16
	 SHA256: 8E:CD:E6:88:4F:3D:87:B1:12:5B:A3:1A:C3:FC:B1:3D:70:16:DE:7F:57:CC:90:4F:E1:CB:97:C6:AE:98:19:6E
Alias name: amazonrootca2
	 SHA1: 5A:8C:EF:45:D7:A6:98:59:76:7A:8C:8B:44:96:B5:78:CF:47:4B:1A
	 SHA256: 1B:A5:B2:AA:8C:65:40:1A:82:96:01:18:F8:0B:EC:4F:62:30:4D:83:CE:C4:71:3A:19:C3:9C:01:1E:A4:6D:B4
Alias name: amazonrootca3
	 SHA1: 0D:44:DD:8C:3C:8C:1A:1A:58:75:64:81:E9:0F:2E:2A:FF:B3:D2:6E
	 SHA256: 18:CE:6C:FE:7B:F1:4E:60:B2:E3:47:B8:DF:E8:68:CB:31:D0:2E:BB:3A:DA:27:15:69:F5:03:43:B4:6D:B3:A4
Alias name: amazonrootca4
	 SHA1: F6:10:84:07:D6:F8:BB:67:98:0C:C2:E2:44:C2:EB:AE:1C:EF:63:BE
	 SHA256: E3:5D:28:41:9E:D0:20:25:CF:A6:90:38:CD:62:39:62:45:8D:A5:C6:95:FB:DE:A3:C2:2B:0B:FB:25:89:70:92
Alias name: amzninternalinfoseccag3
	 SHA1: B9:B1:CA:38:F7:BF:9C:D2:D4:95:E7:B6:5E:75:32:9B:A8:78:2E:F6
	 SHA256: 81:03:0B:C7:E2:54:DA:7B:F8:B7:45:DB:DD:41:15:89:B5:A3:81:86:FB:4B:29:77:1F:84:0A:18:D9:67:6D:68
Alias name: amzninternalrootca
	 SHA1: A7:B7:F6:15:8A:FF:1E:C8:85:13:38:BC:93:EB:A2:AB:A4:09:EF:06
	 SHA256: 0E:DE:63:C1:DC:7A:8E:11:F1:AB:BC:05:4F:59:EE:49:9D:62:9A:2F:DE:9C:A7:16:32:A2:64:29:3E:8B:66:AA
Alias name: aolrootca1
	 SHA1: 39:21:C1:15:C1:5D:0E:CA:5C:CB:5B:C4:F0:7D:21:D8:05:0B:56:6A
	 SHA256: 77:40:73:12:C6:3A:15:3D:5B:C0:0B:4E:51:75:9C:DF:DA:C2:37:DC:2A:33:B6:79:46:E9:8E:9B:FA:68:0A:E3
Alias name: aolrootca2
	 SHA1: 85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84
	 SHA256: 7D:3B:46:5A:60:14:E5:26:C0:AF:FC:EE:21:27:D2:31:17:27:AD:81:1C:26:84:2D:00:6A:F3:73:06:CC:80:BD
Alias name: atostrustedroot2011
	 SHA1: 2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21
	 SHA256: F3:56:BE:A2:44:B7:A9:1E:B3:5D:53:CA:9A:D7:86:4A:CE:01:8E:2D:35:D5:F8:F9:6D:DF:68:A6:F4:1A:A4:74
Alias name: autoridaddecertificacionfirmaprofesionalcifa62634068
	 SHA1: AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA
	 SHA256: 04:04:80:28:BF:1F:28:64:D4:8F:9A:D4:D8:32:94:36:6A:82:88:56:55:3F:3B:14:30:3F:90:14:7F:5D:40:EF
Alias name: baltimorecodesigningca
	 SHA1: 30:46:D8:C8:88:FF:69:30:C3:4A:FC:CD:49:27:08:7C:60:56:7B:0D
	 SHA256: A9:15:45:DB:D2:E1:9C:4C:CD:F9:09:AA:71:90:0D:18:C7:35:1C:89:B3:15:F0:F1:3D:05:C1:3A:8F:FB:46:87
Alias name: baltimorecybertrustca
	 SHA1: D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74
	 SHA256: 16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB
Alias name: baltimorecybertrustroot
	 SHA1: D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74
	 SHA256: 16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB
Alias name: buypassclass2ca
	 SHA1: 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99
	 SHA256: 9A:11:40:25:19:7C:5B:B9:5D:94:E6:3D:55:CD:43:79:08:47:B6:46:B2:3C:DF:11:AD:A4:A0:0E:FF:15:FB:48
Alias name: buypassclass2rootca
	 SHA1: 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99
	 SHA256: 9A:11:40:25:19:7C:5B:B9:5D:94:E6:3D:55:CD:43:79:08:47:B6:46:B2:3C:DF:11:AD:A4:A0:0E:FF:15:FB:48
Alias name: buypassclass3ca
	 SHA1: DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57
	 SHA256: ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D
Alias name: buypassclass3rootca
	 SHA1: DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57
	 SHA256: ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D
Alias name: cadisigrootr2
	 SHA1: B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71
	 SHA256: E2:3D:4A:03:6D:7B:70:E9:F5:95:B1:42:20:79:D2:B9:1E:DF:BB:1F:B6:51:A0:63:3E:AA:8A:9D:C5:F8:07:03
Alias name: camerfirmachambersca
	 SHA1: 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C
	 SHA256: 06:3E:4A:FA:C4:91:DF:D3:32:F3:08:9B:85:42:E9:46:17:D8:93:D7:FE:94:4E:10:A7:93:7E:E2:9D:96:93:C0
Alias name: camerfirmachamberscommerceca
	 SHA1: 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1
	 SHA256: 0C:25:8A:12:A5:67:4A:EF:25:F2:8B:A7:DC:FA:EC:EE:A3:48:E5:41:E6:F5:CC:4E:E6:3B:71:B3:61:60:6A:C3
Alias name: camerfirmachambersignca
	 SHA1: 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C
	 SHA256: 13:63:35:43:93:34:A7:69:80:16:A0:D3:24:DE:72:28:4E:07:9D:7B:52:20:BB:8F:BD:74:78:16:EE:BE:BA:CA
Alias name: certigna
	 SHA1: B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97
	 SHA256: E3:B6:A2:DB:2E:D7:CE:48:84:2F:7A:C5:32:41:C7:B7:1D:54:14:4B:FB:40:C1:1F:3F:1D:0B:42:F5:EE:A1:2D
Alias name: certignarootca
	 SHA1: 2D:0D:52:14:FF:9E:AD:99:24:01:74:20:47:6E:6C:85:27:27:F5:43
	 SHA256: D4:8D:3D:23:EE:DB:50:A4:59:E5:51:97:60:1C:27:77:4B:9D:7B:18:C9:4D:5A:05:95:11:A1:02:50:B9:31:68
Alias name: certplusclass2primaryca
	 SHA1: 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB
	 SHA256: 0F:99:3C:8A:EF:97:BA:AF:56:87:14:0E:D5:9A:D1:82:1B:B4:AF:AC:F0:AA:9A:58:B5:D5:7A:33:8A:3A:FB:CB
Alias name: certplusclass3pprimaryca
	 SHA1: 21:6B:2A:29:E6:2A:00:CE:82:01:46:D8:24:41:41:B9:25:11:B2:79
	 SHA256: CC:C8:94:89:37:1B:AD:11:1C:90:61:9B:EA:24:0A:2E:6D:AD:D9:9F:9F:6E:1D:4D:41:E5:8E:D6:DE:3D:02:85
Alias name: certsignrootca
	 SHA1: FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B
	 SHA256: EA:A9:62:C4:FA:4A:6B:AF:EB:E4:15:19:6D:35:1C:CD:88:8D:4F:53:F3:FA:8A:E6:D7:C4:66:A9:4E:60:42:BB
Alias name: certsignrootcag2
	 SHA1: 26:F9:93:B4:ED:3D:28:27:B0:B9:4B:A7:E9:15:1D:A3:8D:92:E5:32
	 SHA256: 65:7C:FE:2F:A7:3F:AA:38:46:25:71:F3:32:A2:36:3A:46:FC:E7:02:09:51:71:07:02:CD:FB:B6:EE:DA:33:05
Alias name: certum2
	 SHA1: D3:DD:48:3E:2B:BF:4C:05:E8:AF:10:F5:FA:76:26:CF:D3:DC:30:92
	 SHA256: B6:76:F2:ED:DA:E8:77:5C:D3:6C:B0:F6:3C:D1:D4:60:39:61:F4:9E:62:65:BA:01:3A:2F:03:07:B6:D0:B8:04
Alias name: certumca
	 SHA1: 62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18
	 SHA256: D8:E0:FE:BC:1D:B2:E3:8D:00:94:0F:37:D2:7D:41:34:4D:99:3E:73:4B:99:D5:65:6D:97:78:D4:D8:14:36:24
Alias name: certumtrustednetworkca
	 SHA1: 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E
	 SHA256: 5C:58:46:8D:55:F5:8E:49:7E:74:39:82:D2:B5:00:10:B6:D1:65:37:4A:CF:83:A7:D4:A3:2D:B7:68:C4:40:8E
Alias name: certumtrustednetworkca2
	 SHA1: D3:DD:48:3E:2B:BF:4C:05:E8:AF:10:F5:FA:76:26:CF:D3:DC:30:92
	 SHA256: B6:76:F2:ED:DA:E8:77:5C:D3:6C:B0:F6:3C:D1:D4:60:39:61:F4:9E:62:65:BA:01:3A:2F:03:07:B6:D0:B8:04
Alias name: cfcaevroot
	 SHA1: E2:B8:29:4B:55:84:AB:6B:58:C2:90:46:6C:AC:3F:B8:39:8F:84:83
	 SHA256: 5C:C3:D7:8E:4E:1D:5E:45:54:7A:04:E6:87:3E:64:F9:0C:F9:53:6D:1C:CC:2E:F8:00:F3:55:C4:C5:FD:70:FD
Alias name: chambersofcommerceroot2008
	 SHA1: 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C
	 SHA256: 06:3E:4A:FA:C4:91:DF:D3:32:F3:08:9B:85:42:E9:46:17:D8:93:D7:FE:94:4E:10:A7:93:7E:E2:9D:96:93:C0
Alias name: chunghwaepkirootca
	 SHA1: 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0
	 SHA256: C0:A6:F4:DC:63:A2:4B:FD:CF:54:EF:2A:6A:08:2A:0A:72:DE:35:80:3E:2F:F5:FF:52:7A:E5:D8:72:06:DF:D5
Alias name: cia-crt-g3-01-ca
	 SHA1: 2B:EE:2C:BA:A3:1D:B5:FE:60:40:41:95:08:ED:46:82:39:4D:ED:E2
	 SHA256: 20:48:AD:4C:EC:90:7F:FA:4A:15:D4:CE:45:E3:C8:E4:2C:EA:78:33:DC:C7:D3:40:48:FC:60:47:27:42:99:EC
Alias name: cia-crt-g3-02-ca
	 SHA1: 96:4A:BB:A7:BD:DA:FC:97:34:C0:0A:2D:F0:05:98:F7:E6:C6:6F:09
	 SHA256: 93:F1:72:FB:BA:43:31:5C:06:EE:0F:9F:04:89:B8:F6:88:BC:75:15:3C:BE:B4:80:AC:A7:14:3A:F6:FC:4A:C1
Alias name: comodo-ca
	 SHA1: AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4
	 SHA256: 52:F0:E1:C4:E5:8E:C6:29:29:1B:60:31:7F:07:46:71:B8:5D:7E:A8:0D:5B:07:27:34:63:53:4B:32:B4:02:34
Alias name: comodoaaaca
	 SHA1: D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49
	 SHA256: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
Alias name: comodoaaaservicesroot
	 SHA1: D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49
	 SHA256: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
Alias name: comodocertificationauthority
	 SHA1: 66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B
	 SHA256: 0C:2C:D6:3D:F7:80:6F:A3:99:ED:E8:09:11:6B:57:5B:F8:79:89:F0:65:18:F9:80:8C:86:05:03:17:8B:AF:66
Alias name: comodoecccertificationauthority
	 SHA1: 9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11
	 SHA256: 17:93:92:7A:06:14:54:97:89:AD:CE:2F:8F:34:F7:F0:B6:6D:0F:3A:E3:A3:B8:4D:21:EC:15:DB:BA:4F:AD:C7
Alias name: comodorsacertificationauthority
	 SHA1: AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4
	 SHA256: 52:F0:E1:C4:E5:8E:C6:29:29:1B:60:31:7F:07:46:71:B8:5D:7E:A8:0D:5B:07:27:34:63:53:4B:32:B4:02:34
Alias name: cybertrustglobalroot
	 SHA1: 5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6
	 SHA256: 96:0A:DF:00:63:E9:63:56:75:0C:29:65:DD:0A:08:67:DA:0B:9C:BD:6E:77:71:4A:EA:FB:23:49:AB:39:3D:A3
Alias name: deprecateditsecca
	 SHA1: 12:12:0B:03:0E:15:14:54:F4:DD:B3:F5:DE:13:6E:83:5A:29:72:9D
	 SHA256: 9A:59:DA:86:24:1A:FD:BA:A3:39:FA:9C:FD:21:6A:0B:06:69:4D:E3:7E:37:52:6B:BE:63:C8:BC:83:74:2E:CB
Alias name: deutschetelekomrootca2
	 SHA1: 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF
	 SHA256: B6:19:1A:50:D0:C3:97:7F:7D:A9:9B:CD:AA:C8:6A:22:7D:AE:B9:67:9E:C7:0B:A3:B0:C9:D9:22:71:C1:70:D3
Alias name: digicertassuredidrootca
	 SHA1: 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43
	 SHA256: 3E:90:99:B5:01:5E:8F:48:6C:00:BC:EA:9D:11:1E:E7:21:FA:BA:35:5A:89:BC:F1:DF:69:56:1E:3D:C6:32:5C
Alias name: digicertassuredidrootg2
	 SHA1: A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F
	 SHA256: 7D:05:EB:B6:82:33:9F:8C:94:51:EE:09:4E:EB:FE:FA:79:53:A1:14:ED:B2:F4:49:49:45:2F:AB:7D:2F:C1:85
Alias name: digicertassuredidrootg3
	 SHA1: F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89
	 SHA256: 7E:37:CB:8B:4C:47:09:0C:AB:36:55:1B:A6:F4:5D:B8:40:68:0F:BA:16:6A:95:2D:B1:00:71:7F:43:05:3F:C2
Alias name: digicertglobalrootca
	 SHA1: A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36
	 SHA256: 43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61
Alias name: digicertglobalrootg2
	 SHA1: DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4
	 SHA256: CB:3C:CB:B7:60:31:E5:E0:13:8F:8D:D3:9A:23:F9:DE:47:FF:C3:5E:43:C1:14:4C:EA:27:D4:6A:5A:B1:CB:5F
Alias name: digicertglobalrootg3
	 SHA1: 7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E
	 SHA256: 31:AD:66:48:F8:10:41:38:C7:38:F3:9E:A4:32:01:33:39:3E:3A:18:CC:02:29:6E:F9:7C:2A:C9:EF:67:31:D0
Alias name: digicerthighassuranceevrootca
	 SHA1: 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25
	 SHA256: 74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF
Alias name: digicerttrustedrootg4
	 SHA1: DD:FB:16:CD:49:31:C9:73:A2:03:7D:3F:C8:3A:4D:7D:77:5D:05:E4
	 SHA256: 55:2F:7B:DC:F1:A7:AF:9E:6C:E6:72:01:7F:4F:12:AB:F7:72:40:C7:8E:76:1A:C2:03:D1:D9:D2:0A:C8:99:88
Alias name: dstrootcax3
	 SHA1: DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13
	 SHA256: 06:87:26:03:31:A7:24:03:D9:09:F1:05:E6:9B:CF:0D:32:E1:BD:24:93:FF:C6:D9:20:6D:11:BC:D6:77:07:39
Alias name: dtrustrootclass3ca22009
	 SHA1: 58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0
	 SHA256: 49:E7:A4:42:AC:F0:EA:62:87:05:00:54:B5:25:64:B6:50:E4:F4:9E:42:E3:48:D6:AA:38:E0:39:E9:57:B1:C1
Alias name: dtrustrootclass3ca2ev2009
	 SHA1: 96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83
	 SHA256: EE:C5:49:6B:98:8C:E9:86:25:B9:34:09:2E:EC:29:08:BE:D0:B0:F3:16:C2:D4:73:0C:84:EA:F1:F3:D3:48:81
Alias name: ecacc
	 SHA1: 28:90:3A:63:5B:52:80:FA:E6:77:4C:0B:6D:A7:D6:BA:A6:4A:F2:E8
	 SHA256: 88:49:7F:01:60:2F:31:54:24:6A:E2:8C:4D:5A:EF:10:F1:D8:7E:BB:76:62:6F:4A:E0:B7:F9:5B:A7:96:87:99
Alias name: emsigneccrootcac3
	 SHA1: B6:AF:43:C2:9B:81:53:7D:F6:EF:6B:C3:1F:1F:60:15:0C:EE:48:66
	 SHA256: BC:4D:80:9B:15:18:9D:78:DB:3E:1D:8C:F4:F9:72:6A:79:5D:A1:64:3C:A5:F1:35:8E:1D:DB:0E:DC:0D:7E:B3
Alias name: emsigneccrootcag3
	 SHA1: 30:43:FA:4F:F2:57:DC:A0:C3:80:EE:2E:58:EA:78:B2:3F:E6:BB:C1
	 SHA256: 86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B
Alias name: emsignrootcac1
	 SHA1: E7:2E:F1:DF:FC:B2:09:28:CF:5D:D4:D5:67:37:B1:51:CB:86:4F:01
	 SHA256: 12:56:09:AA:30:1D:A0:A2:49:B9:7A:82:39:CB:6A:34:21:6F:44:DC:AC:9F:39:54:B1:42:92:F2:E8:C8:60:8F
Alias name: emsignrootcag1
	 SHA1: 8A:C7:AD:8F:73:AC:4E:C1:B5:75:4D:A5:40:F4:FC:CF:7C:B5:8E:8C
	 SHA256: 40:F6:AF:03:46:A9:9A:A1:CD:1D:55:5A:4E:9C:CE:62:C7:F9:63:46:03:EE:40:66:15:83:3D:C8:C8:D0:03:67
Alias name: entrust2048ca
	 SHA1: 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31
	 SHA256: 6D:C4:71:72:E0:1C:BC:B0:BF:62:58:0D:89:5F:E2:B8:AC:9A:D4:F8:73:80:1E:0C:10:B9:C8:37:D2:1E:B1:77
Alias name: entrustevca
	 SHA1: B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9
	 SHA256: 73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C
Alias name: entrustnetpremium2048secureserverca
	 SHA1: 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31
	 SHA256: 6D:C4:71:72:E0:1C:BC:B0:BF:62:58:0D:89:5F:E2:B8:AC:9A:D4:F8:73:80:1E:0C:10:B9:C8:37:D2:1E:B1:77
Alias name: entrustrootcag2
	 SHA1: 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4
	 SHA256: 43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39
Alias name: entrustrootcertificationauthority
	 SHA1: B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9
	 SHA256: 73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C
Alias name: entrustrootcertificationauthorityec1
	 SHA1: 20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47
	 SHA256: 02:ED:0E:B2:8C:14:DA:45:16:5C:56:67:91:70:0D:64:51:D7:FB:56:F0:B2:AB:1D:3B:8E:B0:70:E5:6E:DF:F5
Alias name: entrustrootcertificationauthorityg2
	 SHA1: 8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4
	 SHA256: 43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39
Alias name: entrustrootcertificationauthorityg4
	 SHA1: 14:88:4E:86:26:37:B0:26:AF:59:62:5C:40:77:EC:35:29:BA:96:01
	 SHA256: DB:35:17:D1:F6:73:2A:2D:5A:B9:7C:53:3E:C7:07:79:EE:32:70:A6:2F:B4:AC:42:38:37:24:60:E6:F0:1E:88
Alias name: epkirootcertificationauthority
	 SHA1: 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0
	 SHA256: C0:A6:F4:DC:63:A2:4B:FD:CF:54:EF:2A:6A:08:2A:0A:72:DE:35:80:3E:2F:F5:FF:52:7A:E5:D8:72:06:DF:D5
Alias name: equifaxsecureebusinessca1
	 SHA1: AE:E6:3D:70:E3:76:FB:C7:3A:EB:B0:A1:C1:D4:C4:7A:A7:40:B3:F4
	 SHA256: 2E:3A:2B:B5:11:25:05:83:6C:A8:96:8B:E2:CB:37:27:CE:9B:56:84:5C:6E:E9:8E:91:85:10:4A:FB:9A:F5:96
Alias name: equifaxsecureglobalebusinessca1
	 SHA1: 3A:74:CB:7A:47:DB:70:DE:89:1F:24:35:98:64:B8:2D:82:BD:1A:36
	 SHA256: 86:AB:5A:65:71:D3:32:9A:BC:D2:E4:E6:37:66:8B:A8:9C:73:1E:C2:93:B6:CB:A6:0F:71:63:40:A0:91:CE:AE
Alias name: eszignorootca2017
	 SHA1: 89:D4:83:03:4F:9E:9A:48:80:5F:72:37:D4:A9:A6:EF:CB:7C:1F:D1
	 SHA256: BE:B0:0B:30:83:9B:9B:C3:2C:32:E4:44:79:05:95:06:41:F2:64:21:B1:5E:D0:89:19:8B:51:8A:E2:EA:1B:99
Alias name: etugracertificationauthority
	 SHA1: 51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39
	 SHA256: B0:BF:D5:2B:B0:D7:D9:BD:92:BF:5D:4D:C1:3D:A2:55:C0:2C:54:2F:37:83:65:EA:89:39:11:F5:5E:55:F2:3C
Alias name: gd-class2-root.pem
	 SHA1: 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4
	 SHA256: C3:84:6B:F2:4B:9E:93:CA:64:27:4C:0E:C6:7C:1E:CC:5E:02:4F:FC:AC:D2:D7:40:19:35:0E:81:FE:54:6A:E4
Alias name: gd_bundle-g2.pem
	 SHA1: 27:AC:93:69:FA:F2:52:07:BB:26:27:CE:FA:CC:BE:4E:F9:C3:19:B8
	 SHA256: 97:3A:41:27:6F:FD:01:E0:27:A2:AA:D4:9E:34:C3:78:46:D3:E9:76:FF:6A:62:0B:67:12:E3:38:32:04:1A:A6
Alias name: gdcatrustauthr5root
	 SHA1: 0F:36:38:5B:81:1A:25:C3:9B:31:4E:83:CA:E9:34:66:70:CC:74:B4
	 SHA256: BF:FF:8F:D0:44:33:48:7D:6A:8A:A6:0C:1A:29:76:7A:9F:C2:BB:B0:5E:42:0F:71:3A:13:B9:92:89:1D:38:93
Alias name: gdroot-g2.pem
	 SHA1: 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B
	 SHA256: 45:14:0B:32:47:EB:9C:C8:C5:B4:F0:D7:B5:30:91:F7:32:92:08:9E:6E:5A:63:E2:74:9D:D3:AC:A9:19:8E:DA
Alias name: geotrustglobalca
	 SHA1: DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12
	 SHA256: FF:85:6A:2D:25:1D:CD:88:D3:66:56:F4:50:12:67:98:CF:AB:AA:DE:40:79:9C:72:2D:E4:D2:B5:DB:36:A7:3A
Alias name: geotrustprimaryca
	 SHA1: 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96
	 SHA256: 37:D5:10:06:C5:12:EA:AB:62:64:21:F1:EC:8C:92:01:3F:C5:F8:2A:E9:8E:E5:33:EB:46:19:B8:DE:B4:D0:6C
Alias name: geotrustprimarycag2
	 SHA1: 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0
	 SHA256: 5E:DB:7A:C4:3B:82:A0:6A:87:61:E8:D7:BE:49:79:EB:F2:61:1F:7D:D7:9B:F9:1C:1C:6B:56:6A:21:9E:D7:66
Alias name: geotrustprimarycag3
	 SHA1: 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD
	 SHA256: B4:78:B8:12:25:0D:F8:78:63:5C:2A:A7:EC:7D:15:5E:AA:62:5E:E8:29:16:E2:CD:29:43:61:88:6C:D1:FB:D4
Alias name: geotrustprimarycertificationauthority
	 SHA1: 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96
	 SHA256: 37:D5:10:06:C5:12:EA:AB:62:64:21:F1:EC:8C:92:01:3F:C5:F8:2A:E9:8E:E5:33:EB:46:19:B8:DE:B4:D0:6C
Alias name: geotrustprimarycertificationauthorityg2
	 SHA1: 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0
	 SHA256: 5E:DB:7A:C4:3B:82:A0:6A:87:61:E8:D7:BE:49:79:EB:F2:61:1F:7D:D7:9B:F9:1C:1C:6B:56:6A:21:9E:D7:66
Alias name: geotrustprimarycertificationauthorityg3
	 SHA1: 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD
	 SHA256: B4:78:B8:12:25:0D:F8:78:63:5C:2A:A7:EC:7D:15:5E:AA:62:5E:E8:29:16:E2:CD:29:43:61:88:6C:D1:FB:D4
Alias name: geotrustuniversalca
	 SHA1: E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79
	 SHA256: A0:45:9B:9F:63:B2:25:59:F5:FA:5D:4C:6D:B3:F9:F7:2F:F1:93:42:03:35:78:F0:73:BF:1D:1B:46:CB:B9:12
Alias name: geotrustuniversalca2
	 SHA1: 37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79
	 SHA256: A0:23:4F:3B:C8:52:7C:A5:62:8E:EC:81:AD:5D:69:89:5D:A5:68:0D:C9:1D:1C:B8:47:7F:33:F8:78:B9:5B:0B
Alias name: globalchambersignroot2008
	 SHA1: 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C
	 SHA256: 13:63:35:43:93:34:A7:69:80:16:A0:D3:24:DE:72:28:4E:07:9D:7B:52:20:BB:8F:BD:74:78:16:EE:BE:BA:CA
Alias name: globalsignca
	 SHA1: B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C
	 SHA256: EB:D4:10:40:E4:BB:3E:C7:42:C9:E3:81:D3:1E:F2:A4:1A:48:B6:68:5C:96:E7:CE:F3:C1:DF:6C:D4:33:1C:99
Alias name: globalsigneccrootcar4
	 SHA1: 69:69:56:2E:40:80:F4:24:A1:E7:19:9F:14:BA:F3:EE:58:AB:6A:BB
	 SHA256: BE:C9:49:11:C2:95:56:76:DB:6C:0A:55:09:86:D7:6E:3B:A0:05:66:7C:44:2C:97:62:B4:FB:B7:73:DE:22:8C
Alias name: globalsigneccrootcar5
	 SHA1: 1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46:3A:1B:69:AA
	 SHA256: 17:9F:BC:14:8A:3D:D0:0F:D2:4E:A1:34:58:CC:43:BF:A7:F5:9C:81:82:D7:83:A5:13:F6:EB:EC:10:0C:89:24
Alias name: globalsignr2ca
	 SHA1: 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE
	 SHA256: CA:42:DD:41:74:5F:D0:B8:1E:B9:02:36:2C:F9:D8:BF:71:9D:A1:BD:1B:1E:FC:94:6F:5B:4C:99:F4:2C:1B:9E
Alias name: globalsignr3ca
	 SHA1: D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD
	 SHA256: CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B
Alias name: globalsignrootca
	 SHA1: B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C
	 SHA256: EB:D4:10:40:E4:BB:3E:C7:42:C9:E3:81:D3:1E:F2:A4:1A:48:B6:68:5C:96:E7:CE:F3:C1:DF:6C:D4:33:1C:99
Alias name: globalsignrootcar2
	 SHA1: 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE
	 SHA256: CA:42:DD:41:74:5F:D0:B8:1E:B9:02:36:2C:F9:D8:BF:71:9D:A1:BD:1B:1E:FC:94:6F:5B:4C:99:F4:2C:1B:9E
Alias name: globalsignrootcar3
	 SHA1: D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD
	 SHA256: CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B
Alias name: globalsignrootcar6
	 SHA1: 80:94:64:0E:B5:A7:A1:CA:11:9C:1F:DD:D5:9F:81:02:63:A7:FB:D1
	 SHA256: 2C:AB:EA:FE:37:D0:6C:A2:2A:BA:73:91:C0:03:3D:25:98:29:52:C4:53:64:73:49:76:3A:3A:B5:AD:6C:CF:69
Alias name: godaddyclass2ca
	 SHA1: 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4
	 SHA256: C3:84:6B:F2:4B:9E:93:CA:64:27:4C:0E:C6:7C:1E:CC:5E:02:4F:FC:AC:D2:D7:40:19:35:0E:81:FE:54:6A:E4
Alias name: godaddyrootcertificateauthorityg2
	 SHA1: 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B
	 SHA256: 45:14:0B:32:47:EB:9C:C8:C5:B4:F0:D7:B5:30:91:F7:32:92:08:9E:6E:5A:63:E2:74:9D:D3:AC:A9:19:8E:DA
Alias name: godaddyrootg2ca
	 SHA1: 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B
	 SHA256: 45:14:0B:32:47:EB:9C:C8:C5:B4:F0:D7:B5:30:91:F7:32:92:08:9E:6E:5A:63:E2:74:9D:D3:AC:A9:19:8E:DA
Alias name: gtsrootr1
	 SHA1: E1:C9:50:E6:EF:22:F8:4C:56:45:72:8B:92:20:60:D7:D5:A7:A3:E8
	 SHA256: 2A:57:54:71:E3:13:40:BC:21:58:1C:BD:2C:F1:3E:15:84:63:20:3E:CE:94:BC:F9:D3:CC:19:6B:F0:9A:54:72
Alias name: gtsrootr2
	 SHA1: D2:73:96:2A:2A:5E:39:9F:73:3F:E1:C7:1E:64:3F:03:38:34:FC:4D
	 SHA256: C4:5D:7B:B0:8E:6D:67:E6:2E:42:35:11:0B:56:4E:5F:78:FD:92:EF:05:8C:84:0A:EA:4E:64:55:D7:58:5C:60
Alias name: gtsrootr3
	 SHA1: 30:D4:24:6F:07:FF:DB:91:89:8A:0B:E9:49:66:11:EB:8C:5E:46:E5
	 SHA256: 15:D5:B8:77:46:19:EA:7D:54:CE:1C:A6:D0:B0:C4:03:E0:37:A9:17:F1:31:E8:A0:4E:1E:6B:7A:71:BA:BC:E5
Alias name: gtsrootr4
	 SHA1: 2A:1D:60:27:D9:4A:B1:0A:1C:4D:91:5C:CD:33:A0:CB:3E:2D:54:CB
	 SHA256: 71:CC:A5:39:1F:9E:79:4B:04:80:25:30:B3:63:E1:21:DA:8A:30:43:BB:26:66:2F:EA:4D:CA:7F:C9:51:A4:BD
Alias name: hellenicacademicandresearchinstitutionseccrootca2015
	 SHA1: 9F:F1:71:8D:92:D5:9A:F3:7D:74:97:B4:BC:6F:84:68:0B:BA:B6:66
	 SHA256: 44:B5:45:AA:8A:25:E6:5A:73:CA:15:DC:27:FC:36:D2:4C:1C:B9:95:3A:06:65:39:B1:15:82:DC:48:7B:48:33
Alias name: hellenicacademicandresearchinstitutionsrootca2011
	 SHA1: FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D
	 SHA256: BC:10:4F:15:A4:8B:E7:09:DC:A5:42:A7:E1:D4:B9:DF:6F:05:45:27:E8:02:EA:A9:2D:59:54:44:25:8A:FE:71
Alias name: hellenicacademicandresearchinstitutionsrootca2015
	 SHA1: 01:0C:06:95:A6:98:19:14:FF:BF:5F:C6:B0:B6:95:EA:29:E9:12:A6
	 SHA256: A0:40:92:9A:02:CE:53:B4:AC:F4:F2:FF:C6:98:1C:E4:49:6F:75:5E:6D:45:FE:0B:2A:69:2B:CD:52:52:3F:36
Alias name: hongkongpostrootca1
	 SHA1: D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58
	 SHA256: F9:E6:7D:33:6C:51:00:2A:C0:54:C6:32:02:2D:66:DD:A2:E7:E3:FF:F1:0A:D0:61:ED:31:D8:BB:B4:10:CF:B2
Alias name: hongkongpostrootca3
	 SHA1: 58:A2:D0:EC:20:52:81:5B:C1:F3:F8:64:02:24:4E:C2:8E:02:4B:02
	 SHA256: 5A:2F:C0:3F:0C:83:B0:90:BB:FA:40:60:4B:09:88:44:6C:76:36:18:3D:F9:84:6E:17:10:1A:44:7F:B8:EF:D6
Alias name: identrustcommercialrootca1
	 SHA1: DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25
	 SHA256: 5D:56:49:9B:E4:D2:E0:8B:CF:CA:D0:8A:3E:38:72:3D:50:50:3B:DE:70:69:48:E4:2F:55:60:30:19:E5:28:AE
Alias name: identrustpublicsectorrootca1
	 SHA1: BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD
	 SHA256: 30:D0:89:5A:9A:44:8A:26:20:91:63:55:22:D1:F5:20:10:B5:86:7A:CA:E1:2C:78:EF:95:8F:D4:F4:38:9F:2F
Alias name: isrgrootx1
	 SHA1: CA:BD:2A:79:A1:07:6A:31:F2:1D:25:36:35:CB:03:9D:43:29:A5:E8
	 SHA256: 96:BC:EC:06:26:49:76:F3:74:60:77:9A:CF:28:C5:A7:CF:E8:A3:C0:AA:E1:1A:8F:FC:EE:05:C0:BD:DF:08:C6
Alias name: izenpecom
	 SHA1: 2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19
	 SHA256: 25:30:CC:8E:98:32:15:02:BA:D9:6F:9B:1F:BA:1B:09:9E:2D:29:9E:0F:45:48:BB:91:4F:36:3B:C0:D4:53:1F
Alias name: keynectisrootca
	 SHA1: 9C:61:5C:4D:4D:85:10:3A:53:26:C2:4D:BA:EA:E4:A2:D2:D5:CC:97
	 SHA256: 42:10:F1:99:49:9A:9A:C3:3C:8D:E0:2B:A6:DB:AA:14:40:8B:DD:8A:6E:32:46:89:C1:92:2D:06:97:15:A3:32
Alias name: microseceszignorootca2009
	 SHA1: 89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E
	 SHA256: 3C:5F:81:FE:A5:FA:B8:2C:64:BF:A2:EA:EC:AF:CD:E8:E0:77:FC:86:20:A7:CA:E5:37:16:3D:F3:6E:DB:F3:78
Alias name: mozillacert0.pem
	 SHA1: 97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74
	 SHA256: A5:31:25:18:8D:21:10:AA:96:4B:02:C7:B7:C6:DA:32:03:17:08:94:E5:FB:71:FF:FB:66:67:D5:E6:81:0A:36
Alias name: mozillacert1.pem
	 SHA1: 23:E5:94:94:51:95:F2:41:48:03:B4:D5:64:D2:A3:A3:F5:D8:8B:8C
	 SHA256: B4:41:0B:73:E2:E6:EA:CA:47:FB:C4:2F:8F:A4:01:8A:F4:38:1D:C5:4C:FA:A8:44:50:46:1E:ED:09:45:4D:E9
Alias name: mozillacert10.pem
	 SHA1: 5F:3A:FC:0A:8B:64:F6:86:67:34:74:DF:7E:A9:A2:FE:F9:FA:7A:51
	 SHA256: 21:DB:20:12:36:60:BB:2E:D4:18:20:5D:A1:1E:E7:A8:5A:65:E2:BC:6E:55:B5:AF:7E:78:99:C8:A2:66:D9:2E
Alias name: mozillacert100.pem
	 SHA1: 58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0
	 SHA256: 49:E7:A4:42:AC:F0:EA:62:87:05:00:54:B5:25:64:B6:50:E4:F4:9E:42:E3:48:D6:AA:38:E0:39:E9:57:B1:C1
Alias name: mozillacert101.pem
	 SHA1: 99:A6:9B:E6:1A:FE:88:6B:4D:2B:82:00:7C:B8:54:FC:31:7E:15:39
	 SHA256: 62:F2:40:27:8C:56:4C:4D:D8:BF:7D:9D:4F:6F:36:6E:A8:94:D2:2F:5F:34:D9:89:A9:83:AC:EC:2F:FF:ED:50
Alias name: mozillacert102.pem
	 SHA1: 96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83
	 SHA256: EE:C5:49:6B:98:8C:E9:86:25:B9:34:09:2E:EC:29:08:BE:D0:B0:F3:16:C2:D4:73:0C:84:EA:F1:F3:D3:48:81
Alias name: mozillacert103.pem
	 SHA1: 70:C1:8D:74:B4:28:81:0A:E4:FD:A5:75:D7:01:9F:99:B0:3D:50:74
	 SHA256: 3C:FC:3C:14:D1:F6:84:FF:17:E3:8C:43:CA:44:0C:00:B9:67:EC:93:3E:8B:FE:06:4C:A1:D7:2C:90:F2:AD:B0
Alias name: mozillacert104.pem
	 SHA1: 4F:99:AA:93:FB:2B:D1:37:26:A1:99:4A:CE:7F:F0:05:F2:93:5D:1E
	 SHA256: 1C:01:C6:F4:DB:B2:FE:FC:22:55:8B:2B:CA:32:56:3F:49:84:4A:CF:C3:2B:7B:E4:B0:FF:59:9F:9E:8C:7A:F7
Alias name: mozillacert105.pem
	 SHA1: 77:47:4F:C6:30:E4:0F:4C:47:64:3F:84:BA:B8:C6:95:4A:8A:41:EC
	 SHA256: F0:9B:12:2C:71:14:F4:A0:9B:D4:EA:4F:4A:99:D5:58:B4:6E:4C:25:CD:81:14:0D:29:C0:56:13:91:4C:38:41
Alias name: mozillacert106.pem
	 SHA1: E7:A1:90:29:D3:D5:52:DC:0D:0F:C6:92:D3:EA:88:0D:15:2E:1A:6B
	 SHA256: D9:5F:EA:3C:A4:EE:DC:E7:4C:D7:6E:75:FC:6D:1F:F6:2C:44:1F:0F:A8:BC:77:F0:34:B1:9E:5D:B2:58:01:5D
Alias name: mozillacert107.pem
	 SHA1: 8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6
	 SHA256: F9:6F:23:F4:C3:E7:9C:07:7A:46:98:8D:5A:F5:90:06:76:A0:F0:39:CB:64:5D:D1:75:49:B2:16:C8:24:40:CE
Alias name: mozillacert108.pem
	 SHA1: B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C
	 SHA256: EB:D4:10:40:E4:BB:3E:C7:42:C9:E3:81:D3:1E:F2:A4:1A:48:B6:68:5C:96:E7:CE:F3:C1:DF:6C:D4:33:1C:99
Alias name: mozillacert109.pem
	 SHA1: B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71
	 SHA256: E2:3D:4A:03:6D:7B:70:E9:F5:95:B1:42:20:79:D2:B9:1E:DF:BB:1F:B6:51:A0:63:3E:AA:8A:9D:C5:F8:07:03
Alias name: mozillacert11.pem
	 SHA1: 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43
	 SHA256: 3E:90:99:B5:01:5E:8F:48:6C:00:BC:EA:9D:11:1E:E7:21:FA:BA:35:5A:89:BC:F1:DF:69:56:1E:3D:C6:32:5C
Alias name: mozillacert110.pem
	 SHA1: 93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17
	 SHA256: 9A:6E:C0:12:E1:A7:DA:9D:BE:34:19:4D:47:8A:D7:C0:DB:18:22:FB:07:1D:F1:29:81:49:6E:D1:04:38:41:13
Alias name: mozillacert111.pem
	 SHA1: 9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65
	 SHA256: 59:76:90:07:F7:68:5D:0F:CD:50:87:2F:9F:95:D5:75:5A:5B:2B:45:7D:81:F3:69:2B:61:0A:98:67:2F:0E:1B
Alias name: mozillacert112.pem
	 SHA1: 43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37
	 SHA256: DD:69:36:FE:21:F8:F0:77:C1:23:A1:A5:21:C1:22:24:F7:22:55:B7:3E:03:A7:26:06:93:E8:A2:4B:0F:A3:89
Alias name: mozillacert113.pem
	 SHA1: 50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31
	 SHA256: 6D:C4:71:72:E0:1C:BC:B0:BF:62:58:0D:89:5F:E2:B8:AC:9A:D4:F8:73:80:1E:0C:10:B9:C8:37:D2:1E:B1:77
Alias name: mozillacert114.pem
	 SHA1: 51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39
	 SHA256: B0:BF:D5:2B:B0:D7:D9:BD:92:BF:5D:4D:C1:3D:A2:55:C0:2C:54:2F:37:83:65:EA:89:39:11:F5:5E:55:F2:3C
Alias name: mozillacert115.pem
	 SHA1: 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9
	 SHA256: 91:E2:F5:78:8D:58:10:EB:A7:BA:58:73:7D:E1:54:8A:8E:CA:CD:01:45:98:BC:0B:14:3E:04:1B:17:05:25:52
Alias name: mozillacert116.pem
	 SHA1: 2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21
	 SHA256: F3:56:BE:A2:44:B7:A9:1E:B3:5D:53:CA:9A:D7:86:4A:CE:01:8E:2D:35:D5:F8:F9:6D:DF:68:A6:F4:1A:A4:74
Alias name: mozillacert117.pem
	 SHA1: D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74
	 SHA256: 16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB
Alias name: mozillacert118.pem
	 SHA1: 7E:78:4A:10:1C:82:65:CC:2D:E1:F1:6D:47:B4:40:CA:D9:0A:19:45
	 SHA256: 5F:0B:62:EA:B5:E3:53:EA:65:21:65:16:58:FB:B6:53:59:F4:43:28:0A:4A:FB:D1:04:D7:7D:10:F9:F0:4C:07
Alias name: mozillacert119.pem
	 SHA1: 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE
	 SHA256: CA:42:DD:41:74:5F:D0:B8:1E:B9:02:36:2C:F9:D8:BF:71:9D:A1:BD:1B:1E:FC:94:6F:5B:4C:99:F4:2C:1B:9E
Alias name: mozillacert12.pem
	 SHA1: A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36
	 SHA256: 43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61
Alias name: mozillacert120.pem
	 SHA1: DA:40:18:8B:91:89:A3:ED:EE:AE:DA:97:FE:2F:9D:F5:B7:D1:8A:41
	 SHA256: CF:56:FF:46:A4:A1:86:10:9D:D9:65:84:B5:EE:B5:8A:51:0C:42:75:B0:E5:F9:4F:40:BB:AE:86:5E:19:F6:73
Alias name: mozillacert121.pem
	 SHA1: CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D
	 SHA256: 8C:72:09:27:9A:C0:4E:27:5E:16:D0:7F:D3:B7:75:E8:01:54:B5:96:80:46:E3:1F:52:DD:25:76:63:24:E9:A7
Alias name: mozillacert122.pem
	 SHA1: 02:FA:F3:E2:91:43:54:68:60:78:57:69:4D:F5:E4:5B:68:85:18:68
	 SHA256: 68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2
Alias name: mozillacert123.pem
	 SHA1: 2A:B6:28:48:5E:78:FB:F3:AD:9E:79:10:DD:6B:DF:99:72:2C:96:E5
	 SHA256: 07:91:CA:07:49:B2:07:82:AA:D3:C7:D7:BD:0C:DF:C9:48:58:35:84:3E:B2:D7:99:60:09:CE:43:AB:6C:69:27
Alias name: mozillacert124.pem
	 SHA1: 4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF
	 SHA256: 80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16
Alias name: mozillacert125.pem
	 SHA1: B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9
	 SHA256: 73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C
Alias name: mozillacert126.pem
	 SHA1: 25:01:90:19:CF:FB:D9:99:1C:B7:68:25:74:8D:94:5F:30:93:95:42
	 SHA256: AF:8B:67:62:A1:E5:28:22:81:61:A9:5D:5C:55:9E:E2:66:27:8F:75:D7:9E:83:01:89:A5:03:50:6A:BD:6B:4C
Alias name: mozillacert127.pem
	 SHA1: DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12
	 SHA256: FF:85:6A:2D:25:1D:CD:88:D3:66:56:F4:50:12:67:98:CF:AB:AA:DE:40:79:9C:72:2D:E4:D2:B5:DB:36:A7:3A
Alias name: mozillacert128.pem
	 SHA1: A9:E9:78:08:14:37:58:88:F2:05:19:B0:6D:2B:0D:2B:60:16:90:7D
	 SHA256: CA:2D:82:A0:86:77:07:2F:8A:B6:76:4F:F0:35:67:6C:FE:3E:5E:32:5E:01:21:72:DF:3F:92:09:6D:B7:9B:85
Alias name: mozillacert129.pem
	 SHA1: E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79
	 SHA256: A0:45:9B:9F:63:B2:25:59:F5:FA:5D:4C:6D:B3:F9:F7:2F:F1:93:42:03:35:78:F0:73:BF:1D:1B:46:CB:B9:12
Alias name: mozillacert13.pem
	 SHA1: 06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91
	 SHA256: 6C:61:DA:C3:A2:DE:F0:31:50:6B:E0:36:D2:A6:FE:40:19:94:FB:D1:3D:F9:C8:D4:66:59:92:74:C4:46:EC:98
Alias name: mozillacert130.pem
	 SHA1: E5:DF:74:3C:B6:01:C4:9B:98:43:DC:AB:8C:E8:6A:81:10:9F:E4:8E
	 SHA256: F4:C1:49:55:1A:30:13:A3:5B:C7:BF:FE:17:A7:F3:44:9B:C1:AB:5B:5A:0A:E7:4B:06:C2:3B:90:00:4C:01:04
Alias name: mozillacert131.pem
	 SHA1: 37:9A:19:7B:41:85:45:35:0C:A6:03:69:F3:3C:2E:AF:47:4F:20:79
	 SHA256: A0:23:4F:3B:C8:52:7C:A5:62:8E:EC:81:AD:5D:69:89:5D:A5:68:0D:C9:1D:1C:B8:47:7F:33:F8:78:B9:5B:0B
Alias name: mozillacert132.pem
	 SHA1: 39:21:C1:15:C1:5D:0E:CA:5C:CB:5B:C4:F0:7D:21:D8:05:0B:56:6A
	 SHA256: 77:40:73:12:C6:3A:15:3D:5B:C0:0B:4E:51:75:9C:DF:DA:C2:37:DC:2A:33:B6:79:46:E9:8E:9B:FA:68:0A:E3
Alias name: mozillacert133.pem
	 SHA1: 85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84
	 SHA256: 7D:3B:46:5A:60:14:E5:26:C0:AF:FC:EE:21:27:D2:31:17:27:AD:81:1C:26:84:2D:00:6A:F3:73:06:CC:80:BD
Alias name: mozillacert134.pem
	 SHA1: 70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62
	 SHA256: 69:FA:C9:BD:55:FB:0A:C7:8D:53:BB:EE:5C:F1:D5:97:98:9F:D0:AA:AB:20:A2:51:51:BD:F1:73:3E:E7:D1:22
Alias name: mozillacert135.pem
	 SHA1: 62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18
	 SHA256: D8:E0:FE:BC:1D:B2:E3:8D:00:94:0F:37:D2:7D:41:34:4D:99:3E:73:4B:99:D5:65:6D:97:78:D4:D8:14:36:24
Alias name: mozillacert136.pem
	 SHA1: D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49
	 SHA256: D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
Alias name: mozillacert137.pem
	 SHA1: 4A:65:D5:F4:1D:EF:39:B8:B8:90:4A:4A:D3:64:81:33:CF:C7:A1:D1
	 SHA256: BD:81:CE:3B:4F:65:91:D1:1A:67:B5:FC:7A:47:FD:EF:25:52:1B:F9:AA:4E:18:B9:E3:DF:2E:34:A7:80:3B:E8
Alias name: mozillacert138.pem
	 SHA1: E1:9F:E3:0E:8B:84:60:9E:80:9B:17:0D:72:A8:C5:BA:6E:14:09:BD
	 SHA256: 3F:06:E5:56:81:D4:96:F5:BE:16:9E:B5:38:9F:9F:2B:8F:F6:1E:17:08:DF:68:81:72:48:49:CD:5D:27:CB:69
Alias name: mozillacert139.pem
	 SHA1: DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9
	 SHA256: A4:5E:DE:3B:BB:F0:9C:8A:E1:5C:72:EF:C0:72:68:D6:93:A2:1C:99:6F:D5:1E:67:CA:07:94:60:FD:6D:88:73
Alias name: mozillacert14.pem
	 SHA1: 5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25
	 SHA256: 74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF
Alias name: mozillacert140.pem
	 SHA1: CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7
	 SHA256: 85:A0:DD:7D:D7:20:AD:B7:FF:05:F8:3D:54:2B:20:9D:C7:FF:45:28:F7:D6:77:B1:83:89:FE:A5:E5:C4:9E:86
Alias name: mozillacert141.pem
	 SHA1: 31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6
	 SHA256: 58:D0:17:27:9C:D4:DC:63:AB:DD:B1:96:A6:C9:90:6C:30:C4:E0:87:83:EA:E8:C1:60:99:54:D6:93:55:59:6B
Alias name: mozillacert142.pem
	 SHA1: 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85
	 SHA256: 18:F1:FC:7F:20:5D:F8:AD:DD:EB:7F:E0:07:DD:57:E3:AF:37:5A:9C:4D:8D:73:54:6B:F4:F1:FE:D1:E1:8D:35
Alias name: mozillacert143.pem
	 SHA1: 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7
	 SHA256: E7:5E:72:ED:9F:56:0E:EC:6E:B4:80:00:73:A4:3F:C3:AD:19:19:5A:39:22:82:01:78:95:97:4A:99:02:6B:6C
Alias name: mozillacert144.pem
	 SHA1: 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27
	 SHA256: 79:08:B4:03:14:C1:38:10:0B:51:8D:07:35:80:7F:FB:FC:F8:51:8A:00:95:33:71:05:BA:38:6B:15:3D:D9:27
Alias name: mozillacert145.pem
	 SHA1: 10:1D:FA:3F:D5:0B:CB:BB:9B:B5:60:0C:19:55:A4:1A:F4:73:3A:04
	 SHA256: D4:1D:82:9E:8C:16:59:82:2A:F9:3F:CE:62:BF:FC:DE:26:4F:C8:4E:8B:95:0C:5F:F2:75:D0:52:35:46:95:A3
Alias name: mozillacert146.pem
	 SHA1: 21:FC:BD:8E:7F:6C:AF:05:1B:D1:B3:43:EC:A8:E7:61:47:F2:0F:8A
	 SHA256: 48:98:C6:88:8C:0C:FF:B0:D3:E3:1A:CA:8A:37:D4:E3:51:5F:F7:46:D0:26:35:D8:66:46:CF:A0:A3:18:5A:E7
Alias name: mozillacert147.pem
	 SHA1: 58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4
	 SHA256: 85:FB:2F:91:DD:12:27:5A:01:45:B6:36:53:4F:84:02:4A:D6:8B:69:B8:EE:88:68:4F:F7:11:37:58:05:B3:48
Alias name: mozillacert148.pem
	 SHA1: 04:83:ED:33:99:AC:36:08:05:87:22:ED:BC:5E:46:00:E3:BE:F9:D7
	 SHA256: 6E:A5:47:41:D0:04:66:7E:ED:1B:48:16:63:4A:A3:A7:9E:6E:4B:96:95:0F:82:79:DA:FC:8D:9B:D8:81:21:37
Alias name: mozillacert149.pem
	 SHA1: 6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1
	 SHA256: 0C:25:8A:12:A5:67:4A:EF:25:F2:8B:A7:DC:FA:EC:EE:A3:48:E5:41:E6:F5:CC:4E:E6:3B:71:B3:61:60:6A:C3
Alias name: mozillacert15.pem
	 SHA1: 74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB
	 SHA256: 0F:99:3C:8A:EF:97:BA:AF:56:87:14:0E:D5:9A:D1:82:1B:B4:AF:AC:F0:AA:9A:58:B5:D5:7A:33:8A:3A:FB:CB
Alias name: mozillacert150.pem
	 SHA1: 33:9B:6B:14:50:24:9B:55:7A:01:87:72:84:D9:E0:2F:C3:D2:D8:E9
	 SHA256: EF:3C:B4:17:FC:8E:BF:6F:97:87:6C:9E:4E:CE:39:DE:1E:A5:FE:64:91:41:D1:02:8B:7D:11:C0:B2:29:8C:ED
Alias name: mozillacert151.pem
	 SHA1: AC:ED:5F:65:53:FD:25:CE:01:5F:1F:7A:48:3B:6A:74:9F:61:78:C6
	 SHA256: 7F:12:CD:5F:7E:5E:29:0E:C7:D8:51:79:D5:B7:2C:20:A5:BE:75:08:FF:DB:5B:F8:1A:B9:68:4A:7F:C9:F6:67
Alias name: mozillacert16.pem
	 SHA1: DA:C9:02:4F:54:D8:F6:DF:94:93:5F:B1:73:26:38:CA:6A:D7:7C:13
	 SHA256: 06:87:26:03:31:A7:24:03:D9:09:F1:05:E6:9B:CF:0D:32:E1:BD:24:93:FF:C6:D9:20:6D:11:BC:D6:77:07:39
Alias name: mozillacert17.pem
	 SHA1: 40:54:DA:6F:1C:3F:40:74:AC:ED:0F:EC:CD:DB:79:D1:53:FB:90:1D
	 SHA256: 76:7C:95:5A:76:41:2C:89:AF:68:8E:90:A1:C7:0F:55:6C:FD:6B:60:25:DB:EA:10:41:6D:7E:B6:83:1F:8C:40
Alias name: mozillacert18.pem
	 SHA1: 79:98:A3:08:E1:4D:65:85:E6:C2:1E:15:3A:71:9F:BA:5A:D3:4A:D9
	 SHA256: 44:04:E3:3B:5E:14:0D:CF:99:80:51:FD:FC:80:28:C7:C8:16:15:C5:EE:73:7B:11:1B:58:82:33:A9:B5:35:A0
Alias name: mozillacert19.pem
	 SHA1: B4:35:D4:E1:11:9D:1C:66:90:A7:49:EB:B3:94:BD:63:7B:A7:82:B7
	 SHA256: C4:70:CF:54:7E:23:02:B9:77:FB:29:DD:71:A8:9A:7B:6C:1F:60:77:7B:03:29:F5:60:17:F3:28:BF:4F:6B:E6
Alias name: mozillacert2.pem
	 SHA1: 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A
	 SHA256: 69:DD:D7:EA:90:BB:57:C9:3E:13:5D:C8:5E:A6:FC:D5:48:0B:60:32:39:BD:C4:54:FC:75:8B:2A:26:CF:7F:79
Alias name: mozillacert20.pem
	 SHA1: D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61
	 SHA256: 62:DD:0B:E9:B9:F5:0A:16:3E:A0:F8:E7:5C:05:3B:1E:CA:57:EA:55:C8:68:8F:64:7C:68:81:F2:C8:35:7B:95
Alias name: mozillacert21.pem
	 SHA1: 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB
	 SHA256: BE:6C:4D:A2:BB:B9:BA:59:B6:F3:93:97:68:37:42:46:C3:C0:05:99:3F:A9:8F:02:0D:1D:ED:BE:D4:8A:81:D5
Alias name: mozillacert22.pem
	 SHA1: 32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96
	 SHA256: 37:D5:10:06:C5:12:EA:AB:62:64:21:F1:EC:8C:92:01:3F:C5:F8:2A:E9:8E:E5:33:EB:46:19:B8:DE:B4:D0:6C
Alias name: mozillacert23.pem
	 SHA1: 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81
	 SHA256: 8D:72:2F:81:A9:C1:13:C0:79:1D:F1:36:A2:96:6D:B2:6C:95:0A:97:1D:B4:6B:41:99:F4:EA:54:B7:8B:FB:9F
Alias name: mozillacert24.pem
	 SHA1: 59:AF:82:79:91:86:C7:B4:75:07:CB:CF:03:57:46:EB:04:DD:B7:16
	 SHA256: 66:8C:83:94:7D:A6:3B:72:4B:EC:E1:74:3C:31:A0:E6:AE:D0:DB:8E:C5:B3:1B:E3:77:BB:78:4F:91:B6:71:6F
Alias name: mozillacert25.pem
	 SHA1: 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5
	 SHA256: 9A:CF:AB:7E:43:C8:D8:80:D0:6B:26:2A:94:DE:EE:E4:B4:65:99:89:C3:D0:CA:F1:9B:AF:64:05:E4:1A:B7:DF
Alias name: mozillacert26.pem
	 SHA1: 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11
	 SHA256: F1:C1:B5:0A:E5:A2:0D:D8:03:0E:C9:F6:BC:24:82:3D:D3:67:B5:25:57:59:B4:E7:1B:61:FC:E9:F7:37:5D:73
Alias name: mozillacert27.pem
	 SHA1: 3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B
	 SHA256: 42:00:F5:04:3A:C8:59:0E:BB:52:7D:20:9E:D1:50:30:29:FB:CB:D4:1C:A1:B5:06:EC:27:F1:5A:DE:7D:AC:69
Alias name: mozillacert28.pem
	 SHA1: 66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B
	 SHA256: 0C:2C:D6:3D:F7:80:6F:A3:99:ED:E8:09:11:6B:57:5B:F8:79:89:F0:65:18:F9:80:8C:86:05:03:17:8B:AF:66
Alias name: mozillacert29.pem
	 SHA1: 74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE
	 SHA256: 15:F0:BA:00:A3:AC:7A:F3:AC:88:4C:07:2B:10:11:A0:77:BD:77:C0:97:F4:01:64:B2:F8:59:8A:BD:83:86:0C
Alias name: mozillacert3.pem
	 SHA1: 87:9F:4B:EE:05:DF:98:58:3B:E3:60:D6:33:E7:0D:3F:FE:98:71:AF
	 SHA256: 39:DF:7B:68:2B:7B:93:8F:84:71:54:81:CC:DE:8D:60:D8:F2:2E:C5:98:87:7D:0A:AA:C1:2B:59:18:2B:03:12
Alias name: mozillacert30.pem
	 SHA1: E7:B4:F6:9D:61:EC:90:69:DB:7E:90:A7:40:1A:3C:F4:7D:4F:E8:EE
	 SHA256: A7:12:72:AE:AA:A3:CF:E8:72:7F:7F:B3:9F:0F:B3:D1:E5:42:6E:90:60:B0:6E:E6:F1:3E:9A:3C:58:33:CD:43
Alias name: mozillacert31.pem
	 SHA1: 9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11
	 SHA256: 17:93:92:7A:06:14:54:97:89:AD:CE:2F:8F:34:F7:F0:B6:6D:0F:3A:E3:A3:B8:4D:21:EC:15:DB:BA:4F:AD:C7
Alias name: mozillacert32.pem
	 SHA1: 60:D6:89:74:B5:C2:65:9E:8A:0F:C1:88:7C:88:D2:46:69:1B:18:2C
	 SHA256: B9:BE:A7:86:0A:96:2E:A3:61:1D:AB:97:AB:6D:A3:E2:1C:10:68:B9:7D:55:57:5E:D0:E1:12:79:C1:1C:89:32
Alias name: mozillacert33.pem
	 SHA1: FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D
	 SHA256: A2:2D:BA:68:1E:97:37:6E:2D:39:7D:72:8A:AE:3A:9B:62:96:B9:FD:BA:60:BC:2E:11:F6:47:F2:C6:75:FB:37
Alias name: mozillacert34.pem
	 SHA1: 59:22:A1:E1:5A:EA:16:35:21:F8:98:39:6A:46:46:B0:44:1B:0F:A9
	 SHA256: 41:C9:23:86:6A:B4:CA:D6:B7:AD:57:80:81:58:2E:02:07:97:A6:CB:DF:4F:FF:78:CE:83:96:B3:89:37:D7:F5
Alias name: mozillacert35.pem
	 SHA1: 2A:C8:D5:8B:57:CE:BF:2F:49:AF:F2:FC:76:8F:51:14:62:90:7A:41
	 SHA256: 92:BF:51:19:AB:EC:CA:D0:B1:33:2D:C4:E1:D0:5F:BA:75:B5:67:90:44:EE:0C:A2:6E:93:1F:74:4F:2F:33:CF
Alias name: mozillacert36.pem
	 SHA1: 23:88:C9:D3:71:CC:9E:96:3D:FF:7D:3C:A7:CE:FC:D6:25:EC:19:0D
	 SHA256: 32:7A:3D:76:1A:BA:DE:A0:34:EB:99:84:06:27:5C:B1:A4:77:6E:FD:AE:2F:DF:6D:01:68:EA:1C:4F:55:67:D0
Alias name: mozillacert37.pem
	 SHA1: B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97
	 SHA256: E3:B6:A2:DB:2E:D7:CE:48:84:2F:7A:C5:32:41:C7:B7:1D:54:14:4B:FB:40:C1:1F:3F:1D:0B:42:F5:EE:A1:2D
Alias name: mozillacert38.pem
	 SHA1: CB:A1:C5:F8:B0:E3:5E:B8:B9:45:12:D3:F9:34:A2:E9:06:10:D3:36
	 SHA256: A6:C5:1E:0D:A5:CA:0A:93:09:D2:E4:C0:E4:0C:2A:F9:10:7A:AE:82:03:85:7F:E1:98:E3:E7:69:E3:43:08:5C
Alias name: mozillacert39.pem
	 SHA1: AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E
	 SHA256: E6:B8:F8:76:64:85:F8:07:AE:7F:8D:AC:16:70:46:1F:07:C0:A1:3E:EF:3A:1F:F7:17:53:8D:7A:BA:D3:91:B4
Alias name: mozillacert4.pem
	 SHA1: E3:92:51:2F:0A:CF:F5:05:DF:F6:DE:06:7F:75:37:E1:65:EA:57:4B
	 SHA256: 0B:5E:ED:4E:84:64:03:CF:55:E0:65:84:84:40:ED:2A:82:75:8B:F5:B9:AA:1F:25:3D:46:13:CF:A0:80:FF:3F
Alias name: mozillacert40.pem
	 SHA1: 80:25:EF:F4:6E:70:C8:D4:72:24:65:84:FE:40:3B:8A:8D:6A:DB:F5
	 SHA256: 8D:A0:84:FC:F9:9C:E0:77:22:F8:9B:32:05:93:98:06:FA:5C:B8:11:E1:C8:13:F6:A1:08:C7:D3:36:B3:40:8E
Alias name: mozillacert41.pem
	 SHA1: 6B:2F:34:AD:89:58:BE:62:FD:B0:6B:5C:CE:BB:9D:D9:4F:4E:39:F3
	 SHA256: EB:F3:C0:2A:87:89:B1:FB:7D:51:19:95:D6:63:B7:29:06:D9:13:CE:0D:5E:10:56:8A:8A:77:E2:58:61:67:E7
Alias name: mozillacert42.pem
	 SHA1: 85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF
	 SHA256: B6:19:1A:50:D0:C3:97:7F:7D:A9:9B:CD:AA:C8:6A:22:7D:AE:B9:67:9E:C7:0B:A3:B0:C9:D9:22:71:C1:70:D3
Alias name: mozillacert43.pem
	 SHA1: F9:CD:0E:2C:DA:76:24:C1:8F:BD:F0:F0:AB:B6:45:B8:F7:FE:D5:7A
	 SHA256: 50:79:41:C7:44:60:A0:B4:70:86:22:0D:4E:99:32:57:2A:B5:D1:B5:BB:CB:89:80:AB:1C:B1:76:51:A8:44:D2
Alias name: mozillacert44.pem
	 SHA1: 5F:43:E5:B1:BF:F8:78:8C:AC:1C:C7:CA:4A:9A:C6:22:2B:CC:34:C6
	 SHA256: 96:0A:DF:00:63:E9:63:56:75:0C:29:65:DD:0A:08:67:DA:0B:9C:BD:6E:77:71:4A:EA:FB:23:49:AB:39:3D:A3
Alias name: mozillacert45.pem
	 SHA1: 67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0
	 SHA256: C0:A6:F4:DC:63:A2:4B:FD:CF:54:EF:2A:6A:08:2A:0A:72:DE:35:80:3E:2F:F5:FF:52:7A:E5:D8:72:06:DF:D5
Alias name: mozillacert46.pem
	 SHA1: 40:9D:4B:D9:17:B5:5C:27:B6:9B:64:CB:98:22:44:0D:CD:09:B8:89
	 SHA256: EC:C3:E9:C3:40:75:03:BE:E0:91:AA:95:2F:41:34:8F:F8:8B:AA:86:3B:22:64:BE:FA:C8:07:90:15:74:E9:39
Alias name: mozillacert47.pem
	 SHA1: 1B:4B:39:61:26:27:6B:64:91:A2:68:6D:D7:02:43:21:2D:1F:1D:96
	 SHA256: E4:C7:34:30:D7:A5:B5:09:25:DF:43:37:0A:0D:21:6E:9A:79:B9:D6:DB:83:73:A0:C6:9E:B1:CC:31:C7:C5:2A
Alias name: mozillacert48.pem
	 SHA1: A0:A1:AB:90:C9:FC:84:7B:3B:12:61:E8:97:7D:5F:D3:22:61:D3:CC
	 SHA256: 0F:4E:9C:DD:26:4B:02:55:50:D1:70:80:63:40:21:4F:E9:44:34:C9:B0:2F:69:7E:C7:10:FC:5F:EA:FB:5E:38
Alias name: mozillacert49.pem
	 SHA1: 61:57:3A:11:DF:0E:D8:7E:D5:92:65:22:EA:D0:56:D7:44:B3:23:71
	 SHA256: B7:B1:2B:17:1F:82:1D:AA:99:0C:D0:FE:50:87:B1:28:44:8B:A8:E5:18:4F:84:C5:1E:02:B5:C8:FB:96:2B:24
Alias name: mozillacert5.pem
	 SHA1: B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6
	 SHA256: CE:CD:DC:90:50:99:D8:DA:DF:C5:B1:D2:09:B7:37:CB:E2:C1:8C:FB:2C:10:C0:FF:0B:CF:0D:32:86:FC:1A:A2
Alias name: mozillacert50.pem
	 SHA1: 8C:96:BA:EB:DD:2B:07:07:48:EE:30:32:66:A0:F3:98:6E:7C:AE:58
	 SHA256: 35:AE:5B:DD:D8:F7:AE:63:5C:FF:BA:56:82:A8:F0:0B:95:F4:84:62:C7:10:8E:E9:A0:E5:29:2B:07:4A:AF:B2
Alias name: mozillacert51.pem
	 SHA1: FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B
	 SHA256: EA:A9:62:C4:FA:4A:6B:AF:EB:E4:15:19:6D:35:1C:CD:88:8D:4F:53:F3:FA:8A:E6:D7:C4:66:A9:4E:60:42:BB
Alias name: mozillacert52.pem
	 SHA1: 8B:AF:4C:9B:1D:F0:2A:92:F7:DA:12:8E:B9:1B:AC:F4:98:60:4B:6F
	 SHA256: E2:83:93:77:3D:A8:45:A6:79:F2:08:0C:C7:FB:44:A3:B7:A1:C3:79:2C:B7:EB:77:29:FD:CB:6A:8D:99:AE:A7
Alias name: mozillacert53.pem
	 SHA1: 7F:8A:B0:CF:D0:51:87:6A:66:F3:36:0F:47:C8:8D:8C:D3:35:FC:74
	 SHA256: 2D:47:43:7D:E1:79:51:21:5A:12:F3:C5:8E:51:C7:29:A5:80:26:EF:1F:CC:0A:5F:B3:D9:DC:01:2F:60:0D:19
Alias name: mozillacert54.pem
	 SHA1: 03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD
	 SHA256: B4:78:B8:12:25:0D:F8:78:63:5C:2A:A7:EC:7D:15:5E:AA:62:5E:E8:29:16:E2:CD:29:43:61:88:6C:D1:FB:D4
Alias name: mozillacert55.pem
	 SHA1: AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12
	 SHA256: A4:31:0D:50:AF:18:A6:44:71:90:37:2A:86:AF:AF:8B:95:1F:FB:43:1D:83:7F:1E:56:88:B4:59:71:ED:15:57
Alias name: mozillacert56.pem
	 SHA1: F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2
	 SHA256: 4B:03:F4:58:07:AD:70:F2:1B:FC:2C:AE:71:C9:FD:E4:60:4C:06:4C:F5:FF:B6:86:BA:E5:DB:AA:D7:FD:D3:4C
Alias name: mozillacert57.pem
	 SHA1: D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58
	 SHA256: F9:E6:7D:33:6C:51:00:2A:C0:54:C6:32:02:2D:66:DD:A2:E7:E3:FF:F1:0A:D0:61:ED:31:D8:BB:B4:10:CF:B2
Alias name: mozillacert58.pem
	 SHA1: 8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0
	 SHA256: 5E:DB:7A:C4:3B:82:A0:6A:87:61:E8:D7:BE:49:79:EB:F2:61:1F:7D:D7:9B:F9:1C:1C:6B:56:6A:21:9E:D7:66
Alias name: mozillacert59.pem
	 SHA1: 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54
	 SHA256: 23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C
Alias name: mozillacert6.pem
	 SHA1: 27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4
	 SHA256: C3:84:6B:F2:4B:9E:93:CA:64:27:4C:0E:C6:7C:1E:CC:5E:02:4F:FC:AC:D2:D7:40:19:35:0E:81:FE:54:6A:E4
Alias name: mozillacert60.pem
	 SHA1: 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3
	 SHA256: BF:0F:EE:FB:9E:3A:58:1A:D5:F9:E9:DB:75:89:98:57:43:D2:61:08:5C:4D:31:4F:6F:5D:72:59:AA:42:16:12
Alias name: mozillacert61.pem
	 SHA1: E0:B4:32:2E:B2:F6:A5:68:B6:54:53:84:48:18:4A:50:36:87:43:84
	 SHA256: 03:95:0F:B4:9A:53:1F:3E:19:91:94:23:98:DF:A9:E0:EA:32:D7:BA:1C:DD:9B:C8:5D:B5:7E:D9:40:0B:43:4A
Alias name: mozillacert62.pem
	 SHA1: A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B
	 SHA256: A4:B6:B3:99:6F:C2:F3:06:B3:FD:86:81:BD:63:41:3D:8C:50:09:CC:4F:A3:29:C2:CC:F0:E2:FA:1B:14:03:05
Alias name: mozillacert63.pem
	 SHA1: 89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E
	 SHA256: 3C:5F:81:FE:A5:FA:B8:2C:64:BF:A2:EA:EC:AF:CD:E8:E0:77:FC:86:20:A7:CA:E5:37:16:3D:F3:6E:DB:F3:78
Alias name: mozillacert64.pem
	 SHA1: 62:7F:8D:78:27:65:63:99:D2:7D:7F:90:44:C9:FE:B3:F3:3E:FA:9A
	 SHA256: AB:70:36:36:5C:71:54:AA:29:C2:C2:9F:5D:41:91:16:3B:16:2A:22:25:01:13:57:D5:6D:07:FF:A7:BC:1F:72
Alias name: mozillacert65.pem
	 SHA1: 69:BD:8C:F4:9C:D3:00:FB:59:2E:17:93:CA:55:6A:F3:EC:AA:35:FB
	 SHA256: BC:23:F9:8A:31:3C:B9:2D:E3:BB:FC:3A:5A:9F:44:61:AC:39:49:4C:4A:E1:5A:9E:9D:F1:31:E9:9B:73:01:9A
Alias name: mozillacert66.pem
	 SHA1: DD:E1:D2:A9:01:80:2E:1D:87:5E:84:B3:80:7E:4B:B1:FD:99:41:34
	 SHA256: E6:09:07:84:65:A4:19:78:0C:B6:AC:4C:1C:0B:FB:46:53:D9:D9:CC:6E:B3:94:6E:B7:F3:D6:99:97:BA:D5:98
Alias name: mozillacert67.pem
	 SHA1: D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD
	 SHA256: CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B
Alias name: mozillacert68.pem
	 SHA1: AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA
	 SHA256: 04:04:80:28:BF:1F:28:64:D4:8F:9A:D4:D8:32:94:36:6A:82:88:56:55:3F:3B:14:30:3F:90:14:7F:5D:40:EF
Alias name: mozillacert69.pem
	 SHA1: 2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19
	 SHA256: 25:30:CC:8E:98:32:15:02:BA:D9:6F:9B:1F:BA:1B:09:9E:2D:29:9E:0F:45:48:BB:91:4F:36:3B:C0:D4:53:1F
Alias name: mozillacert7.pem
	 SHA1: AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A
	 SHA256: 14:65:FA:20:53:97:B8:76:FA:A6:F0:A9:95:8E:55:90:E4:0F:CC:7F:AA:4F:B7:C2:C8:67:75:21:FB:5F:B6:58
Alias name: mozillacert70.pem
	 SHA1: 78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C
	 SHA256: 06:3E:4A:FA:C4:91:DF:D3:32:F3:08:9B:85:42:E9:46:17:D8:93:D7:FE:94:4E:10:A7:93:7E:E2:9D:96:93:C0
Alias name: mozillacert71.pem
	 SHA1: 4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C
	 SHA256: 13:63:35:43:93:34:A7:69:80:16:A0:D3:24:DE:72:28:4E:07:9D:7B:52:20:BB:8F:BD:74:78:16:EE:BE:BA:CA
Alias name: mozillacert72.pem
	 SHA1: 47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B
	 SHA256: 45:14:0B:32:47:EB:9C:C8:C5:B4:F0:D7:B5:30:91:F7:32:92:08:9E:6E:5A:63:E2:74:9D:D3:AC:A9:19:8E:DA
Alias name: mozillacert73.pem
	 SHA1: B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E
	 SHA256: 2C:E1:CB:0B:F9:D2:F9:E1:02:99:3F:BE:21:51:52:C3:B2:DD:0C:AB:DE:1C:68:E5:31:9B:83:91:54:DB:B7:F5
Alias name: mozillacert74.pem
	 SHA1: 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F
	 SHA256: 56:8D:69:05:A2:C8:87:08:A4:B3:02:51:90:ED:CF:ED:B1:97:4A:60:6A:13:C6:E5:29:0F:CB:2A:E6:3E:DA:B5
Alias name: mozillacert75.pem
	 SHA1: D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A
	 SHA256: 08:29:7A:40:47:DB:A2:36:80:C7:31:DB:6E:31:76:53:CA:78:48:E1:BE:BD:3A:0B:01:79:A7:07:F9:2C:F1:78
Alias name: mozillacert76.pem
	 SHA1: F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7
	 SHA256: 03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7
Alias name: mozillacert77.pem
	 SHA1: 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6
	 SHA256: EB:04:CF:5E:B1:F3:9A:FA:76:2F:2B:B1:20:F2:96:CB:A5:20:C1:B9:7D:B1:58:95:65:B8:1C:B9:A1:7B:72:44
Alias name: mozillacert78.pem
	 SHA1: 29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F
	 SHA256: 0A:81:EC:5A:92:97:77:F1:45:90:4A:F3:8D:5D:50:9F:66:B5:E2:C5:8F:CD:B5:31:05:8B:0E:17:F3:F0:B4:1B
Alias name: mozillacert79.pem
	 SHA1: D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27
	 SHA256: 70:A7:3F:7F:37:6B:60:07:42:48:90:45:34:B1:14:82:D5:BF:0E:69:8E:CC:49:8D:F5:25:77:EB:F2:E9:3B:9A
Alias name: mozillacert8.pem
	 SHA1: 3E:2B:F7:F2:03:1B:96:F3:8C:E6:C4:D8:A8:5D:3E:2D:58:47:6A:0F
	 SHA256: C7:66:A9:BE:F2:D4:07:1C:86:3A:31:AA:49:20:E8:13:B2:D1:98:60:8C:B7:B7:CF:E2:11:43:B8:36:DF:09:EA
Alias name: mozillacert80.pem
	 SHA1: B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB
	 SHA256: BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23
Alias name: mozillacert81.pem
	 SHA1: 07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E
	 SHA256: 5C:58:46:8D:55:F5:8E:49:7E:74:39:82:D2:B5:00:10:B6:D1:65:37:4A:CF:83:A7:D4:A3:2D:B7:68:C4:40:8E
Alias name: mozillacert82.pem
	 SHA1: 2E:14:DA:EC:28:F0:FA:1E:8E:38:9A:4E:AB:EB:26:C0:0A:D3:83:C3
	 SHA256: FC:BF:E2:88:62:06:F7:2B:27:59:3C:8B:07:02:97:E1:2D:76:9E:D1:0E:D7:93:07:05:A8:09:8E:FF:C1:4D:17
Alias name: mozillacert83.pem
	 SHA1: A0:73:E5:C5:BD:43:61:0D:86:4C:21:13:0A:85:58:57:CC:9C:EA:46
	 SHA256: 8C:4E:DF:D0:43:48:F3:22:96:9E:7E:29:A4:CD:4D:CA:00:46:55:06:1C:16:E1:B0:76:42:2E:F3:42:AD:63:0E
Alias name: mozillacert84.pem
	 SHA1: D3:C0:63:F2:19:ED:07:3E:34:AD:5D:75:0B:32:76:29:FF:D5:9A:F2
	 SHA256: 79:3C:BF:45:59:B9:FD:E3:8A:B2:2D:F1:68:69:F6:98:81:AE:14:C4:B0:13:9A:C7:88:A7:8A:1A:FC:CA:02:FB
Alias name: mozillacert85.pem
	 SHA1: CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48
	 SHA256: BF:D8:8F:E1:10:1C:41:AE:3E:80:1B:F8:BE:56:35:0E:E9:BA:D1:A6:B9:BD:51:5E:DC:5C:6D:5B:87:11:AC:44
Alias name: mozillacert86.pem
	 SHA1: 74:2C:31:92:E6:07:E4:24:EB:45:49:54:2B:E1:BB:C5:3E:61:74:E2
	 SHA256: E7:68:56:34:EF:AC:F6:9A:CE:93:9A:6B:25:5B:7B:4F:AB:EF:42:93:5B:50:A2:65:AC:B5:CB:60:27:E4:4E:70
Alias name: mozillacert87.pem
	 SHA1: 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74
	 SHA256: 51:3B:2C:EC:B8:10:D4:CD:E5:DD:85:39:1A:DF:C6:C2:DD:60:D8:7B:B7:36:D2:B5:21:48:4A:A4:7A:0E:BE:F6
Alias name: mozillacert88.pem
	 SHA1: FE:45:65:9B:79:03:5B:98:A1:61:B5:51:2E:AC:DA:58:09:48:22:4D
	 SHA256: BC:10:4F:15:A4:8B:E7:09:DC:A5:42:A7:E1:D4:B9:DF:6F:05:45:27:E8:02:EA:A9:2D:59:54:44:25:8A:FE:71
Alias name: mozillacert89.pem
	 SHA1: C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D
	 SHA256: E3:89:36:0D:0F:DB:AE:B3:D2:50:58:4B:47:30:31:4E:22:2F:39:C1:56:A0:20:14:4E:8D:96:05:61:79:15:06
Alias name: mozillacert9.pem
	 SHA1: F4:8B:11:BF:DE:AB:BE:94:54:20:71:E6:41:DE:6B:BE:88:2B:40:B9
	 SHA256: 76:00:29:5E:EF:E8:5B:9E:1F:D6:24:DB:76:06:2A:AA:AE:59:81:8A:54:D2:77:4C:D4:C0:B2:C0:11:31:E1:B3
Alias name: mozillacert90.pem
	 SHA1: F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC
	 SHA256: 55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66
Alias name: mozillacert91.pem
	 SHA1: 3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04
	 SHA256: C1:B4:82:99:AB:A5:20:8F:E9:63:0A:CE:55:CA:68:A0:3E:DA:5A:51:9C:88:02:A0:D3:A6:73:BE:8F:8E:55:7D
Alias name: mozillacert92.pem
	 SHA1: A3:F1:33:3F:E2:42:BF:CF:C5:D1:4E:8F:39:42:98:40:68:10:D1:A0
	 SHA256: E1:78:90:EE:09:A3:FB:F4:F4:8B:9C:41:4A:17:D6:37:B7:A5:06:47:E9:BC:75:23:22:72:7F:CC:17:42:A9:11
Alias name: mozillacert93.pem
	 SHA1: 31:F1:FD:68:22:63:20:EE:C6:3B:3F:9D:EA:4A:3E:53:7C:7C:39:17
	 SHA256: C7:BA:65:67:DE:93:A7:98:AE:1F:AA:79:1E:71:2D:37:8F:AE:1F:93:C4:39:7F:EA:44:1B:B7:CB:E6:FD:59:95
Alias name: mozillacert94.pem
	 SHA1: 49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99
	 SHA256: 9A:11:40:25:19:7C:5B:B9:5D:94:E6:3D:55:CD:43:79:08:47:B6:46:B2:3C:DF:11:AD:A4:A0:0E:FF:15:FB:48
Alias name: mozillacert95.pem
	 SHA1: DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57
	 SHA256: ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D
Alias name: mozillacert96.pem
	 SHA1: 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1
	 SHA256: FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD
Alias name: mozillacert97.pem
	 SHA1: 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F
	 SHA256: 83:CE:3C:12:29:68:8A:59:3D:48:5F:81:97:3C:0F:91:95:43:1E:DA:37:CC:5E:36:43:0E:79:C7:A8:88:63:8B
Alias name: mozillacert98.pem
	 SHA1: C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7
	 SHA256: 3E:84:BA:43:42:90:85:16:E7:75:73:C0:99:2F:09:79:CA:08:4E:46:85:68:1F:F1:95:CC:BA:8A:22:9B:8A:76
Alias name: mozillacert99.pem
	 SHA1: F1:7F:6F:B6:31:DC:99:E3:A3:C8:7F:FE:1C:F1:81:10:88:D9:60:33
	 SHA256: 97:8C:D9:66:F2:FA:A0:7B:A7:AA:95:00:D9:C0:2E:9D:77:F2:CD:AD:A6:AD:6B:A7:4A:F4:B9:1C:66:59:3C:50
Alias name: netlockaranyclassgoldfotanusitvany
	 SHA1: 06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91
	 SHA256: 6C:61:DA:C3:A2:DE:F0:31:50:6B:E0:36:D2:A6:FE:40:19:94:FB:D1:3D:F9:C8:D4:66:59:92:74:C4:46:EC:98
Alias name: networksolutionscertificateauthority
	 SHA1: 74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE
	 SHA256: 15:F0:BA:00:A3:AC:7A:F3:AC:88:4C:07:2B:10:11:A0:77:BD:77:C0:97:F4:01:64:B2:F8:59:8A:BD:83:86:0C
Alias name: oistewisekeyglobalrootgaca
	 SHA1: 59:22:A1:E1:5A:EA:16:35:21:F8:98:39:6A:46:46:B0:44:1B:0F:A9
	 SHA256: 41:C9:23:86:6A:B4:CA:D6:B7:AD:57:80:81:58:2E:02:07:97:A6:CB:DF:4F:FF:78:CE:83:96:B3:89:37:D7:F5
Alias name: oistewisekeyglobalrootgbca
	 SHA1: 0F:F9:40:76:18:D3:D7:6A:4B:98:F0:A8:35:9E:0C:FD:27:AC:CC:ED
	 SHA256: 6B:9C:08:E8:6E:B0:F7:67:CF:AD:65:CD:98:B6:21:49:E5:49:4A:67:F5:84:5E:7B:D1:ED:01:9F:27:B8:6B:D6
Alias name: oistewisekeyglobalrootgcca
	 SHA1: E0:11:84:5E:34:DE:BE:88:81:B9:9C:F6:16:26:D1:96:1F:C3:B9:31
	 SHA256: 85:60:F9:1C:36:24:DA:BA:95:70:B5:FE:A0:DB:E3:6F:F1:1A:83:23:BE:94:86:85:4F:B3:F3:4A:55:71:19:8D
Alias name: quovadisrootca
	 SHA1: DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9
	 SHA256: A4:5E:DE:3B:BB:F0:9C:8A:E1:5C:72:EF:C0:72:68:D6:93:A2:1C:99:6F:D5:1E:67:CA:07:94:60:FD:6D:88:73
Alias name: quovadisrootca1g3
	 SHA1: 1B:8E:EA:57:96:29:1A:C9:39:EA:B8:0A:81:1A:73:73:C0:93:79:67
	 SHA256: 8A:86:6F:D1:B2:76:B5:7E:57:8E:92:1C:65:82:8A:2B:ED:58:E9:F2:F2:88:05:41:34:B7:F1:F4:BF:C9:CC:74
Alias name: quovadisrootca2
	 SHA1: CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7
	 SHA256: 85:A0:DD:7D:D7:20:AD:B7:FF:05:F8:3D:54:2B:20:9D:C7:FF:45:28:F7:D6:77:B1:83:89:FE:A5:E5:C4:9E:86
Alias name: quovadisrootca2g3
	 SHA1: 09:3C:61:F3:8B:8B:DC:7D:55:DF:75:38:02:05:00:E1:25:F5:C8:36
	 SHA256: 8F:E4:FB:0A:F9:3A:4D:0D:67:DB:0B:EB:B2:3E:37:C7:1B:F3:25:DC:BC:DD:24:0E:A0:4D:AF:58:B4:7E:18:40
Alias name: quovadisrootca3
	 SHA1: 1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85
	 SHA256: 18:F1:FC:7F:20:5D:F8:AD:DD:EB:7F:E0:07:DD:57:E3:AF:37:5A:9C:4D:8D:73:54:6B:F4:F1:FE:D1:E1:8D:35
Alias name: quovadisrootca3g3
	 SHA1: 48:12:BD:92:3C:A8:C4:39:06:E7:30:6D:27:96:E6:A4:CF:22:2E:7D
	 SHA256: 88:EF:81:DE:20:2E:B0:18:45:2E:43:F8:64:72:5C:EA:5F:BD:1F:C2:D9:D2:05:73:07:09:C5:D8:B8:69:0F:46
Alias name: secomevrootca1
	 SHA1: FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D
	 SHA256: A2:2D:BA:68:1E:97:37:6E:2D:39:7D:72:8A:AE:3A:9B:62:96:B9:FD:BA:60:BC:2E:11:F6:47:F2:C6:75:FB:37
Alias name: secomscrootca1
	 SHA1: 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7
	 SHA256: E7:5E:72:ED:9F:56:0E:EC:6E:B4:80:00:73:A4:3F:C3:AD:19:19:5A:39:22:82:01:78:95:97:4A:99:02:6B:6C
Alias name: secomscrootca2
	 SHA1: 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74
	 SHA256: 51:3B:2C:EC:B8:10:D4:CD:E5:DD:85:39:1A:DF:C6:C2:DD:60:D8:7B:B7:36:D2:B5:21:48:4A:A4:7A:0E:BE:F6
Alias name: secomvalicertclass1ca
	 SHA1: E5:DF:74:3C:B6:01:C4:9B:98:43:DC:AB:8C:E8:6A:81:10:9F:E4:8E
	 SHA256: F4:C1:49:55:1A:30:13:A3:5B:C7:BF:FE:17:A7:F3:44:9B:C1:AB:5B:5A:0A:E7:4B:06:C2:3B:90:00:4C:01:04
Alias name: secureglobalca
	 SHA1: 3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B
	 SHA256: 42:00:F5:04:3A:C8:59:0E:BB:52:7D:20:9E:D1:50:30:29:FB:CB:D4:1C:A1:B5:06:EC:27:F1:5A:DE:7D:AC:69
Alias name: securesignrootca11
	 SHA1: 3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3
	 SHA256: BF:0F:EE:FB:9E:3A:58:1A:D5:F9:E9:DB:75:89:98:57:43:D2:61:08:5C:4D:31:4F:6F:5D:72:59:AA:42:16:12
Alias name: securetrustca
	 SHA1: 87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11
	 SHA256: F1:C1:B5:0A:E5:A2:0D:D8:03:0E:C9:F6:BC:24:82:3D:D3:67:B5:25:57:59:B4:E7:1B:61:FC:E9:F7:37:5D:73
Alias name: securitycommunicationrootca
	 SHA1: 36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7
	 SHA256: E7:5E:72:ED:9F:56:0E:EC:6E:B4:80:00:73:A4:3F:C3:AD:19:19:5A:39:22:82:01:78:95:97:4A:99:02:6B:6C
Alias name: securitycommunicationrootca2
	 SHA1: 5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74
	 SHA256: 51:3B:2C:EC:B8:10:D4:CD:E5:DD:85:39:1A:DF:C6:C2:DD:60:D8:7B:B7:36:D2:B5:21:48:4A:A4:7A:0E:BE:F6
Alias name: soneraclass1ca
	 SHA1: 07:47:22:01:99:CE:74:B9:7C:B0:3D:79:B2:64:A2:C8:55:E9:33:FF
	 SHA256: CD:80:82:84:CF:74:6F:F2:FD:6E:B5:8A:A1:D5:9C:4A:D4:B3:CA:56:FD:C6:27:4A:89:26:A7:83:5F:32:31:3D
Alias name: soneraclass2ca
	 SHA1: 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27
	 SHA256: 79:08:B4:03:14:C1:38:10:0B:51:8D:07:35:80:7F:FB:FC:F8:51:8A:00:95:33:71:05:BA:38:6B:15:3D:D9:27
Alias name: soneraclass2rootca
	 SHA1: 37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27
	 SHA256: 79:08:B4:03:14:C1:38:10:0B:51:8D:07:35:80:7F:FB:FC:F8:51:8A:00:95:33:71:05:BA:38:6B:15:3D:D9:27
Alias name: sslcomevrootcertificationauthorityecc
	 SHA1: 4C:DD:51:A3:D1:F5:20:32:14:B0:C6:C5:32:23:03:91:C7:46:42:6D
	 SHA256: 22:A2:C1:F7:BD:ED:70:4C:C1:E7:01:B5:F4:08:C3:10:88:0F:E9:56:B5:DE:2A:4A:44:F9:9C:87:3A:25:A7:C8
Alias name: sslcomevrootcertificationauthorityrsar2
	 SHA1: 74:3A:F0:52:9B:D0:32:A0:F4:4A:83:CD:D4:BA:A9:7B:7C:2E:C4:9A
	 SHA256: 2E:7B:F1:6C:C2:24:85:A7:BB:E2:AA:86:96:75:07:61:B0:AE:39:BE:3B:2F:E9:D0:CC:6D:4E:F7:34:91:42:5C
Alias name: sslcomrootcertificationauthorityecc
	 SHA1: C3:19:7C:39:24:E6:54:AF:1B:C4:AB:20:95:7A:E2:C3:0E:13:02:6A
	 SHA256: 34:17:BB:06:CC:60:07:DA:1B:96:1C:92:0B:8A:B4:CE:3F:AD:82:0E:4A:A3:0B:9A:CB:C4:A7:4E:BD:CE:BC:65
Alias name: sslcomrootcertificationauthorityrsa
	 SHA1: B7:AB:33:08:D1:EA:44:77:BA:14:80:12:5A:6F:BD:A9:36:49:0C:BB
	 SHA256: 85:66:6A:56:2E:E0:BE:5C:E9:25:C1:D8:89:0A:6F:76:A8:7E:C1:6D:4D:7D:5F:29:EA:74:19:CF:20:12:3B:69
Alias name: staatdernederlandenevrootca
	 SHA1: 76:E2:7E:C1:4F:DB:82:C1:C0:A6:75:B5:05:BE:3D:29:B4:ED:DB:BB
	 SHA256: 4D:24:91:41:4C:FE:95:67:46:EC:4C:EF:A6:CF:6F:72:E2:8A:13:29:43:2F:9D:8A:90:7A:C4:CB:5D:AD:C1:5A
Alias name: staatdernederlandenrootcag3
	 SHA1: D8:EB:6B:41:51:92:59:E0:F3:E7:85:00:C0:3D:B6:88:97:C9:EE:FC
	 SHA256: 3C:4F:B0:B9:5A:B8:B3:00:32:F4:32:B8:6F:53:5F:E1:72:C1:85:D0:FD:39:86:58:37:CF:36:18:7F:A6:F4:28
Alias name: starfieldclass2ca
	 SHA1: AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A
	 SHA256: 14:65:FA:20:53:97:B8:76:FA:A6:F0:A9:95:8E:55:90:E4:0F:CC:7F:AA:4F:B7:C2:C8:67:75:21:FB:5F:B6:58
Alias name: starfieldrootcertificateauthorityg2
	 SHA1: B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E
	 SHA256: 2C:E1:CB:0B:F9:D2:F9:E1:02:99:3F:BE:21:51:52:C3:B2:DD:0C:AB:DE:1C:68:E5:31:9B:83:91:54:DB:B7:F5
Alias name: starfieldrootg2ca
	 SHA1: B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E
	 SHA256: 2C:E1:CB:0B:F9:D2:F9:E1:02:99:3F:BE:21:51:52:C3:B2:DD:0C:AB:DE:1C:68:E5:31:9B:83:91:54:DB:B7:F5
Alias name: starfieldservicesrootcertificateauthorityg2
	 SHA1: 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F
	 SHA256: 56:8D:69:05:A2:C8:87:08:A4:B3:02:51:90:ED:CF:ED:B1:97:4A:60:6A:13:C6:E5:29:0F:CB:2A:E6:3E:DA:B5
Alias name: starfieldservicesrootg2ca
	 SHA1: 92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F
	 SHA256: 56:8D:69:05:A2:C8:87:08:A4:B3:02:51:90:ED:CF:ED:B1:97:4A:60:6A:13:C6:E5:29:0F:CB:2A:E6:3E:DA:B5
Alias name: swisssigngoldcag2
	 SHA1: D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61
	 SHA256: 62:DD:0B:E9:B9:F5:0A:16:3E:A0:F8:E7:5C:05:3B:1E:CA:57:EA:55:C8:68:8F:64:7C:68:81:F2:C8:35:7B:95
Alias name: swisssigngoldg2ca
	 SHA1: D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61
	 SHA256: 62:DD:0B:E9:B9:F5:0A:16:3E:A0:F8:E7:5C:05:3B:1E:CA:57:EA:55:C8:68:8F:64:7C:68:81:F2:C8:35:7B:95
Alias name: swisssignplatinumg2ca
	 SHA1: 56:E0:FA:C0:3B:8F:18:23:55:18:E5:D3:11:CA:E8:C2:43:31:AB:66
	 SHA256: 3B:22:2E:56:67:11:E9:92:30:0D:C0:B1:5A:B9:47:3D:AF:DE:F8:C8:4D:0C:EF:7D:33:17:B4:C1:82:1D:14:36
Alias name: swisssignsilvercag2
	 SHA1: 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB
	 SHA256: BE:6C:4D:A2:BB:B9:BA:59:B6:F3:93:97:68:37:42:46:C3:C0:05:99:3F:A9:8F:02:0D:1D:ED:BE:D4:8A:81:D5
Alias name: swisssignsilverg2ca
	 SHA1: 9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB
	 SHA256: BE:6C:4D:A2:BB:B9:BA:59:B6:F3:93:97:68:37:42:46:C3:C0:05:99:3F:A9:8F:02:0D:1D:ED:BE:D4:8A:81:D5
Alias name: szafirrootca2
	 SHA1: E2:52:FA:95:3F:ED:DB:24:60:BD:6E:28:F3:9C:CC:CF:5E:B3:3F:DE
	 SHA256: A1:33:9D:33:28:1A:0B:56:E5:57:D3:D3:2B:1C:E7:F9:36:7E:B0:94:BD:5F:A7:2A:7E:50:04:C8:DE:D7:CA:FE
Alias name: teliasonerarootcav1
	 SHA1: 43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37
	 SHA256: DD:69:36:FE:21:F8:F0:77:C1:23:A1:A5:21:C1:22:24:F7:22:55:B7:3E:03:A7:26:06:93:E8:A2:4B:0F:A3:89
Alias name: thawtepersonalfreemailca
	 SHA1: E6:18:83:AE:84:CA:C1:C1:CD:52:AD:E8:E9:25:2B:45:A6:4F:B7:E2
	 SHA256: 5B:38:BD:12:9E:83:D5:A0:CA:D2:39:21:08:94:90:D5:0D:4A:AE:37:04:28:F8:DD:FF:FF:FA:4C:15:64:E1:84
Alias name: thawtepremiumserverca
	 SHA1: E0:AB:05:94:20:72:54:93:05:60:62:02:36:70:F7:CD:2E:FC:66:66
	 SHA256: 3F:9F:27:D5:83:20:4B:9E:09:C8:A3:D2:06:6C:4B:57:D3:A2:47:9C:36:93:65:08:80:50:56:98:10:5D:BC:E9
Alias name: thawteprimaryrootca
	 SHA1: 91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81
	 SHA256: 8D:72:2F:81:A9:C1:13:C0:79:1D:F1:36:A2:96:6D:B2:6C:95:0A:97:1D:B4:6B:41:99:F4:EA:54:B7:8B:FB:9F
Alias name: thawteprimaryrootcag2
	 SHA1: AA:DB:BC:22:23:8F:C4:01:A1:27:BB:38:DD:F4:1D:DB:08:9E:F0:12
	 SHA256: A4:31:0D:50:AF:18:A6:44:71:90:37:2A:86:AF:AF:8B:95:1F:FB:43:1D:83:7F:1E:56:88:B4:59:71:ED:15:57
Alias name: thawteprimaryrootcag3
	 SHA1: F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2
	 SHA256: 4B:03:F4:58:07:AD:70:F2:1B:FC:2C:AE:71:C9:FD:E4:60:4C:06:4C:F5:FF:B6:86:BA:E5:DB:AA:D7:FD:D3:4C
Alias name: thawteserverca
	 SHA1: 9F:AD:91:A6:CE:6A:C6:C5:00:47:C4:4E:C9:D4:A5:0D:92:D8:49:79
	 SHA256: 87:C6:78:BF:B8:B2:5F:38:F7:E9:7B:33:69:56:BB:CF:14:4B:BA:CA:A5:36:47:E6:1A:23:25:BC:10:55:31:6B
Alias name: trustcenterclass2caii
	 SHA1: AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E
	 SHA256: E6:B8:F8:76:64:85:F8:07:AE:7F:8D:AC:16:70:46:1F:07:C0:A1:3E:EF:3A:1F:F7:17:53:8D:7A:BA:D3:91:B4
Alias name: trustcenterclass4caii
	 SHA1: A6:9A:91:FD:05:7F:13:6A:42:63:0B:B1:76:0D:2D:51:12:0C:16:50
	 SHA256: 32:66:96:7E:59:CD:68:00:8D:9D:D3:20:81:11:85:C7:04:20:5E:8D:95:FD:D8:4F:1C:7B:31:1E:67:04:FC:32
Alias name: trustcenteruniversalcai
	 SHA1: 6B:2F:34:AD:89:58:BE:62:FD:B0:6B:5C:CE:BB:9D:D9:4F:4E:39:F3
	 SHA256: EB:F3:C0:2A:87:89:B1:FB:7D:51:19:95:D6:63:B7:29:06:D9:13:CE:0D:5E:10:56:8A:8A:77:E2:58:61:67:E7
Alias name: trustcoreca1
	 SHA1: 58:D1:DF:95:95:67:6B:63:C0:F0:5B:1C:17:4D:8B:84:0B:C8:78:BD
	 SHA256: 5A:88:5D:B1:9C:01:D9:12:C5:75:93:88:93:8C:AF:BB:DF:03:1A:B2:D4:8E:91:EE:15:58:9B:42:97:1D:03:9C
Alias name: trustcorrootcertca1
	 SHA1: FF:BD:CD:E7:82:C8:43:5E:3C:6F:26:86:5C:CA:A8:3A:45:5B:C3:0A
	 SHA256: D4:0E:9C:86:CD:8F:E4:68:C1:77:69:59:F4:9E:A7:74:FA:54:86:84:B6:C4:06:F3:90:92:61:F4:DC:E2:57:5C
Alias name: trustcorrootcertca2
	 SHA1: B8:BE:6D:CB:56:F1:55:B9:63:D4:12:CA:4E:06:34:C7:94:B2:1C:C0
	 SHA256: 07:53:E9:40:37:8C:1B:D5:E3:83:6E:39:5D:AE:A5:CB:83:9E:50:46:F1:BD:0E:AE:19:51:CF:10:FE:C7:C9:65
Alias name: trustisfpsrootca
	 SHA1: 3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04
	 SHA256: C1:B4:82:99:AB:A5:20:8F:E9:63:0A:CE:55:CA:68:A0:3E:DA:5A:51:9C:88:02:A0:D3:A6:73:BE:8F:8E:55:7D
Alias name: ttelesecglobalrootclass2
	 SHA1: 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9
	 SHA256: 91:E2:F5:78:8D:58:10:EB:A7:BA:58:73:7D:E1:54:8A:8E:CA:CD:01:45:98:BC:0B:14:3E:04:1B:17:05:25:52
Alias name: ttelesecglobalrootclass2ca
	 SHA1: 59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9
	 SHA256: 91:E2:F5:78:8D:58:10:EB:A7:BA:58:73:7D:E1:54:8A:8E:CA:CD:01:45:98:BC:0B:14:3E:04:1B:17:05:25:52
Alias name: ttelesecglobalrootclass3
	 SHA1: 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1
	 SHA256: FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD
Alias name: ttelesecglobalrootclass3ca
	 SHA1: 55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1
	 SHA256: FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD
Alias name: tubitakkamusmsslkoksertifikasisurum1
	 SHA1: 31:43:64:9B:EC:CE:27:EC:ED:3A:3F:0B:8F:0D:E4:E8:91:DD:EE:CA
	 SHA256: 46:ED:C3:68:90:46:D5:3A:45:3F:B3:10:4A:B8:0D:CA:EC:65:8B:26:60:EA:16:29:DD:7E:86:79:90:64:87:16
Alias name: twcaglobalrootca
	 SHA1: 9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65
	 SHA256: 59:76:90:07:F7:68:5D:0F:CD:50:87:2F:9F:95:D5:75:5A:5B:2B:45:7D:81:F3:69:2B:61:0A:98:67:2F:0E:1B
Alias name: twcarootcertificationauthority
	 SHA1: CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48
	 SHA256: BF:D8:8F:E1:10:1C:41:AE:3E:80:1B:F8:BE:56:35:0E:E9:BA:D1:A6:B9:BD:51:5E:DC:5C:6D:5B:87:11:AC:44
Alias name: ucaextendedvalidationroot
	 SHA1: A3:A1:B0:6F:24:61:23:4A:E3:36:A5:C2:37:FC:A6:FF:DD:F0:D7:3A
	 SHA256: D4:3A:F9:B3:54:73:75:5C:96:84:FC:06:D7:D8:CB:70:EE:5C:28:E7:73:FB:29:4E:B4:1E:E7:17:22:92:4D:24
Alias name: ucaglobalg2root
	 SHA1: 28:F9:78:16:19:7A:FF:18:25:18:AA:44:FE:C1:A0:CE:5C:B6:4C:8A
	 SHA256: 9B:EA:11:C9:76:FE:01:47:64:C1:BE:56:A6:F9:14:B5:A5:60:31:7A:BD:99:88:39:33:82:E5:16:1A:A0:49:3C
Alias name: usertrustecc
	 SHA1: D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0
	 SHA256: 4F:F4:60:D5:4B:9C:86:DA:BF:BC:FC:57:12:E0:40:0D:2B:ED:3F:BC:4D:4F:BD:AA:86:E0:6A:DC:D2:A9:AD:7A
Alias name: usertrustecccertificationauthority
	 SHA1: D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0
	 SHA256: 4F:F4:60:D5:4B:9C:86:DA:BF:BC:FC:57:12:E0:40:0D:2B:ED:3F:BC:4D:4F:BD:AA:86:E0:6A:DC:D2:A9:AD:7A
Alias name: usertrustrsa
	 SHA1: 2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E
	 SHA256: E7:93:C9:B0:2F:D8:AA:13:E2:1C:31:22:8A:CC:B0:81:19:64:3B:74:9C:89:89:64:B1:74:6D:46:C3:D4:CB:D2
Alias name: usertrustrsacertificationauthority
	 SHA1: 2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E
	 SHA256: E7:93:C9:B0:2F:D8:AA:13:E2:1C:31:22:8A:CC:B0:81:19:64:3B:74:9C:89:89:64:B1:74:6D:46:C3:D4:CB:D2
Alias name: utndatacorpsgcca
	 SHA1: 58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4
	 SHA256: 85:FB:2F:91:DD:12:27:5A:01:45:B6:36:53:4F:84:02:4A:D6:8B:69:B8:EE:88:68:4F:F7:11:37:58:05:B3:48
Alias name: utnuserfirstclientauthemailca
	 SHA1: B1:72:B1:A5:6D:95:F9:1F:E5:02:87:E1:4D:37:EA:6A:44:63:76:8A
	 SHA256: 43:F2:57:41:2D:44:0D:62:74:76:97:4F:87:7D:A8:F1:FC:24:44:56:5A:36:7A:E6:0E:DD:C2:7A:41:25:31:AE
Alias name: utnuserfirsthardwareca
	 SHA1: 04:83:ED:33:99:AC:36:08:05:87:22:ED:BC:5E:46:00:E3:BE:F9:D7
	 SHA256: 6E:A5:47:41:D0:04:66:7E:ED:1B:48:16:63:4A:A3:A7:9E:6E:4B:96:95:0F:82:79:DA:FC:8D:9B:D8:81:21:37
Alias name: utnuserfirstobjectca
	 SHA1: E1:2D:FB:4B:41:D7:D9:C3:2B:30:51:4B:AC:1D:81:D8:38:5E:2D:46
	 SHA256: 6F:FF:78:E4:00:A7:0C:11:01:1C:D8:59:77:C4:59:FB:5A:F9:6A:3D:F0:54:08:20:D0:F4:B8:60:78:75:E5:8F
Alias name: valicertclass2ca
	 SHA1: 31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6
	 SHA256: 58:D0:17:27:9C:D4:DC:63:AB:DD:B1:96:A6:C9:90:6C:30:C4:E0:87:83:EA:E8:C1:60:99:54:D6:93:55:59:6B
Alias name: verisignc1g1.pem
	 SHA1: 90:AE:A2:69:85:FF:14:80:4C:43:49:52:EC:E9:60:84:77:AF:55:6F
	 SHA256: D1:7C:D8:EC:D5:86:B7:12:23:8A:48:2C:E4:6F:A5:29:39:70:74:2F:27:6D:8A:B6:A9:E4:6E:E0:28:8F:33:55
Alias name: verisignc1g2.pem
	 SHA1: 27:3E:E1:24:57:FD:C4:F9:0C:55:E8:2B:56:16:7F:62:F5:32:E5:47
	 SHA256: 34:1D:E9:8B:13:92:AB:F7:F4:AB:90:A9:60:CF:25:D4:BD:6E:C6:5B:9A:51:CE:6E:D0:67:D0:0E:C7:CE:9B:7F
Alias name: verisignc1g3.pem
	 SHA1: 20:42:85:DC:F7:EB:76:41:95:57:8E:13:6B:D4:B7:D1:E9:8E:46:A5
	 SHA256: CB:B5:AF:18:5E:94:2A:24:02:F9:EA:CB:C0:ED:5B:B8:76:EE:A3:C1:22:36:23:D0:04:47:E4:F3:BA:55:4B:65
Alias name: verisignc1g6.pem
	 SHA1: 51:7F:61:1E:29:91:6B:53:82:FB:72:E7:44:D9:8D:C3:CC:53:6D:64
	 SHA256: 9D:19:0B:2E:31:45:66:68:5B:E8:A8:89:E2:7A:A8:C7:D7:AE:1D:8A:AD:DB:A3:C1:EC:F9:D2:48:63:CD:34:B9
Alias name: verisignc2g1.pem
	 SHA1: 67:82:AA:E0:ED:EE:E2:1A:58:39:D3:C0:CD:14:68:0A:4F:60:14:2A
	 SHA256: BD:46:9F:F4:5F:AA:E7:C5:4C:CB:D6:9D:3F:3B:00:22:55:D9:B0:6B:10:B1:D0:FA:38:8B:F9:6B:91:8B:2C:E9
Alias name: verisignc2g2.pem
	 SHA1: B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D
	 SHA256: 3A:43:E2:20:FE:7F:3E:A9:65:3D:1E:21:74:2E:AC:2B:75:C2:0F:D8:98:03:05:BC:50:2C:AF:8C:2D:9B:41:A1
Alias name: verisignc2g3.pem
	 SHA1: 61:EF:43:D7:7F:CA:D4:61:51:BC:98:E0:C3:59:12:AF:9F:EB:63:11
	 SHA256: 92:A9:D9:83:3F:E1:94:4D:B3:66:E8:BF:AE:7A:95:B6:48:0C:2D:6C:6C:2A:1B:E6:5D:42:36:B6:08:FC:A1:BB
Alias name: verisignc2g6.pem
	 SHA1: 40:B3:31:A0:E9:BF:E8:55:BC:39:93:CA:70:4F:4E:C2:51:D4:1D:8F
	 SHA256: CB:62:7D:18:B5:8A:D5:6D:DE:33:1A:30:45:6B:C6:5C:60:1A:4E:9B:18:DE:DC:EA:08:E7:DA:AA:07:81:5F:F0
Alias name: verisignc3g1.pem
	 SHA1: A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B
	 SHA256: A4:B6:B3:99:6F:C2:F3:06:B3:FD:86:81:BD:63:41:3D:8C:50:09:CC:4F:A3:29:C2:CC:F0:E2:FA:1B:14:03:05
Alias name: verisignc3g2.pem
	 SHA1: 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F
	 SHA256: 83:CE:3C:12:29:68:8A:59:3D:48:5F:81:97:3C:0F:91:95:43:1E:DA:37:CC:5E:36:43:0E:79:C7:A8:88:63:8B
Alias name: verisignc3g3.pem
	 SHA1: 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6
	 SHA256: EB:04:CF:5E:B1:F3:9A:FA:76:2F:2B:B1:20:F2:96:CB:A5:20:C1:B9:7D:B1:58:95:65:B8:1C:B9:A1:7B:72:44
Alias name: verisignc3g4.pem
	 SHA1: 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A
	 SHA256: 69:DD:D7:EA:90:BB:57:C9:3E:13:5D:C8:5E:A6:FC:D5:48:0B:60:32:39:BD:C4:54:FC:75:8B:2A:26:CF:7F:79
Alias name: verisignc3g5.pem
	 SHA1: 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5
	 SHA256: 9A:CF:AB:7E:43:C8:D8:80:D0:6B:26:2A:94:DE:EE:E4:B4:65:99:89:C3:D0:CA:F1:9B:AF:64:05:E4:1A:B7:DF
Alias name: verisignc4g2.pem
	 SHA1: 0B:77:BE:BB:CB:7A:A2:47:05:DE:CC:0F:BD:6A:02:FC:7A:BD:9B:52
	 SHA256: 44:64:0A:0A:0E:4D:00:0F:BD:57:4D:2B:8A:07:BD:B4:D1:DF:ED:3B:45:BA:AB:A7:6F:78:57:78:C7:01:19:61
Alias name: verisignc4g3.pem
	 SHA1: C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D
	 SHA256: E3:89:36:0D:0F:DB:AE:B3:D2:50:58:4B:47:30:31:4E:22:2F:39:C1:56:A0:20:14:4E:8D:96:05:61:79:15:06
Alias name: verisignclass1ca
	 SHA1: CE:6A:64:A3:09:E4:2F:BB:D9:85:1C:45:3E:64:09:EA:E8:7D:60:F1
	 SHA256: 51:84:7C:8C:BD:2E:9A:72:C9:1E:29:2D:2A:E2:47:D7:DE:1E:3F:D2:70:54:7A:20:EF:7D:61:0F:38:B8:84:2C
Alias name: verisignclass1g2ca
	 SHA1: 27:3E:E1:24:57:FD:C4:F9:0C:55:E8:2B:56:16:7F:62:F5:32:E5:47
	 SHA256: 34:1D:E9:8B:13:92:AB:F7:F4:AB:90:A9:60:CF:25:D4:BD:6E:C6:5B:9A:51:CE:6E:D0:67:D0:0E:C7:CE:9B:7F
Alias name: verisignclass1g3ca
	 SHA1: 20:42:85:DC:F7:EB:76:41:95:57:8E:13:6B:D4:B7:D1:E9:8E:46:A5
	 SHA256: CB:B5:AF:18:5E:94:2A:24:02:F9:EA:CB:C0:ED:5B:B8:76:EE:A3:C1:22:36:23:D0:04:47:E4:F3:BA:55:4B:65
Alias name: verisignclass2g2ca
	 SHA1: B3:EA:C4:47:76:C9:C8:1C:EA:F2:9D:95:B6:CC:A0:08:1B:67:EC:9D
	 SHA256: 3A:43:E2:20:FE:7F:3E:A9:65:3D:1E:21:74:2E:AC:2B:75:C2:0F:D8:98:03:05:BC:50:2C:AF:8C:2D:9B:41:A1
Alias name: verisignclass2g3ca
	 SHA1: 61:EF:43:D7:7F:CA:D4:61:51:BC:98:E0:C3:59:12:AF:9F:EB:63:11
	 SHA256: 92:A9:D9:83:3F:E1:94:4D:B3:66:E8:BF:AE:7A:95:B6:48:0C:2D:6C:6C:2A:1B:E6:5D:42:36:B6:08:FC:A1:BB
Alias name: verisignclass3ca
	 SHA1: A1:DB:63:93:91:6F:17:E4:18:55:09:40:04:15:C7:02:40:B0:AE:6B
	 SHA256: A4:B6:B3:99:6F:C2:F3:06:B3:FD:86:81:BD:63:41:3D:8C:50:09:CC:4F:A3:29:C2:CC:F0:E2:FA:1B:14:03:05
Alias name: verisignclass3g2ca
	 SHA1: 85:37:1C:A6:E5:50:14:3D:CE:28:03:47:1B:DE:3A:09:E8:F8:77:0F
	 SHA256: 83:CE:3C:12:29:68:8A:59:3D:48:5F:81:97:3C:0F:91:95:43:1E:DA:37:CC:5E:36:43:0E:79:C7:A8:88:63:8B
Alias name: verisignclass3g3ca
	 SHA1: 13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6
	 SHA256: EB:04:CF:5E:B1:F3:9A:FA:76:2F:2B:B1:20:F2:96:CB:A5:20:C1:B9:7D:B1:58:95:65:B8:1C:B9:A1:7B:72:44
Alias name: verisignclass3g4ca
	 SHA1: 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A
	 SHA256: 69:DD:D7:EA:90:BB:57:C9:3E:13:5D:C8:5E:A6:FC:D5:48:0B:60:32:39:BD:C4:54:FC:75:8B:2A:26:CF:7F:79
Alias name: verisignclass3g5ca
	 SHA1: 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5
	 SHA256: 9A:CF:AB:7E:43:C8:D8:80:D0:6B:26:2A:94:DE:EE:E4:B4:65:99:89:C3:D0:CA:F1:9B:AF:64:05:E4:1A:B7:DF
Alias name: verisignclass3publicprimarycertificationauthorityg4
	 SHA1: 22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A
	 SHA256: 69:DD:D7:EA:90:BB:57:C9:3E:13:5D:C8:5E:A6:FC:D5:48:0B:60:32:39:BD:C4:54:FC:75:8B:2A:26:CF:7F:79
Alias name: verisignclass3publicprimarycertificationauthorityg5
	 SHA1: 4E:B6:D5:78:49:9B:1C:CF:5F:58:1E:AD:56:BE:3D:9B:67:44:A5:E5
	 SHA256: 9A:CF:AB:7E:43:C8:D8:80:D0:6B:26:2A:94:DE:EE:E4:B4:65:99:89:C3:D0:CA:F1:9B:AF:64:05:E4:1A:B7:DF
Alias name: verisignroot.pem
	 SHA1: 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54
	 SHA256: 23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C
Alias name: verisigntsaca
	 SHA1: 20:CE:B1:F0:F5:1C:0E:19:A9:F3:8D:B1:AA:8E:03:8C:AA:7A:C7:01
	 SHA256: CB:6B:05:D9:E8:E5:7C:D8:82:B1:0B:4D:B7:0D:E4:BB:1D:E4:2B:A4:8A:7B:D0:31:8B:63:5B:F6:E7:78:1A:9D
Alias name: verisignuniversalrootca
	 SHA1: 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54
	 SHA256: 23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C
Alias name: verisignuniversalrootcertificationauthority
	 SHA1: 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54
	 SHA256: 23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C
Alias name: xrampglobalca
	 SHA1: B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6
	 SHA256: CE:CD:DC:90:50:99:D8:DA:DF:C5:B1:D2:09:B7:37:CB:E2:C1:8C:FB:2C:10:C0:FF:0B:CF:0D:32:86:FC:1A:A2
Alias name: xrampglobalcaroot
	 SHA1: B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6
	 SHA256: CE:CD:DC:90:50:99:D8:DA:DF:C5:B1:D2:09:B7:37:CB:E2:C1:8C:FB:2C:10:C0:FF:0B:CF:0D:32:86:FC:1A:A2
```

# Use AWS WAF to protect your REST APIs in API Gateway
<a name="apigateway-control-access-aws-waf"></a>

AWS WAF is a web application firewall that helps protect web applications and APIs from attacks. It enables you to configure a set of rules called a web access control list (web ACL) that allow, block, or count web requests based on customizable web security rules and conditions that you define. For more information, see [How AWS WAF Works](https://docs.aws.amazon.com/waf/latest/developerguide/how-aws-waf-works.html).

You can use AWS WAF to protect your API Gateway REST API from common web exploits, such as SQL injection and cross-site scripting (XSS) attacks. These could affect API availability and performance, compromise security, or consume excessive resources. For example, you can create rules to allow or block requests from specified IP address ranges, requests from CIDR blocks, requests that originate from a specific country or region, requests that contain malicious SQL code, or requests that contain malicious script. 

You can also create rules that match a specified string or a regular expression pattern in HTTP headers, method, query string, URI, and the request body (limited to the first 64 KB). Additionally, you can create rules to block attacks from specific user agents, bad bots, and content scrapers. For example, you can use rate-based rules to specify the number of web requests that are allowed by each client IP in a trailing, continuously updated, 5-minute period. 

**Important**  
AWS WAF is your first line of defense against web exploits. When AWS WAF is enabled on an API, AWS WAF rules are evaluated before other access control features, such as [resource policies](apigateway-resource-policies.md), [IAM policies](permissions.md), [Lambda authorizers](apigateway-use-lambda-authorizer.md), and [Amazon Cognito authorizers](apigateway-integrate-with-cognito.md). For example, if AWS WAF blocks access from a CIDR block that a resource policy allows, AWS WAF takes precedence and the resource policy isn't evaluated.

To enable AWS WAF for your API, you need to do the following:

1. Use the AWS WAF console, AWS SDK, or CLI to create a web ACL that contains the desired combination of AWS WAF managed rules and your own custom rules. For more information, see [Getting Started with AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/getting-started.html) and [Web access control lists (web ACLs)](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl.html).
**Important**  
API Gateway requires an AWS WAFV2 web ACL for a Regional application or an AWS WAF Classic Regional web ACL.

1. Associate the AWS WAF web ACL with an API stage. You can do this by using the AWS WAF console, AWS SDK, CLI, or by using the API Gateway console.

## To associate an AWS WAF web ACL with an API Gateway API stage using the API Gateway console
<a name="apigateway-control-access-aws-waf-console"></a>

To use the API Gateway console to associate an AWS WAF web ACL with an existing API Gateway API stage, use the following steps:

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose an existing API or create a new one.

1. In the main navigation pane, choose **Stages**, and then choose a stage.

1. In the **Stage details** section, choose **Edit**.

1. Under **Web application firewall (AWS WAF)**, select your web ACL.

   If you are using AWS WAFV2, select an AWS WAFV2 web ACL for a Regional application. The web ACL and any other AWS WAFV2 resources that it uses must be located in the same Region as your API.

   If you are using AWS WAF Classic Regional, select a Regional web ACL.

1. Choose **Save changes**.

## Associate an AWS WAF web ACL with an API Gateway API stage using the AWS CLI
<a name="apigateway-control-access-aws-waf-awscli"></a>

The following [associate-web-acl](https://docs.aws.amazon.com/cli/latest/reference/wafv2/associate-web-acl.html) command associates an AWS WAFV2 web ACL for a Regional application with an existing API Gateway API stage:

```
aws wafv2 associate-web-acl \
--web-acl-arn  arn:aws:wafv2:{region}:111122223333:regional/webacl/test-cli/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111 \
--resource-arn arn:aws:apigateway:{region}::/restapis/4wk1k4onj3/stages/prod
```

The following [associate-web-acl](https://docs.aws.amazon.com/cli/latest/reference/waf-regional/associate-web-acl.html) command associates an AWS WAF Classic Regional web ACL with an existing API Gateway API stage:

```
aws waf-regional associate-web-acl \
--web-acl-id 'aabc123a-fb4f-4fc6-becb-2b00831cadcf' \
--resource-arn 'arn:aws:apigateway:{region}::/restapis/4wk1k4onj3/stages/prod'
```

## Associate an AWS WAF web ACL with an API stage using the AWS WAF REST API
<a name="apigateway-control-access-aws-waf-api"></a>

To use the AWS WAFV2 REST API to associate an AWS WAFV2 web ACL for a Regional application with an existing API Gateway API stage, use the [AssociateWebACL](https://docs.aws.amazon.com/waf/latest/APIReference/API_AssociateWebACL.html) command, as in the following example:

```
import boto3
 
wafv2 = boto3.client('wafv2')

wafv2.associate_web_acl(
    WebACLArn='arn:aws:wafv2:{region}:111122223333:regional/webacl/test/abc6aa3b-fc33-4841-b3db-0ef3d3825b25',
    ResourceArn='arn:aws:apigateway:{region}::/restapis/4wk1k4onj3/stages/prod'
)
```

To use the AWS WAF REST API to associate an AWS WAF Classic Regional web ACL with an existing API Gateway API stage, use the [AssociateWebACL](https://docs.aws.amazon.com/waf/latest/APIReference/API_wafRegional_AssociateWebACL.html) command, as in the following example:

```
import boto3
 
waf = boto3.client('waf-regional')
 
waf.associate_web_acl(
    WebACLId='aabc123a-fb4f-4fc6-becb-2b00831cadcf',
    ResourceArn='arn:aws:apigateway:{region}::/restapis/4wk1k4onj3/stages/prod'
)
```

# Throttle requests to your REST APIs for better throughput in API Gateway
<a name="api-gateway-request-throttling"></a>

You can configure throttling and quotas for your APIs to help protect them from being overwhelmed by too many requests. Both throttles and quotas are applied on a best-effort basis and should be thought of as targets rather than guaranteed request ceilings.

API Gateway throttles requests to your API using the token bucket algorithm, where a token counts for a request. Specifically, API Gateway examines the rate and a burst of request submissions against all APIs in your account, per Region. In the token bucket algorithm, a burst can allow pre-defined overrun of those limits, but other factors can also cause limits to be overrun in some cases.

When request submissions exceed the steady-state request rate and burst limits, API Gateway begins to throttle requests. Clients may receive `429 Too Many Requests` error responses at this point. Upon catching such exceptions, the client can resubmit the failed requests in a way that is rate limiting.

As an API developer, you can set the target limits for individual API stages or methods to improve overall performance across all APIs in your account. Alternatively, you can enable usage plans to set throttles on client request submissions based on specified requests rates and quotas.

**Topics**
+ [How throttling limit settings are applied in API Gateway](#apigateway-how-throttling-limits-are-applied)
+ [Account-level throttling per Region](#apig-request-throttling-account-level-limits)
+ [Configuring API-level and stage-level throttling targets in a usage plan](#apigateway-api-level-throttling-in-usage-plan)
+ [Configuring stage-level throttling targets](#apigateway-stage-level-throttling)
+ [Configuring method-level throttling targets in a usage plan](#apigateway-method-level-throttling-in-usage-plan)

## How throttling limit settings are applied in API Gateway
<a name="apigateway-how-throttling-limits-are-applied"></a>

Before you configure throttle and quota settings for your API, it's useful to understand the types of throttling-related settings for your API and how API Gateway applies them.

Amazon API Gateway provides four basic types of throttling-related settings:
+ *AWS throttling limits* are applied across all accounts and clients in a Region. These limit settings exist to prevent your API—and your account—from being overwhelmed by too many requests. These limits are set by AWS and can't be changed by a customer.
+ Per-account limits are applied to all APIs in an account in a specified Region. The account-level rate limit can be increased upon request - higher limits are possible with APIs that have shorter timeouts and smaller payloads. To request an increase of account-level throttling limits per Region, contact the [AWS Support Center](https://console.aws.amazon.com/support/home#/). For more information, see [Amazon API Gateway quotas](limits.md). Note that these limits can't be higher than the AWS throttling limits.
+ Per-API, per-stage throttling limits are applied at the API method level for a stage. You can configure the same settings for all methods, or configure different throttle settings for each method. Note that these limits can't be higher than the AWS throttling limits.
+ *Per-client throttling limits* are applied to clients that use API keys associated with your usage plan as client identifier. Note that these limits can't be higher than the per-account limits.

API Gateway applies your throttling-related settings in the following order:

1. [Per-client or per-method throttling limits](#apigateway-method-level-throttling-in-usage-plan) that you set for an API stage in a [usage plan](api-gateway-create-usage-plans.md#api-gateway-usage-plan-create)

1. [Per-method throttling limits that you set for an API stage](set-up-stages.md#how-to-stage-settings)

1. [Account-level throttling per Region](#apig-request-throttling-account-level-limits)

1. AWS Regional throttling

## Account-level throttling per Region
<a name="apig-request-throttling-account-level-limits"></a>

By default, API Gateway limits the steady-state requests per second (RPS) across all APIs within an AWS account, per Region. It also limits the burst (that is, the maximum bucket size) across all APIs within an AWS account, per Region. In API Gateway, the burst limit represents the target maximum number of concurrent request submissions that API Gateway will fulfill before returning `429 Too Many Requests` error responses. For more information on throttling quotas, see [Amazon API Gateway quotas](limits.md).

## Configuring API-level and stage-level throttling targets in a usage plan
<a name="apigateway-api-level-throttling-in-usage-plan"></a>

In a [usage plan](api-gateway-api-usage-plans.md), you can set a per-method throttling target for all methods at the API or stage level. You can specify a *throttling rate*, which is the rate, in requests per second, that tokens are added to the token bucket. You can also specify a *throttling burst*, which is the capacity of the token bucket.

You can use the AWS CLI, SDKs, and the AWS Management Console to create a usage plan. For more information about how to create a usage plan, see [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md). 

## Configuring stage-level throttling targets
<a name="apigateway-stage-level-throttling"></a>

You can use the AWS CLI, SDKs, and the AWS Management Console to create stage-level throttling targets.

For more information about how to use the AWS Management Console to create stage-level throttling targets, see [Modify stage settings](set-up-stages.md#how-to-stage-settings). For more information about how to use the AWS CLI to create stage-level throttling targets, see [create-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-stage.html).

## Configuring method-level throttling targets in a usage plan
<a name="apigateway-method-level-throttling-in-usage-plan"></a>

You can set additional throttling targets at the method level in **Usage Plans** as shown in [Create a usage plan](api-gateway-create-usage-plans.md#api-gateway-usage-plan-create). In the API Gateway console, these are set by specifying `Resource=<resource>`, `Method=<method>` in the **Configure Method Throttling** setting. For example, for the [PetStore example](api-gateway-create-api-step-by-step.md), you might specify `Resource=/pets`, `Method=GET`.

# Private REST APIs in API Gateway
<a name="apigateway-private-apis"></a>

A private API is a REST API that is only callable from within an Amazon VPC. You can access your API using an [interface VPC endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html), which is an endpoint network interface that you create in your VPC. Interface endpoints are powered by AWS PrivateLink, a technology that enables you to privately access AWS services by using private IP addresses.

You can also use Direct Connect to establish a connection from an on-premises network to Amazon VPC and then access your private API over that connection. In all cases, traffic to your private API uses secure connections and is isolated from the public internet. Traffic doesn't leave the Amazon network.

## Best practices for private APIs
<a name="apigateway-private-api-best-practices"></a>

We recommend that you use the following best practices when you create your private API:
+ Use a single VPC endpoint to access multiple private APIs. This reduces the number of VPC endpoints that you might need.
+ Associate your VPC endpoint to your API. This creates a Route 53 alias DNS record and simplifies invoking your private API.
+ Turn on private DNS for your VPC. When you turn on private DNS for your VPC, you can invoke your API within a VPC without passing the `Host` or `x-apigw-api-id` header.

  If you turn on private DNS, you can’t access the default endpoint for public APIs. To access the default endpoint for public APIs, you can turn off private DNS, create a private hosted zone for each private API in your VPC, and then provision the required records in Route 53. This allows your private API to resolve while you can still invoke public default endpoint from your VPC. For more information, see [Creating a private hosted zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zone-private-creating.html).
+ Restrict access to your private API to specific VPCs or VPC endpoints. Add `aws:SourceVpc` or `aws:SourceVpce` conditions to your API's resource policy to restrict access.
+ For the most secure data perimeter, you can create a VPC endpoint policy. This controls access to the VPC endpoints that can invoke your private API.

## Considerations for private APIs
<a name="apigateway-private-api-considerations"></a>

The following considerations might impact your use of private APIs:
+ Only REST APIs are supported.
+ You cannot convert a private API to an edge-optimized API.
+ Private APIs only support TLS 1.2. Earlier TLS versions are not supported.
+ If you make a request using HTTP/2 protocol, the request is enforced to use HTTP/1.1 protocol.
+ You can't set the IP address type for private APIs to only allow IPv4 addresses to invoke your private API. Only dualstack is supported. For more information, see [IP address types for REST APIs in API Gateway](api-gateway-ip-address-type.md).
+ To send traffic using your private API, you can use all IP address types supported by Amazon VPC. You can send dualstack and IPv6 traffic by configuring the settings on your VPC endpoint. You can't modify this using API Gateway. For more information, see [Add IPv6 support for your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-migrate-ipv6-add.html).
+ VPC endpoints for private APIs are subject to the same limitations as other interface VPC endpoints. For more information, see [Access an AWS service using an interface VPC endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html) in the *AWS PrivateLink Guide*. For more information about using API Gateway with shared VPCs and shared subnets, see [Shared subnets](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#interface-endpoint-shared-subnets) in the *AWS PrivateLink Guide*.

## Next steps for private APIs
<a name="apigateway-private-api-next-steps"></a>

 To learn how to create a private API and associate a VPC endpoint see, [Create a private API](apigateway-private-api-create.md). To follow a tutorial where you create dependencies in CloudFormation and a private API in the AWS Management Console, see [Tutorial: Create a private REST API](private-api-tutorial.md).

# Create a private API
<a name="apigateway-private-api-create"></a>

Before you create a private API, you first create a VPC endpoint for API Gateway. Next you create your private API and attach a resource policy to it. Optionally, you can associate your VPC endpoint with your private API to simplify how you invoke your API. Finally, you deploy your API.

The following procedures describe how to accomplish this. You can create a private REST API using the AWS Management Console, AWS CLI or an AWS SDK. 

## Prerequisites
<a name="apigateway-private-api-create-interface-vpc-prerequisites"></a>

To follow these steps, you must have a fully configured VPC. To learn how to create a VPC, see [Create a VPC only](https://docs.aws.amazon.com/vpc/latest/userguide/create-vpc.html#create-vpc-only) in the *Amazon VPC User Guide*. To follow all recommend steps when you create your VPC, enable private DNS. This way you can invoke your API within a VPC without having to pass the Host or `x-apigw-api-id` header.

To enable private DNS, the `enableDnsSupport` and `enableDnsHostnames` attributes of your VPC must be set to `true`. For more information, see [DNS Support in Your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support) and [Updating DNS Support for Your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-updating).

## Step 1: Create a VPC endpoint for API Gateway in your VPC
<a name="apigateway-private-api-create-interface-vpc-endpoint"></a>

The following procedure shows how to create a VPC endpoint for API Gateway. To create a VPC endpoint for API Gateway, you specify the `execute-api` domain for the AWS Region where you create your private API. The `execute-api` domain is the API Gateway component service for API execution.

When you create your VPC endpoint for API Gateway, you specify the DNS settings. If you turn off private DNS, you can only access your API using public DNS. For more information, see [Issue: I can't connect to my public API from an API Gateway VPC endpoint](#apigateway-private-api-troubleshooting-public-access).

------
#### [ AWS Management Console ]

**To create an interface VPC endpoint for API Gateway**

1. Sign in to the AWS Management Console and open the Amazon VPC console at [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/).

1. In the navigation pane, under **Virtual private cloud**, choose **Endpoints**.

1. Choose **Create endpoint**.

1. (Optional) For **Name tag**, enter a name to help identify your VPC endpoint.

1. For **Service category**, choose **AWS services**.

1. Under **Services**, in the search bar, enter **execute-api**. Then, choose the API Gateway service endpoint in the AWS Region where you will create your API. The service name should look like `com.amazonaws.us-east-1.execute-api` and the **Type** should be **Interface**.

1. For **VPC**, choose the VPC that you want to create the endpoint in.

1. (Optional) To turn off **Enable Private DNS Name**, choose **Additional settings** and then clear **Enable Private DNS Name**.

1. For **Subnets**, choose the Availability Zones where you created the endpoint network interfaces. To improve the availability of your API, choose multiple subnets.

1. For **Security group**, select the security group to associate with the VPC endpoint network interfaces.

   The security group you choose must be set to allow TCP Port 443 inbound HTTPS traffic from either an IP range in your VPC or another security group in your VPC.

1. For **Policy**, do one of the following:
   + If you have not created your private API or you don't want to configure a custom VPC endpoint policy, choose **Full access**.
   + If you have already created a private API and want to configure a custom VPC endpoint policy, you can enter a custom VPC endpoint policy. For more information, see [Use VPC endpoint policies for private APIs in API Gateway](apigateway-vpc-endpoint-policies.md).

   You can update the VPC endpoint policy after you create your VPC endpoint. For more information, see [Update a VPC endpoint policy](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-access.html#update-vpc-endpoint-policy).

1. Choose **Create endpoint**.

1. Copy the resulting VPC endpoint ID, as you might use it in future steps.

------
#### [ AWS CLI ]

The following [create-vpc-endpoint](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-vpc-endpoint.html) command creates a VPC endpoint:

```
aws ec2 create-vpc-endpoint \
    --vpc-id vpc-1a2b3c4d \
    --vpc-endpoint-type Interface \
    --service-name com.amazonaws.us-east-1.execute-api \
    --subnet-ids subnet-7b16de0c \
    --security-group-id sg-1a2b3c4d
```

Copy the resulting VPC endpoint ID, as you might use it in future steps.

------

## Step 2: Create a private API
<a name="apigateway-private-api-create-using-console"></a>

After you create your VPC endpoint, you create a private REST API. The following procedure shows how to create a private API. 

------
#### [ AWS Management Console ]

**To create a private API**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose **Create API**.

1. Under **REST API**, choose **Build**.

1. For **Name**, enter a name.

1.  (Optional) For **Description**, enter a description. 

1. For **API endpoint type**, select **Private**.

1. (Optional) For **VPC endpoint IDs**, enter a VPC endpoint ID.

   If you associate a VPC endpoint ID with your private API, you can invoke your API from within your VPC without overriding a `Host` header or passing an `x-apigw-api-id header` For more information, see [(Optional) Associate or disassociate a VPC endpoint with a private API](#associate-private-api-with-vpc-endpoint).

1. For **IP address type**, choose **Dualstack**.

1. Choose **Create API**.

 After completing the preceding steps, you can follow the instructions in [Get started with the REST API console](getting-started-rest-new-console.md) to set up methods and integrations for this API, but you can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API. 

------
#### [ AWS CLI ]

The following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command creates a private API:

```
aws apigateway create-rest-api \
        --name 'Simple PetStore (AWS CLI, Private)' \
        --description 'Simple private PetStore API' \
        --region us-west-2 \
        --endpoint-configuration '{ "types": ["PRIVATE"], "ipAddressType": "dualstack" }'
```

A successful call returns output similar to the following:

```
{
    "createdDate": "2017-10-13T18:41:39Z",
    "description": "Simple private PetStore API",
    "endpointConfiguration": {
        "types": [
            "PRIVATE"
        ],
        "ipAddressType": "dualstack"
    },
    "id": "0qzs2sy7bh",
    "name": "Simple PetStore (AWS CLI, Private)"
}
```

 After completing the preceding steps, you can follow the instructions in [Tutorial: Create a REST API using AWS SDKs or the AWS CLI](api-gateway-create-api-cli-sdk.md) to set up methods and integrations for this API, but you can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API. 

------
#### [ SDK JavaScript v3 ]

The following example shows how to create a private API by using the AWS SDK for JavaScript v3:

```
import {APIGatewayClient, CreateRestApiCommand} from "@aws-sdk/client-api-gateway";
const apig = new APIGatewayClient({region:"us-east-1"});

const input = { // CreateRestApiRequest
  name: "Simple PetStore (JavaScript v3 SDK, private)", // required
  description: "Demo private API created using the AWS SDK for JavaScript v3",
  version: "0.00.001",
  endpointConfiguration: { // EndpointConfiguration
    types: [ "PRIVATE"],
  },  
};

export const handler = async (event) => {
const command = new CreateRestApiCommand(input);
try {
  const result = await apig.send(command);
  console.log(result);
} catch (err){
  console.error(err)
 }
};
```

A successful call returns output similar to the following:

```
{
  apiKeySource: 'HEADER',
  createdDate: 2024-04-03T17:56:36.000Z,
  description: 'Demo private API created using the AWS SDK for JavaScript v3',
  disableExecuteApiEndpoint: false,
  endpointConfiguration: { types: [ 'PRIVATE' ] },
  id: 'abcd1234',
  name: 'Simple PetStore (JavaScript v3 SDK, private)',
  rootResourceId: 'efg567',
  version: '0.00.001'
}
```

 After completing the preceding steps, you can follow the instructions in [Tutorial: Create a REST API using AWS SDKs or the AWS CLI](api-gateway-create-api-cli-sdk.md) to set up methods and integrations for this API, but you can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API. 

------
#### [ Python SDK ]

The following example shows how to create a private API by using the AWS SDK for Python:

```
import json
import boto3
import logging

logger = logging.getLogger()
apig = boto3.client('apigateway')

def lambda_handler(event, context):
    try:
      result = apig.create_rest_api(
      name='Simple PetStore (Python SDK, private)',
      description='Demo private API created using the AWS SDK for Python',
      version='0.00.001',
      endpointConfiguration={
          'types': [
             'PRIVATE',
          ],
      },
      )
    except botocore.exceptions.ClientError as error:
            logger.exception("Couldn't create private API %s.", error)
            raise
    attribute=["id", "name", "description", "createdDate", "version", "apiKeySource", "endpointConfiguration"]
    filtered_data ={key:result[key] for key in attribute}
    result = json.dumps(filtered_data, default=str, sort_keys='true')
    return result
```

A successful call returns output similar to the following:

```
"{\"apiKeySource\": \"HEADER\", \"createdDate\": \"2024-04-03 17:27:05+00:00\", \"description\": \"Demo private API created using the AWS SDK for \", \"endpointConfiguration\": {\"types\": [\"PRIVATE\"]}, \"id\": \"abcd1234\", \"name\": \"Simple PetStore (Python SDK, private)\", \"version\": \"0.00.001\"}"
```

 After completing the preceding steps, you can follow the instructions in [Tutorial: Create a REST API using AWS SDKs or the AWS CLI](api-gateway-create-api-cli-sdk.md) to set up methods and integrations for this API, but you can't deploy your API. To deploy your API, follow step 3 and attach a resource policy to your API. 

------

## Step 3: Set up a resource policy for a private API
<a name="apigateway-private-api-set-up-resource-policy"></a>

Your current private API is inaccessible to all VPCs. Use a resource policy to grant your VPCs and VPC endpoints access to your private APIs. You can grant access to a VPC endpoint in any AWS account.

Your resource policy should contain `aws:SourceVpc` or `aws:SourceVpce` conditions to restrict access. We recommend that you identify specific VPCs and VPC endpoints and don't create a resource policy that allows access for all VPCs and VPC endpoints.

The following procedure shows how to attach a resource policy to your API.

------
#### [ AWS Management Console ]

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose a REST API.

1. In the main navigation pane, choose **Resource policy**.

1. Choose **Create policy**.

1. Choose **Select a template** and then choose **Source VPC**.

1. Replace `{{vpcID}}` (including the curly braces) with your VPC ID.

1. Choose **Save changes**.

------
#### [ AWS CLI ]

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command attaches a resource policy to an existing API:

```
aws apigateway update-rest-api \
    --rest-api-id a1b2c3 \
    --patch-operations op=replace,path=/policy,value='"{\"jsonEscapedPolicyDocument\"}"'
```

------

You might also want to control which resources have access to your VPC endpoint. To control which resources have access to your VPC endpoint, attach an endpoint policy to your VPC endpoint. For more information, see [Use VPC endpoint policies for private APIs in API Gateway](apigateway-vpc-endpoint-policies.md).

## (Optional) Associate or disassociate a VPC endpoint with a private API
<a name="associate-private-api-with-vpc-endpoint"></a>

When you associate a VPC endpoint with your private API, API Gateway generates a new Route 53 alias DNS record. You can use this record to invoke your private APIs just as you do your public APIs without overriding a `Host` header or passing an `x-apigw-api-id` header.

The generated base URL is in the following format:

```
https://{rest-api-id}-{vpce-id}.execute-api.{region}.amazonaws.com/{stage}
```

------
#### [ Associate a VPC endpoint (AWS Management Console) ]

You can associate a VPC endpoint with your private API when you create it, or after it's created. The following procedure shows how to associate a VPC endpoint with a previously created API. 

**To associate a VPC endpoint with a private API**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose your private API.

1. In the main navigation pane, choose **Resource policy**.

1. Edit your resource policy to allow calls from your additional VPC endpoint.

1. In the main navigation pane, choose **API settings**.

1. In the **API details** section, choose **Edit**.

1. For **VPC endpoint IDs**, select additional VPC endpoint IDs.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

------
#### [ Dissociate a VPC endpoint (AWS Management Console) ]

**To disassociate a VPC endpoint from a private REST API**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose your private API.

1. In the main navigation pane, choose **Resource policy**.

1. Edit your resource policy to remove mentions of the VPC endpoint you want to dissociate from your private API.

1. In the main navigation pane, choose **API settings**.

1. In the **API details** section, choose **Edit**.

1. For **VPC endpoint IDs**, choose the **X** to dissociate the VPC endpoint.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

------
#### [ Associate a VPC endpoint (AWS CLI) ]

The following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command associates VPC endpoints at the time of API creation:

```
aws apigateway create-rest-api \
    --name Petstore \
    --endpoint-configuration '{ "types": ["PRIVATE"], "vpcEndpointIds" : ["vpce-0212a4ababd5b8c3e", "vpce-0393a628149c867ee"] }' \
    --region us-west-2
```

The output will look like the following:

```
{
    "apiKeySource": "HEADER",
    "endpointConfiguration": {
        "types": [
            "PRIVATE"
        ],
        "vpcEndpointIds": [
            "vpce-0212a4ababd5b8c3e",
            "vpce-0393a628149c867ee"
        ]
    },
    "id": "u67n3ov968",
    "createdDate": 1565718256,
    "name": "Petstore"
}
```

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command associates VPC endpoints to an API that you already created:

```
aws apigateway update-rest-api \
    --rest-api-id u67n3ov968 \
    --patch-operations "op='add',path='/endpointConfiguration/vpcEndpointIds',value='vpce-01d622316a7df47f9'" \
    --region us-west-2
```

The output will look like the following:

```
{
    "name": "Petstore",
    "apiKeySource": "1565718256",
    "tags": {},
    "createdDate": 1565718256,
    "endpointConfiguration": {
        "vpcEndpointIds": [
            "vpce-0212a4ababd5b8c3e",
            "vpce-0393a628149c867ee",
            "vpce-01d622316a7df47f9"
        ],
        "types": [
            "PRIVATE"
        ]
    },
    "id": "u67n3ov968"
}
```

Redeploy your API for the changes to take effect.

------
#### [ Disassociate a VPC endpoint (AWS CLI) ]

The following [update-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-rest-api.html) command dissociates a VPC endpoint from a private API:

```
aws apigateway update-rest-api \
    --rest-api-id u67n3ov968 \
    --patch-operations "op='remove',path='/endpointConfiguration/vpcEndpointIds',value='vpce-0393a628149c867ee'" \
    --region us-west-2
```

The output will look like the following:

```
{
    "name": "Petstore",
    "apiKeySource": "1565718256",
    "tags": {},
    "createdDate": 1565718256,
    "endpointConfiguration": {
        "vpcEndpointIds": [
            "vpce-0212a4ababd5b8c3e",
            "vpce-01d622316a7df47f9"
        ],
        "types": [
            "PRIVATE"
        ]
    },
    "id": "u67n3ov968"
}
```

Redeploy your API for the changes to take effect.

------

## Step 4: Deploy a private API
<a name="apigateway-private-api-deploy-using-console"></a>

To deploy your API, you create an API deployment and associate it with a stage. The following procedure shows how to deploy your private API.

------
#### [ AWS Management Console ]

**To deploy a private API**

1. Choose your API.

1. Choose **Deploy API**.

1. For **Stage**, select **New stage**.

1. For **Stage name**, enter a stage name.

1. (Optional) For **Description**, enter a description.

1. Choose **Deploy**.

------
#### [ AWS CLI ]

The following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command deploys a private API:

```
aws apigateway create-deployment --rest-api-id a1b2c3 \ 
  --stage-name test \
  --stage-description 'Private API test stage' \
  --description 'First deployment'
```

------

## Troubleshoot your private API
<a name="apigateway-private-api-troubleshooting"></a>

The following provides troubleshooting advice for errors and issues that you might encounter when creating a private API.

### Issue: I can't connect to my public API from an API Gateway VPC endpoint
<a name="apigateway-private-api-troubleshooting-public-access"></a>

When you create your VPC, you can configure the DNS settings. We recommend that you turn on private DNS for your VPC. If you choose turn off private DNS, you're only able to access your API via public DNS.

If you enable private DNS, you can't access the default endpoint of a public API Gateway API from your VPC endpoint. You can access an API with a custom domain name.

If you create a Regional custom domain name, use an A type alias record, if you create an edge-optimized custom domain name, there are no restrictions for your record type. You can access these public APIs with private DNS enabled. For more information, see [Issue: I connect to my public API from an API Gateway VPC endpoint](https://repost.aws/knowledge-center/api-gateway-vpc-connections).

### Issue: My API returns `{"Message":"User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-1:********/****/****/"}`
<a name="apigateway-private-api-troubleshooting-principal"></a>

In your resource policy, if you set the Principal to an AWS principal, such as the following:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111122223333:role/developer",
                    "arn:aws:iam::111122223333:role/Admin"
                ]
            },
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/stage/GET/pets"
            ]
        }
    ]
}
```

------

You must use `AWS_IAM` authorization for every method in your API, or else your API returns the previous error message. For more instructions on how to turn on `AWS_IAM` authorization for a method, see [Methods for REST APIs in API Gateway](how-to-method-settings.md).

### Issue: I can't tell if my VPC endpoint is associated with my API
<a name="apigateway-private-api-troubleshooting-associate-wait-time"></a>

If you associate or dissociate a VPC endpoint with your private API, you need to redeploy your API. The update operation might take few minutes to complete due to DNS propagation. During this time, your API is available, but DNS propagation for the newly generated DNS URLs may still be in progress. If after several minutes, your new URLs are not resolving in DNS, we recommend that you redeploy your API.

# Custom domain names for private APIs in API Gateway
<a name="apigateway-private-custom-domains"></a>

You can create a custom domain name for your private APIs. Use a private custom domain name to provide API callers with a simpler and more intuitive URL. With a private custom domain name, you can reduce complexity, configure security measures during the TLS handshake, and control the certificate lifecycle of your domain name using AWS Certificate Manager (ACM). For more information, see [Securing your certificate's private key for your custom domain name](#apigateway-private-custom-domains-secure-certificate-private-key).

Custom domain names for private APIs don’t need to be unique across multiple accounts. You can create `example.private.com` in account 111122223333 and in account 555555555555, as long as your ACM certificate covers the domain name. To identify a private custom domain name, use the private custom domain name ARN. This identifier is unique to private custom domain names.

When you create a private custom domain name in API Gateway, you're an *API provider*. You can provide your private custom domain name to other AWS accounts using API Gateway or AWS Resource Access Manager (AWS RAM).

When you invoke a private custom domain name, you're an *API consumer*. You can consume a private custom domain name from your own AWS account or from another AWS account.

When you consume a private custom domain name, you create a domain name access association between a VPC endpoint and a private custom domain name. With a domain name access association, API consumers can invoke your private custom domain name while isolated from the public internet. For more information, see [Tasks of API providers and API consumers for custom domain names for private APIs](apigateway-private-custom-domains-associations.md).

## Securing your certificate's private key for your custom domain name
<a name="apigateway-private-custom-domains-secure-certificate-private-key"></a>

When you request an SSL/TLS certificate using ACM to create your custom domain name for private APIs, ACM generates a public/private key pair. When you import a certificate, you generate the key pair. The public key becomes part of the certificate. To safely store the private key, ACM creates another key using AWS KMS, called the KMS key, with the alias **aws/acm**. AWS KMS uses this key to encrypt your certificate’s private key. For more information, see [Data protection in AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/data-protection.html) in the *AWS Certificate Manager User Guide*.

API Gateway uses AWS TLS Connection Manager, a service that is only accessible to AWS services, to secure and use your certificate's private keys. When you use your ACM certificate to create a API Gateway custom domain name, API Gateway associates your certificate with AWS TLS Connection Manager. We do this by creating a grant in AWS KMS against your AWS managed key. This grant allows TLS Connection Manager to use AWS KMS to decrypt your certificate's private key. TLS Connection Manager uses the certificate and the decrypted (plaintext) private key to establish a secure connection (SSL/TLS session) with clients of API Gateway services. When the certificate is disassociated from a API Gateway service, the grant is retired. For more information, see [Grants](https://docs.aws.amazon.com/kms/latest/developerguide/grants.html) in the *AWS Key Management Service Developer Guide*.

For more information, see [Data encryption at rest in Amazon API Gateway](data-protection-encryption.md#data-protection-at-rest).

## Considerations for private custom domain names
<a name="apigateway-private-custom-domains-considerations"></a>

The following considerations might impact your use of private custom domain names:
+ It takes about 15 minutes for API Gateway to provision your private custom domain name.
+ If you update your ACM certificate, it takes about 15 minutes for API Gateway to complete the update. During this time, your domain name is in the `UPDATING` state, and you can still access it.
+ To invoke a private custom domain name, you must create a domain name access association. After you create a domain name access association, it takes about 15 minutes to be ready.
+ The private custom domain name ARN contains the *account-id* and the *domain-name-id*. When you create a domain name, API Gateway uses the ARN format of `arn:partition:apigateway:region::/domainnames/domain-name`. When you access a private custom domain name, you use the ARN format of `arn:partition:apigateway:region:account-id:/domainnames/domain-name+domain-name-id`. 

  You might need to modify your IAM permissions to allow access to a private domain name after you create it.
+ You can't invoke private custom domain names with the same name from the same VPC endpoint. For example, if you wanted to invoke `arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234` and `arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+xyz000`, associate each private custom domain name with a different VPC endpoint.
+ Wildcard certificates are supported, such as a certificate for `*.private.example.com`.
+ Wildcard custom domain names aren't supported.
+ Only RSA certificates with a 2048-bit key length and ECDSA certificates with 256-bit and 384-bit key lengths are supported.
+ You can't set the IP address type for private APIs to only allow IPv4 addresses to invoke your private API. Only dualstack is supported. For more information, see [IP address types for REST APIs in API Gateway](api-gateway-ip-address-type.md).
+ To send traffic using your private API, you can use all IP address types supported by Amazon VPC. You can send dualstack and IPv6 traffic by configuring the settings on your VPC endpoint. You can't modify this using API Gateway. For more information, see [Add IPv6 support for your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-migrate-ipv6-add.html).
+ Multi-level base path mapping, such as mapping your private API to `/developers/feature`, isn't supported, but you can use a routing rule to create a multi-level path condition. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).
+ You can’t set a minimum TLS version for your private custom domain name. All private custom domain names have the security policy of `TLS-1-2`.
+ You can use VPC endpoint policy to control access to a private custom domain name. For more information, see examples 4 and 5 in [Use VPC endpoint policies for private APIs in API Gateway](apigateway-vpc-endpoint-policies.md).
+ You must create a separate resource policy for your private API and for your private custom domain name. To invoke a private custom domain name, an API consumer needs access from the private custom domain name resource policy, the private API resource policy, and any VPC endpoint policies or authorization on the private API.

## Considerations for using private custom domain names with other API Gateway resources
<a name="apigateway-private-custom-domains-considerations-for-migration"></a>

The following considerations might impact how you use private custom domain names with other API Gateway resources:
+ You can't send traffic from a private custom domain name to a public API.
+ When a private API is mapped to a private custom domain name, you can't change the API's endpoint type. 
+ You can't migrate a public custom domain name to a private custom domain name.
+ If you have a VPC endpoint that you use to access a public custom domain name, don't use it to create a domain name access association with a private custom domain name.

## Differences between private custom domain names and public custom domain names
<a name="apigateway-private-custom-domains-public-differences"></a>

The following describes the differences between private and public custom domain names:
+ Private custom domain names don’t need to be unique across multiple accounts.
+ A private domain name has a domain name ID. This ID uniquely identifies a private custom domain name and isn't generated for public custom domain names.
+ When you use the AWS CLI to update or delete your private custom domain name, you must provide the domain name ID. If you have a private custom domain name called `example.com` and a public custom domain name called `example.com` and you don't provide the domain name ID, API Gateway will modify or delete your public custom domain name.

## Next steps for custom domain names for private APIs
<a name="apigateway-private-custom-domains-next-steps"></a>

For information about the tasks of an API provider and an API consumer, see [Tasks of API providers and API consumers for custom domain names for private APIs](apigateway-private-custom-domains-associations.md).

For instructions on creating a private custom domain name that you can invoke in your own AWS account, see [Tutorial: Create and invoke a custom domain name for private APIs](apigateway-private-custom-domains-tutorial.md).

For instructions on providing another AWS account access to your private custom domain name, see [API provider: Share your private custom domain name using AWS RAM](apigateway-private-custom-domains-provider-share.md). For instructions on associating your VPC endpoint with a private custom domain name in another AWS account, see [API consumer: Associate your VPC endpoint with a private custom domain name shared with you](apigateway-private-custom-domains-consumer-create.md).

# Tasks of API providers and API consumers for custom domain names for private APIs
<a name="apigateway-private-custom-domains-associations"></a>

When you create a private custom domain name, you're an *API provider*. When you invoke a private custom domain name, you're an *API consumer*. You can consume a private custom domain name from your own AWS account or from another AWS account.

The following section explains the tasks required by the API provider and API consumer to use a private custom domain name. If you want to invoke a private custom domain name in your own AWS account, you are both the API provider and the API consumer. If you want to invoke a private custom domain in another AWS account, depending on the trust relationship between the API provider and API consumer in AWS Organizations, AWS RAM might complete some tasks for you.

## Tasks of an API provider
<a name="apigateway-private-custom-domains-associations-provider"></a>

API providers create private APIs and map them to custom domain names.

 API providers manage two resource policies to protect their private custom domain names. The first policy is for the `execute-api` service and controls which VPC endpoints can invoke your private custom domain name. In the private custom domain name configuration, it's called the `policy`.

The second policy is for the Amazon API Gateway Management service and controls which VPC endpoints in other AWS accounts can form a domain name access association with your private custom domain name. A VPC endpoint needs to form a domain name access association with a private custom domain name to invoke it. In the private custom domain name configuration, it's the `managementPolicy`. You can use AWS RAM or API Gateway to update this policy. If you don't plan on allowing VPC endpoints in other AWS accounts to invoke your custom domain name, you don't edit the `managementPolicy`.

If you are an API provider, you must do the following:

1. Create a private API.

1. Update your private API's `policy` to grant your VPC endpoint access to your private API.

1. Create a private custom domain name.

1. Update your private custom domain name's `policy` to grant your VPC endpoint access to your private custom domain name.

1. Create a base path mapping or a routing rule to send traffic from your private API to your private custom domain name. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

If you want to allow API consumers in other AWS accounts to access your private custom domain name, do the following:

1. Update the `managementPolicy` of your private custom domain name to allow API consumers in other accounts to associate their VPC endpoints with your private custom domain name. You can do this using the following methods:  
**AWS RAM**  
With AWS RAM, if the API provider and the API consumer are in the same organization using AWS Organizations, the resource share between provider and consumer is automatically accepted. Otherwise, you should wait until the API consumer accepts the resource share. **We recommend that you use AWS RAM to share your private custom domain name.**   
**API Gateway**  
With API Gateway, only the AWS CLI is supported. You must update your private custom domain name using a patch operation and provide your own policy document for the `managementPolicy`.

1. Update the `policy` of your private custom domain name and any private APIs mapped to it to grant access to the API consumer's VPC endpoint.

For instructions on how to provide your API to another AWS account, see [API provider: Share your private custom domain name using AWS RAM](apigateway-private-custom-domains-provider-share.md). 

## Tasks of an API consumer
<a name="apigateway-private-custom-domains-associations-consumer"></a>

API consumers associate their VPC endpoints with a domain name ARN to invoke a private custom domain name. API consumers don't need to create an API Gateway API.

If you are an API consumer, do the following:

1. Create a VPC endpoint with private DNS enabled in Amazon VPC.

1. (Optional - if AWS RAM is used) Accept a private custom domain resource share in AWS RAM within **12 hours** of the resource share. If you and the API provider are in the same organization, the resource share is automatically accepted.

1. Get the private custom domain name ARN. Because the private custom domain name URL is not unique, you use the private custom domain name ARN to form the domain name access association between your VPC endpoint and the private custom domain name. You can use AWS RAM to retrieve the private custom domain name ARN.

1. Associate the private custom domain ARN with your VPC endpoint in API Gateway. This creates a secure connection between your VPC endpoint and the private custom domain name. Traffic doesn't leave the Amazon network.

1. Wait for the API provider to grant your VPC endpoint access to the private custom domain name and any private APIs mapped to the private custom domain name. If you're both the API provider and the API consumer, you grant your own VPC endpoint invoke access.

1. Create a Route 53 Private Hosted Zone and a Route 53 record to resolve the private custom domain name in Route 53.

For instructions on how to consume an API in another AWS account, see [API consumer: Associate your VPC endpoint with a private custom domain name shared with you](apigateway-private-custom-domains-consumer-create.md).

# Tutorial: Create and invoke a custom domain name for private APIs
<a name="apigateway-private-custom-domains-tutorial"></a>

In this tutorial, you create a private custom domain name that you can invoke in a VPC in your own account. To accomplish this, you are the API provider and the API consumer. You need an existing private API and VPC endpoint to complete this tutorial. If you have a VPC endpoint that you use to access a public custom domain name, don't use it for this tutorial or to create any domain name access associations.

## Step 1: Create a private custom domain name
<a name="apigateway-private-custom-domains-provider-create-domain"></a>

You create your private custom domain name by specifying the domain name, the ACM certificate, and the policy for the `execute-api` service to control which VPC endpoints can invoke it.

------
#### [ AWS Management Console ]

**To create a private custom domain name**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose **Add domain name**.

1. For **Domain name**, enter a domain name. 

   Your ACM certificate must cover this domain name, but the domain name doesn't need to be unique.

1. Select **Private**.

1. For **Routing mode**, choose **API mappings only**.

1. For **ACM certificate**, select a certificate.

1. Choose **Add domain name**.

API Gateway provisions a domain name with a `deny` all resource policy. This is the resource policy for the `execute-api` service. You need to update this resource policy to grant access to your VPC endpoints to invoke your private custom domain name.

**To update your resource policy**

1. Choose the **Resource policy** tab, and then choose **Edit resource policy**.

1. Enter the following resource policy in the code editor. Replace the VPC endpoint *vpce-abcd1234efg* with your own VPC endpoint ID.  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": "*",
               "Action": "execute-api:Invoke",
               "Resource": [
                   "execute-api:/*"
               ]
           },
           {
               "Effect": "Deny",
               "Principal": "*",
               "Action": "execute-api:Invoke",
               "Resource": [
                   "execute-api:/*"
               ],
               "Condition" : {
                   "StringNotEquals": {
                       "aws:SourceVpce": "vpce-abcd1234"
                   }
               }
           }
       ]
   }
   ```

1. Choose **Save changes**.

------
#### [ AWS CLI ]

When you create a private custom domain name using the AWS CLI, you provide a resource policy for the `execute-api` service to grant access to VPC endpoints to invoke your private custom domain name, using the `--policy file://policy.json` parameter. You can modify this policy later.

For this example, you'll attach the following resource policy as the `policy` by loading parameters from a file. Copy and save this file as `policy.json`. This policy only allows incoming traffic to a private custom domain name from the VPC endpoint * `vpce-abcd1234efg`*:

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-abcd1234"
                }
            }
        }
    ]
}
```

The following [create-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-domain-name.html) command creates a private custom domain name:

```
aws apigateway create-domain-name \
    --domain-name 'private.example.com' \
    --certificate-arn 'arn:aws:acm:us-west-2:111122223333:certificate/a1b2c3d4-5678-90ab-cdef' \
    --security-policy 'TLS_1_2' \
    --endpoint-configuration '{"types":["PRIVATE"]}' \
    --policy file://policy.json
```

The output will like the following.

```
{
    "domainName": "private.example.com",
    "domainNameId": "abcd1234",
    "domainNameArn": "arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234",
    "certificateArn": "arn:aws:acm:us-west-2:111122223333:certificate/a1b2c3d4-5678-90ab-cdef",
    "certificateUploadDate": "2024-09-10T10:31:20-07:00",
    "endpointConfiguration": {
        "types": [
            "PRIVATE"
        ]
    },
    "domainNameStatus": "AVAILABLE",
    "securityPolicy": "TLS_1_2",
    "routingMode" : "API_MAPPING_ONLY",
    "policy": "..."
}
```

------

## Step 2: Create a base path mapping to map your private API to your private custom domain name
<a name="apigateway-private-custom-domains-base-path-mapping"></a>

After you create your private custom domain name, you map a private API to it. A base path mapping makes an API accessible through the combination of the private custom domain name and an associated base path. We recommend that you use a single private custom domain name as the hostname of multiple private APIs.

All API providers need to create a base path mapping, even if you don't plan on invoking your own API. You also need to grant access for VPC endpoints to invoke any private APIs that you map to your private custom domain name.

------
#### [ AWS Management Console ]

**To create a base path mapping**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose a private custom domain name.

1. On the **API mappings** tab, choose **Configure mappings**.

1. Choose **Add new mapping**.

1. Enter an **API**, a **Stage**, and optionally a **Path**.

1. Choose **Save**.

------
#### [ AWS CLI ]

The following [create-base-path-mapping](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-base-path-mapping.html) command creates a mapping between a private API and a private custom domain name:

```
aws apigateway create-base-path-mapping \
    --domain-name-id abcd1234 \
    --domain-name 'private.example.com' \
    --rest-api-id a1b2c3 \
    --stage prod \
    --base-path v1
```

The output will look like the following.

```
{
    "basePath": "v1",
    "restApiId": "a1b2c3",
    "stage": "prod"
}
```

------

For more flexibility on how you route traffic to your APIs, you can change the routing mode to `ROUTING_RULE_ONLY` or `ROUTING_RULE_THEN_API_MAPPING` and create a routing rule. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

**Note**  
If you want other AWS accounts to invoke your private custom domain name, after you complete this tutorial, follow the steps in [API provider: Share your private custom domain name using AWS RAM](apigateway-private-custom-domains-provider-share.md).

## Step 3: Create a domain name access association between your custom domain name and a VPC endpoint
<a name="apigateway-private-custom-domains-provider-associate-with-vpce"></a>

Next, you create a domain name access association between your private custom domain name and your VPC endpoint. Your VPC endpoint uses the domain name access association to invoke your private custom domain name while isolated from the public internet.

------
#### [ AWS Management Console ]

**To create a domain name access association**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose a private custom domain name.

1. In the **Resource sharing** tab, for **Domain name access associations**, choose **Create domain name access association**.

1. For **Domain name ARN**, select your domain name.

1. For **VPC endpoint ID**, select the VPC endpoint ID you provided access to in step 1.

1. Choose **Domain name access association**.

You can also create your domain name access association using the **Domain name access associations** page of the console.

------
#### [ AWS CLI ]

The following `create-domain-name-access-association` command creates a domain name access association between your private custom domain name and your VPC endpoint.

```
aws apigateway create-domain-name-access-association \
    --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234 \
    --access-association-source vpce-abcd1234efg \
    --access-association-source-type VPCE \
    --region us-west-2
```

The output will look like the following.

```
{
    "domainNameAccessAssociationARN": "arn:aws:apigateway:us-west-2:111122223333:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg",
    "accessAssociationSource": "vpce-abcd1234efg",
    "accessAssociationSourceType": "VPCE",
    "domainNameARN" : "arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234"
}
```

------

After you create your domain name access association, it takes about 15 minutes to be ready. While you wait, you can proceed with the following steps.

## Step 4: Create a Route 53 hosted zone
<a name="apigateway-private-custom-domains-provider-create-route-53-private-hosted-zone"></a>

After you update your resource policy and associate your private custom domain name with your VPC endpoint, you create a private hosted zone in Route 53 to resolve your custom domain name. A hosted zone is container that holds information about how you want to route traffic for a domain within one or more VPCs without exposing your resources to the internet. For more information, see [Working with private hosted zones](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-private.html).

------
#### [ AWS Management Console ]

To use the AWS Management Console, see [Creating a private hosted zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zone-private-creating.html) in the *Amazon Route 53 Developer Guide*.

For **Name**, use the name of your private custom domain name. For **VPC ID**, use the VPC containing the VPC endpoint that you used in the previous steps.

------
#### [ AWS CLI ]

The following [create-hosted-zone](https://docs.aws.amazon.com/cli/latest/reference/route53/create-hosted-zone.html) command creates a private hosted zone:

```
aws route53 create-hosted-zone --name private.example.com \
    --caller-reference 2014-04-01-18:47 \
    --hosted-zone-config Comment="command-line version",PrivateZone=true \
    --vpc VPCRegion=us-west-2,VPCId=vpc-abcd1234
```

The output contains the hosted zone ID. You use the hosted zone ID in the following steps.

------

## Step 5: Create a Route 53 DNS record
<a name="apigateway-private-custom-domains-provider-create-route-53-record"></a>

After you create the hosted zone, you create an record to resolve your private custom domain name. You use the hosted zone ID you created in the previous step. In this example, you create an A record type. If you are using IPv6 for your VPC endpoint, create an AAAA record type. If you are using dualstack for your VPC endpoint, create both an AAAA and an A record type.

------
#### [ AWS Management Console ]

To use the AWS Management Console, see [Routing traffic to an Amazon API Gateway API by using your domain name](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

Use **Quick create** and turn on **Alias**. For endpoint, use the VPC endpoint DNS name.

------
#### [ AWS CLI ]

To configure your DNS records to map the private custom domain name to its hostname of the given hosted zone ID, you create a JSON file that contains the configuration for setting up a DNS record for the private domain name.

The following `setup-dns-record.json` shows how to create a DNS `A` record to map a private custom domain name to its private hostname. You provide the `DNSName` of your VPC DNS ID, and the hosted zone ID you created in the previous step.

```
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "private.example.com",
        "Type": "A",
        "AliasTarget": {
          "DNSName": "vpce-abcd1234.execute-api.us-west-2.vpce.amazonaws.com",
          "HostedZoneId": "Z2OJLYMUO9EFXC",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}
```

The following [change-resource-record-sets](https://docs.aws.amazon.com/cli/latest/reference/route53/change-resource-record-sets.html) command creates a DNS record for your private custom domain name:

```
aws route53 change-resource-record-sets \
    --hosted-zone-id ZABCDEFG1234 \
    --change-batch file://path/to/your/setup-dns-record.json
```

Replace the`hosted-zone-id` with the Route 53 Hosted Zone ID of the DNS record set in your account. The `change-batch` parameter value points to a JSON file.

------

If you don't plan on invoking your own private custom domain name, after you confirm your private custom domain name is working, you can delete these resources.

## Step 6: Invoke your private custom domain name
<a name="apigateway-private-custom-domains-tutorial-invoke"></a>

You can now invoke your private custom domain name in your own AWS account. In your VPC, use the following curl command to access your private custom domain name.

```
curl https://private.example.com/v1
```

For more information about other ways to invoke your private API, see [Invoke a private API using a custom domain name](apigateway-private-api-test-invoke-url.md#apigateway-private-custom-domains-provider-invoke).

## Step 7: Clean up
<a name="apigateway-private-custom-domains-cleanup"></a>

To prevent unnecessary costs, delete the association between your VPC endpoint and your private custom domain name, and then delete your private custom domain name.

------
#### [ AWS Management Console ]

**To delete the domain name access association**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Domain name access associations**.

1. Select your domain name access association, and then choose **Delete**.

1. Confirm your choice, and then choose **Delete**.

After you delete your domain name access association, you can delete your private custom domain name.

**To delete your private custom domain name**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose your private custom domain name.

1. Choose **Delete**.

1. Confirm your choice, and then choose **Delete**.

If necessary, you can also delete your VPC endpoint. For more information, see [Delete an interface endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/delete-interface-endpoint.html).

------
#### [ AWS CLI ]

**To clean up**

1. The following `delete-access-association` command deletes the domain name access association:

   ```
   aws apigateway delete-domain-name-access-association \
       --domain-name-access-association-arn 'arn:aws:apigateway:us-west-2:111122223333:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg' \
       --region us-west-2
   ```

1. The following `delete-domain-name` command deletes your private custom domain name. This command also removes all base path mappings.

   ```
   aws apigateway delete-domain-name \
       --domain-name test.private.com \
       --domain-name-id abcd1234
   ```

If necessary, you can also delete your VPC endpoint. For more information, see [Delete an interface endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/delete-interface-endpoint.html).

------

## Best practices
<a name="apigateway-private-custom-domains-best-practices"></a>

We recommend that you use the following best practices when you create your private custom domain name:
+ Use base path mapping or routing rules to send traffic from one private custom domain name to multiple private APIs.
+ When a VPC endpoint no longer needs access to a private custom domain name, delete the association. In addition, remove the VPC endpoint from the `policy` for the `execute-api` service for the private custom domain. 
+ Configure at least two Availability Zones per VPC endpoint.
+ Disable the default endpoint. We recommend that you disable the default endpoint to allow your API consumers to only call your API from the custom domain name. For more information, see [Disable the default endpoint for REST APIs](rest-api-disable-default-endpoint.md).
+ We recommend that you provision a Route 53 private hosted zone and an A-type record when you set up your private custom domain name. If you don't plan on invoking your own private custom domain name, you can delete these resources later.

# Working with cross-account private custom domain names
<a name="apigateway-private-custom-domains-other-accounts"></a>

This section explains how to work with cross-account private custom domain names. You can provide a private custom domain name to another AWS account and use another AWS account to invoke a private custom domain name.

You can share your private custom domain name to another AWS account using AWS Resource Access Manager or API Gateway. AWS Resource Access Manager (AWS RAM) helps you securely share your resources across AWS accounts and within your organization or organizational units (OUs). For more information, see [What is AWS Resource Access Manager](https://docs.aws.amazon.com/ram/latest/userguide/what-is.html).

For instructions on how to share a private custom domain name with another AWS account using AWS RAM, see [API provider: Share your private custom domain name using AWS RAM](apigateway-private-custom-domains-provider-share.md).

For instructions on how to share a private custom domain name with another AWS account using API Gateway, see [API provider: Share your private custom domain name using the API Gateway AWS CLI](apigateway-private-custom-domains-provider-share-cli.md).

For instructions on how to consume a private custom domain name in another AWS account, see [API consumer: Associate your VPC endpoint with a private custom domain name shared with you](apigateway-private-custom-domains-consumer-create.md).

## Best practices for working with cross-account private custom domain names
<a name="apigateway-private-custom-domains-other-accounts-best-practices"></a>

We recommend the following best practices for working with cross-account private custom domain names:
+ Use AWS RAM to share your private custom domain names. When you use AWS RAM, you can reduce operational overhead and you don't have to create a `managementPolicy` for the Amazon API Gateway Management service.
+ Use the `resource-owner` parameter when you list your private custom domain names or domain name access associations. Use the `resource-owner` parameter to only list the resources owned by you or by other AWS accounts.

  The following example shows how to get all domain name access associations that you own:

  ```
  aws apigateway get-domain-name-access-associations --resource-owner SELF
  ```

  Use `--resource-owner OTHER_ACCOUNTS` to list all the domain name access associations that other accounts have formed with your private custom domain name.

# API provider: Share your private custom domain name using AWS RAM
<a name="apigateway-private-custom-domains-provider-share"></a>

You can provide API consumers in other AWS accounts access to your private custom domain name. In this section, you learn how to share your private custom domain name using AWS RAM and how to control access to your private custom domain name.

## Considerations for sharing your private custom domain name
<a name="apigateway-private-custom-domains-provider-share-considerations"></a>

The following considerations might impact how you provide access to your private custom domain name using AWS RAM. To learn how to share your private custom domain name without using AWS RAM, see [API provider: Share your private custom domain name using the API Gateway AWS CLI](apigateway-private-custom-domains-provider-share-cli.md).
+ Private custom domain names are shared at the AWS Region level. Both the private custom domain name and the VPC endpoint need to be in the same AWS Region.
+ You can use one resource share with multiple principals, and after you create the resource share, you can add more principals to it. We recommend that when possible, you reuse your resource share.
+ You always need to grant the API consumer's VPC endpoint access to invoke your private custom domain name and any private APIs mapped to it.
+ If the API consumer and API provider are in the same organization using AWS Organizations, the resource share is automatically accepted. You still need to create the resource share using AWS RAM.
+ If the API consumer and API provider are in the same organization using AWS Organizations and resource sharing within your organization is enabled, any principals in the organization that you share with are automatically granted access to the resource shares. There is no need for an invitation and you can skip the resource share.
+ If the API consumer doesn't accept the resource share within **12 hours**, the API provider must share the resource again.
+ After you create the resource share, AWS RAM updates the `managementPolicy` for the Amazon API Gateway Management service for your private custom domain name to prevent access to principals without explicit `allow` access. For more information, see [Determining whether a request is allowed or denied within an account](https://docs.aws.amazon.com//IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow) in the IAM User Guide.

  The updated `managementPolicy` will look like the following:

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Id": "abcd1234-1234-abcd-abcd-1234abcdefg",
      "Statement": [
          {
              "Sid": "APIGatewayPrivateDomainNameManagementPolicyDefaultPermission-org",
              "Effect": "Allow",
              "Principal": "*",
              "Action": "apigateway:CreateAccessAssociation",
              "Resource": "arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234",
              "Condition": {
                  "StringEquals": {
                      "aws:PrincipalOrgID": "o-1234abcd"
                  },
                  "StringNotEquals": {
                      "aws:PrincipalAccount": "111122223333"
                  }
              }
          }
      ]
  }
  ```

------

  AWS RAM has prevented principals without explicit `allow` access to create access associations with your private custom domain name, by adding the following:

  ```
  "StringNotEquals": {
      "aws:PrincipalAccount": "111122223333"
  }
  ```

  You can still use the principal in the AWS account who created the private custom domain name to create domain name access associations.

## Allow other accounts to create domain name access associations with your private custom domain name
<a name="apigateway-private-custom-domains-provider-management-policy-update"></a>

First, you grant access to another AWS account to create domain name access associations with your private custom domain name.

------
#### [ AWS Management Console ]

To use the AWS Management Console, see [Creating a resource share in AWS RAM](https://docs.aws.amazon.com/ram/latest/userguide/working-with-sharing-create.html) in the *AWS RAM User Guide*.

For **Select resource type**, choose **API Gateway Private Custom Domains**.

------
#### [ AWS CLI ]

The following [create-resource-share](https://docs.aws.amazon.com/cli/latest/reference/ram/create-resource-share.html) creates a resource share for your private custom domain name. It can take a few minutes for the resource and principal associations to complete. For principals, provide an account ID or an Organizations ID, such as `arn:aws:organizations::123456789012:organization/o-1234abcd`. You can provide multiple principals for your resource share.

```
aws ram create-resource-share \
    --region us-west-2 \
    --name privateCustomDomain-resource-share \
    --permission-arns arn:aws:ram::aws:permission/APIGatewayPrivateDomainNameManagementPolicyDefaultPermission \
    --resource-arns arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234 \
    --principals 222222222222
```

------

After you have provided access to another AWS account, API consumers in that account must create a domain name access association between their VPC endpoint with your private custom domain name. You can't create the domain name access association for them. For more information, see [Associate your VPC endpoint with a shared private custom domain name](apigateway-private-custom-domains-consumer-create.md#apigateway-private-custom-domains-consumer-associate).

## Allow other accounts to invoke your private custom domain name
<a name="apigateway-private-custom-domains-provider-policy-update"></a>

Next, you grant access for the API consumer's VPC endpoint to invoke your private custom domain name and any private APIs mapped to it.

------
#### [ AWS Management Console ]

**To allow VPC endpoints in other accounts to invoke your private custom domain name**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose the private custom domain name that you shared with other AWS accounts.

1. On the **Resource policy** tab, choose **Edit resource policy**.

1. Add the VPC endpoint ID of the API consumer to your resource policy.

   You can find the VPC endpoint ID of the API consumer on the **Domain name access associations** section of the **Resource sharing** tab on the **Domain details** page of your private custom domain name.

1. Choose **Save changes**.

------
#### [ AWS CLI ]

The following `policy` for the `execute-api` service allows incoming traffic to a private custom domain name from both VPC endpoint `vpce-abcd1234efg` and `vpce-xyz000abc`.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": [
                    "vpce-abcd1234",
                    "vpce-xyzz0000"
                    ]
                }
            }
        }
    ]
}
```

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command uses a patch operation to update the `policy` for a private custom domain name:

```
aws apigateway update-domain-name
    --domain-name private.example.com \
    --domain-name-id abcd1234 \
    --patch-operations op=replace,path=/policy,value='"{\"Version\": \"2012-10-17\",		 	 	 \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"]},{\"Effect\": \"Deny\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"],\"Condition\":{\"StringNotEquals\":[\"vpce-abcd1234efg\", \"vpce-xyz000abc\"]}}}]}"
```

------

# API provider: Stop sharing a private custom domain name using AWS RAM
<a name="apigateway-private-custom-domains-provider-stop-sharing"></a>

To stop sharing your private custom domain name, first you stop the API consumer from creating more domain name access associations by dissociating the resource share. Then, you reject the domain name access association and remove the API consumer's VPC endpoint from your `policy` for the `execute-api` service. The API consumer can then delete their domain name access association.

## Stop sharing your private custom domain name
<a name="apigateway-private-custom-domains-provider-dissociate-ram"></a>

First, you stop the resource share using AWS RAM.

------
#### [ AWS Management Console ]

To use the AWS Management Console, see [Update a resource share in AWS RAM](https://docs.aws.amazon.com/ram/latest/userguide/working-with-sharing-update.html).

------
#### [ AWS CLI ]

The following [disassociate-resource-share](https://docs.aws.amazon.com/cli/latest/reference/ram/disassociate-resource-share.html) disassociates a resource share for your private custom domain name.

```
aws ram disassociate-resource-share \
    --region us-west-2 \
    --resource-arns arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234 \
    --principals 222222222222
```

------

## Reject the domain name access association
<a name="apigateway-private-custom-domains-provider-reject"></a>

After you stop sharing your resource using AWS RAM, you reject the domain name access association between a VPC endpoint in another account and your private custom domain name. 

**Note**  
You can't reject a domain name access association in your own account. To stop resource sharing, delete the domain name access association. For more information, see [Delete a domain name access association](apigateway-private-custom-domains-tutorial.md#apigateway-private-custom-domains-cleanup).

When you reject a domain name access association with a VPC endpoint, if an API consumer tries to call your private custom domain name, API Gateway rejects the call and returns a `403` status code.

------
#### [ AWS Management Console ]

**To reject a domain name access association**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose the private custom domain name that you shared with other AWS accounts.

1. On the **Resource sharing**, choose the domain name access association you want to reject.

1. Choose **Reject association**.

1. Confirm your choice, and then choose **Reject**.

------
#### [ AWS CLI ]

The following `reject-domain-name-access-association` command rejects the domain name access association between the VPC endpoint and your private custom domain name:

```
aws apigateway reject-domain-name-access-association \
    --domain-name-access-association-arn arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg \
    --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234
```

------

## Deny the API provider access to invoke your private custom domain name
<a name="apigateway-private-custom-domains-provider-deny-access"></a>

After you reject the domain name access association, you remove the API consumer's VPC endpoint from your `policy` for the `execute-api` service.

------
#### [ AWS Management Console ]

**To remove the API consumer's VPC endpoint from your resource policy**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose the private custom domain name that you shared with other AWS accounts.

1. On the **Resource policy** tab, choose **Edit**.

1. Remove the VPC endpoint from the policy.

1. Choose **Save changes**.

------
#### [ AWS CLI ]

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command uses a patch operation to update the `policy` for the `execute-api` service for a private custom domain name. This new `policy` removes an additional VPC endpoint ID added in [Allow other accounts to invoke your private custom domain name](apigateway-private-custom-domains-provider-share.md#apigateway-private-custom-domains-provider-policy-update):

```
aws apigateway update-domain-name
    --domain-name private.example.com \
    --domain-name-id abcd1234 \
    --patch-operations op=replace,path=/policy,value='"{\"Version\": \"2012-10-17\",		 	 	 \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"]},{\"Effect\": \"Deny\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"],\"Condition\":{\"StringNotEquals\":{\"aws:SourceVpce\": \"vpce-abcd1234efg\"}}}]}"
```

------

The API consumer should then delete the domain name access association. You can't delete it for them. For more information, see [API consumer: Delete your domain name access association with a private custom domain name](apigateway-private-custom-domains-consumer-delete-domain-name-access-association.md).

# API provider: Share your private custom domain name using the API Gateway AWS CLI
<a name="apigateway-private-custom-domains-provider-share-cli"></a>

You can share a private custom domain name using the API Gateway AWS CLI, but we recommend that you use AWS RAM to reduce your operational overhead. For instructions on how to use AWS RAM to share your private custom domain name, see [API provider: Share your private custom domain name using AWS RAM](apigateway-private-custom-domains-provider-share.md).

To share a private custom domain name using the API Gateway AWS CLI, you grant other AWS accounts access to create domain name access associations and invoke your private custom domain name. You do this by updating the `managementPolicy` for the API Gateway Management service and the `policy` for the `execute-api` service for your private custom domain name. You also need to grant access for the API consumer's VPC endpoint in the resource policy for any private APIs mapped to your private custom domain name.

The API consumer still needs to create a domain name access association in their own account between their VPC endpoint and your private custom domain name. You can't do this for them.

## Grant access to your private custom domain name
<a name="apigateway-private-custom-domains-provider-share-cli-allow"></a>

**To grant access to your private custom domain name**

1. To update the `managementPolicy` for the API Gateway Management service, you create a JSON file that contains the patch operation to update the policy. The following `patch-managementPolicy.json` replaces the current `managementPolicy` with an example policy that grants AWS accounts 111122223333 and 444455556666 access to create domain name access associations with the private custom domain name `private.example.com`.

   ```
   [{
       "op": "replace",
       "path": "/managementPolicy",
       "value": "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"arn:aws:iam::111122223333:root\", \"arn:aws:iam::444455556666:root\"]},\"Action\":\"apigateway:CreateAccessAssociation\",\"Resource\":\"arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"}]}"
   }]
   ```

    The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command updates the `managementPolicy` using `patch-managementPolicy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-managementPolicy.json
   ```

   Once you grant access, you need to notify the API consumer that they can form the domain name access association. If you use AWS RAM, AWS RAM will do this step for you.

1. To update the `policy` for the `execute-api` service, you create a JSON file that contains the patch operation to update the policy. The following `patch-policy.json` replaces the current `policy` with an example policy that grants two VPC endpoints to invoke the private custom domain name `private.example.com`.

   ```
   [{
       "op": "replace",
       "path": "/policy",
       "value": "{\"Version\": \"2012-10-17\",		 	 	 \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\": \"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"},{\"Effect\": \"Deny\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\": \"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\",\"Condition\": {\"StringNotEquals\": {\"aws:SourceVpce\": [\"vpce-abcd1234\",\"vpce-xyzz0000\"]}}}]}"
   }]
   ```

    Use the following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command to update the `policy` using `patch-policy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-policy.json
   ```

## Deny access to your private custom domain name
<a name="apigateway-private-custom-domains-provider-share-cli-deny"></a>

To stop sharing your private custom domain name, you need to reject the domain name access association between your private custom domain name and the API consumer's VPC endpoint.

**To deny access to your private custom domain name**

1. The following `reject-domain-name-access-association` command rejects the domain name access association.

   ```
   aws apigateway reject-domain-name-access-association \
       --domain-name-access-association-arn arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234 \
       --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234
   ```

1. Modify the `patch-managementPolicy.json` to remove access for the API provider's account to create a domain name access association with your private custom domain name. The following `patch-managementPolicy.json` removes one account from the `managementPolicy`:

   ```
   [{
        "op": "replace",
        "path": "/managementPolicy",
        "value": "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"apigateway:CreateAccessAssociation\",\"Resource\":\"arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"}]}"
   }]
   ```

   The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command to updates the `managementPolicy` using `patch-managementPolicy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-managementPolicy.json
   ```

1. Modify the `patch-policy.json` to remove access for the API provider's VPC endpoint to invoke your private custom domain name. The following `patch-policy.json` removes the VPC endpoint ID from the `policy`:

   ```
   [{
       "op": "replace",
       "path": "/policy",
       "value": "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"execute-api:Invoke\",\"Resource\":\"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"},{\"Effect\":\"Deny\",\"Principal\":\"*\",\"Action\":\"execute-api:Invoke\",\"Resource\":\"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\",\"Condition\":{\"StringNotEquals\":{\"aws:SourceVpce\":\"vpce-abcd1234\"}}}]}"
   }]
   ```

   The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-domain-name.html) command updates the `policy` using `patch-policy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-policy.json
   ```

## Example policies used in this procedure
<a name="apigateway-private-custom-domains-provider-share-cli-policies"></a>

The following section shows the example policies used in the previous procedure.

The following example policy is for the `managementPolicy` for the Amazon API Gateway Management service. This policy grants AWS accounts 111122223333 and 444455556666 access to create domain name access associations with the private custom domain name `private.example.com`. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "111122223333",
                    "444455556666"
                ]
            },
            "Action": "apigateway:CreateAccessAssociation",
            "Resource": "arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+a1b2c3"
        }
    ]
}
```

------

The following example policy is the policy for the `policy` for the `execute-api` service. This policy grants VPC endpoints `vpce-abcd1234` and `vpce-xyzz0000` access to invoke the private custom domain name.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234",
            "Condition": {
                "StringNotEquals": {
                    "aws:SourceVpce": [
                        "vpce-abcd1234",
                        "vpce-xyzz0000"
                    ]
                }
            }
        }
    ]
}
```

------

# API consumer: Associate your VPC endpoint with a private custom domain name shared with you
<a name="apigateway-private-custom-domains-consumer-create"></a>

The following procedure shows how to consume a private domain name in another AWS account. Depending on your trust relationship with the API provider, AWS RAM might complete some tasks for you.

When you are in a different AWS account from a private custom domain name, you can only associate your VPC endpoint with a private custom domain name and invoke it. You can't view the `policy` or any other parameters of the private custom domain name.

## Prerequisites
<a name="apigateway-private-custom-domains-consumer-prerequisites"></a>

The following prerequisites are required to consume a private custom domain name in another AWS account:
+ A VPC and a VPC endpoint for the `execute-api` service. Your VPC must have `enableDnsHostnames` and `enableDnsSupport` set to `true`.
+ We recommend that you configure at least two Availability Zones per VPC endpoint.

## (Optional) Accept the private custom domain resource share
<a name="apigateway-private-custom-domains-consumer-accept-resource-share"></a>

If your API provider used AWS RAM to create a resource share, you have **12 hours** to accept it. If you are in the same organization using AWS Organizations as the API provider, the share is automatically accepted. If you are in an organization that has automatic shared resources enabled, the resource is automatically shared with you.

------
#### [ AWS Management Console ]

To use the AWS Management Console, see [Accepting and rejecting resource share invitations](https://docs.aws.amazon.com/ram/latest/userguide/working-with-shared-invitations.html) in the *AWS RAM User Guide*. 

------
#### [ AWS CLI ]

To find all resources shared with you, use the following [get-resource-share-invitations](https://docs.aws.amazon.com/cli/latest/reference/ram/get-resource-share-invitations.html) command:

```
aws ram get-resource-share-invitations \
    --region us-west-2
```

Use the resulting resource share ARN to accept the resource share invitation. The following [accept-resource-share-invitation](https://docs.aws.amazon.com/cli/latest/reference/ram/accept-resource-share-invitation.html) command accepts the resource share.

```
aws ram accept-resource-share-invitation \
    --resource-share-invitation-arn arn:aws:ram:us-west-2:123456789012:resource-share-invitation/1e3477be-4a95-46b4-bbe0-c4001EXAMPLE \
    --region us-west-2
```

------

## Associate your VPC endpoint with a shared private custom domain name
<a name="apigateway-private-custom-domains-consumer-associate"></a>

Because private custom domain names aren't unique, you associate your VPC endpoint with the unique custom domain name ARN. After you create your domain name access association, it can take up to 15 minutes for your VPC endpoint to successfully invoke your private custom domain name. If you have a VPC endpoint that you use to access a public custom domain name, don't use it to create any domain name access associations. 

------
#### [ AWS Management Console ]

**To associate your VPC endpoint with a shared private custom domain name**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Domain name access associations**.

1. Choose **Create domain name access association**.

1. For **Domain name ARN**, select the domain name ARN that the API provider shared with you.

   The domain name ARN might not appear in the dropdown list. You can use the AWS RAM console to view domain names shared with you and then copy the domain name ARN and enter it into this field.

1. For **VPC endpoint ID**, select the VPC endpoint ID you want to form the domain name access association with.

1. Choose **Create domain name access association**.

------
#### [ AWS CLI ]

Because private custom domain names aren't unique, you associate your VPC endpoint with the unique custom domain name ARN. To find the domain name ARN, use one of the following commands.

1.   
**AWS RAM**  
The following [list-resources](https://docs.aws.amazon.com/cli/latest/reference/ram/list-resources.html) command lists resources that are shared with you. The API provider must have used AWS RAM to share their private custom domain with you to use this command.  

   ```
   aws ram list-resources \
       --resource-owner OTHER-ACCOUNTS \
       --region us-west-2
       --resource-type apigateway:Domainnames
   ```  
**API Gateway**  
The following `get-domain-names` command lists all private custom domain names owned by other AWS accounts that you can form domain name access associations with.  

   ```
   aws apigateway get-domain-names \
       --resource-owner OTHER_ACCOUNTS \
       --region us-west-2
   ```

1.  After your retrieve the ARN, use API Gateway to create the domain name access association between your VPC endpoint and a shared private custom domain name. Use the following `create-domain-name-access-association` command:

   ```
   aws apigateway create-domain-name-access-association \
       --access-association-source-type VPCE \
       --access-association-source 'vpce-1a2b3c4d5e6f1a2b3' \
       --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234"
   ```

   The output will look like the following.

   ```
   {
       "domainNameAccessAssociationARN": "arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg", 
       "accessAssociationSource": "vpce-1a2b3c4d5e6f1a2b3",
       "accessAssociationSourceType": "VPCE",
       "domainNameARN" : "arn:aws:apigateway:us-west-1:111122223333:/domainnames/private.example.com+a1b2c3"
   }
   ```

------

After you associate your VPC endpoint with the private custom domain name, confirm that your API provider has updated the policy of their private custom domain name to allow your VPC endpoint to invoke their domain name. For more information, see [Allow other accounts to invoke your private custom domain name](apigateway-private-custom-domains-provider-share.md#apigateway-private-custom-domains-provider-policy-update).

## Create a Route 53 hosted zone
<a name="apigateway-private-custom-domains-consumer-create-route-53-private-hosted-zone"></a>

To resolve the private custom domain name, you need to create a Route 53 private hosted zone. A hosted zone is container that holds information about how you want to route traffic for a domain within one or more VPCs without exposing your resources to the internet. For more information, see [Working with private hosted zones](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-private.html).

------
#### [ AWS Management Console ]

To use the AWS Management Console, see [Creating a private hosted zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zone-private-creating.html) in the *Amazon Route 53 Developer Guide*.

For **Name**, use the name of the private custom domain name. For **VPC ID**, use the VPC containing the VPC endpoint that you used for your domain name access association.

------
#### [ AWS CLI ]

The following [create-hosted-zone](https://docs.aws.amazon.com/cli/latest/reference/route53/create-hosted-zone.html) command creates a private hosted zone:

```
aws route53 create-hosted-zone --name private.example.com \
    --caller-reference 2014-04-01-18:47 \
    --hosted-zone-config Comment="command-line version",PrivateZone=true \
    --vpc VPCRegion=us-west-2,VPCId=vpc-abcd1234
```

The output contains the hosted zone ID. You use the hosted zone ID in the following steps.

------

## Create a Route 53 DNS record
<a name="apigateway-private-custom-domains-consumer-create-route-53-record"></a>

After you create the hosted zone, you create an record to resolve the private custom domain. In this example, you create an A record type. If you are using IPv6 for your VPC endpoint, create an AAAA record type. If you are using dualstack for your VPC endpoint, create both an AAAA and an A record type.

------
#### [ AWS Management Console ]

To use the AWS Management Console, see [Routing traffic to an Amazon API Gateway API by using your domain name](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

Use **Quick create** and turn on **Alias**. For endpoint, use the VPC endpoint DNS name.

------
#### [ AWS CLI ]

To configure your DNS records to map the private custom domain name to its hostname of the given hosted zone ID, first create a JSON file that contains the configuration for setting up a DNS record for the private domain name.

The following `setup-dns-record.json` shows how to create a DNS `A` record to map a private custom domain name to its private hostname. You provide the `DNSName` of your VPC DNS ID, and the hosted zone ID you created in the previous step.

```
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "private.example.com",
        "Type": "A",
        "AliasTarget": {
          "DNSName": "vpce-abcd1234.execute-api.us-west-2.vpce.amazonaws.com",
          "HostedZoneId": "Z2OJLYMUO9EFXC",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}
```

The following [change-resource-record-sets](https://docs.aws.amazon.com/cli/latest/reference/route53/change-resource-record-sets.html) command creates a DNS record for the private custom domain name:

```
aws route53 change-resource-record-sets \
    --hosted-zone-id ZABCDEFG1234 \
    --change-batch file://path/to/your/setup-dns-record.json
```

Replace the`hosted-zone-id` with the Route 53 Hosted Zone ID of the DNS record set in your account. The `change-batch` parameter value points to a JSON file.

------

## Next steps for an API consumer
<a name="apigateway-private-custom-domains-consumer-next-steps"></a>

You can now invoke the private API in your own AWS account. In your VPC, you can use the following curl command to access your private custom domain name.

```
curl https://private.example.com/v1
```

For more information about other ways to invoke your private API, see [Invoke a private API using a custom domain name](apigateway-private-api-test-invoke-url.md#apigateway-private-custom-domains-provider-invoke).

# API consumer: Delete your domain name access association with a private custom domain name
<a name="apigateway-private-custom-domains-consumer-delete-domain-name-access-association"></a>

If you are an API consumer, at any time, you can delete the access association resource. The API provider can't delete the domain name access association for you.

We recommend that you always delete a domain name access association when you're no longer using it.

------
#### [ AWS Management Console ]

**To delete the domain name access association**

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. In the main navigation pane, choose **Domain name access associations**.

1. Select your domain name access association, and then choose **Delete**.

1. Confirm your choice, and then choose **Delete**.

------
#### [ AWS CLI ]

The following `delete-access-association` command deletes the access association:

```
aws apigateway delete-domain-name-access-association \
    --domain-name-access-association-arn 'arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg'
```

------

# Create a custom domain name for private APIs using CloudFormation
<a name="apigateway-private-custom-domains-cfn"></a>

The following example CloudFormation template creates a private API and a private custom domain name, maps the private API to the custom domain name, and then creates a domain name access association. You need to provide your own VPC endpoint, domain name, and certificate ARN.

The following considerations might impact your use of CloudFormation to create a private custom domain name:
+ You can't reject a domain name access association using CloudFormation. To reject a domain name access association, use the AWS CLI.
+ Use the `AWS::ApiGateway::DomainNameV2` CloudFormation property to create a private custom domain name.
+ Use the `AWS::ApiGateway:BasePathMappingV2` CloudFormation property to create a base path mapping.

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  EndpointID:
    Type: String
    Default: vpce-abcd1234567efg
    Description: A VPC endpoint with enableDnsHostnames and enableDnsSupport set to true.
  DomainName:
    Type: String
    Default: private.example.com
    Description: A domain name that you own.
  CertificateArn:
    Type: String
    Default: arn:aws:acm:us-west-2:123456789:certificate/abcd-000-1234-0000-000000abcd
    Description: An ACM certificate that covers the domain name.
Resources:
  PrivateApi:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      EndpointConfiguration:
        Types:
          - PRIVATE
        VpcEndpointIds:
          - !Ref EndpointID
      Name: private-api
      Policy:
        Statement:
          - Action: 'execute-api:Invoke'
            Effect: Allow
            Principal: '*'
            Resource: 'execute-api:/*'
          - Action: 'execute-api:Invoke'
            Condition:
              StringNotEquals:
                'aws:SourceVpce': !Ref EndpointID
            Effect: Deny
            Principal: '*'
            Resource: 'execute-api:/*'
        Version: 2012-10-17		 	 	 
  PrivateApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    Properties:
      RestApiId: !Ref PrivateApi
      Description: Private API deployment
    DependsOn:
      - PrivateApiMethod
  PrivateApiStage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
      RestApiId: !Ref PrivateApi
      DeploymentId: !Ref PrivateApiDeployment
      StageName: prod
  PrivateApiMethod: 
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !GetAtt PrivateApi.RootResourceId
      RestApiId: !Ref PrivateApi
      AuthorizationType: NONE
      Integration:
        Type: MOCK
        RequestTemplates:
          application/json: "{\"statusCode\": 200}"
        IntegrationResponses:
          - StatusCode: '200'
      MethodResponses:
        - StatusCode: '200'
  PrivateDomainName:
    Type: AWS::ApiGateway::DomainNameV2
    Properties:
      DomainName: !Ref DomainName
      CertificateArn: !Ref CertificateArn
      EndpointConfiguration:
        Types:
          - PRIVATE
      SecurityPolicy: TLS_1_2
      Policy:
        Statement:
            - Action: 'execute-api:Invoke'
              Effect: Allow
              Principal: '*'
              Resource: 'execute-api:/*'
            - Action: 'execute-api:Invoke'
              Condition:
                StringNotEquals:
                  'aws:SourceVpce': !Ref EndpointID
              Effect: Deny
              Principal: '*'
              Resource: 'execute-api:/*'
        Version: 2012-10-17		 	 	 
  PrivateBasePathMapping:
    Type: AWS::ApiGateway::BasePathMappingV2
    DependsOn:
      - PrivateApiStage
    Properties:
      BasePath: prod
      DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
      RestApiId: !Ref PrivateApi
      Stage: prod
  DomainNameAccessAssociation: 
    Type: AWS::ApiGateway::DomainNameAccessAssociation
    Properties:
      DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
      AccessAssociationSource: !Ref EndpointID
      AccessAssociationSourceType: VPCE
```

# Invoke a private API
<a name="apigateway-private-api-test-invoke-url"></a>

You can only invoke a private API from within a VPC using a VPC endpoint. Your private API must have a resource policy that allows specific VPCs and VPC endpoints to invoke your API.

If you invoke a private API without using a custom domain name or private DNS names and your APIs or domain name uses a security policy that starts with `SecurityPolicy_`, you must set the endpoint access mode to `BASIC`. For more information, see [Endpoint access mode](apigateway-security-policies.md#apigateway-security-policies-endpoint-access-mode).

## Invoke a private API using a custom domain name
<a name="apigateway-private-custom-domains-provider-invoke"></a>

To invoke a private API using a custom domain name, your VPC endpoint needs a domain name access association with a custom domain name, and the custom domain name needs to allow access for the VPC endpoint to invoke it. For more information, see [Custom domain names for private APIs in API Gateway](apigateway-private-custom-domains.md).

There are no differences between invoking a private custom domain name in a VPC in your own AWS account or in a different AWS account.

### Use your custom domain name
<a name="apigateway-private-custom-domains-invoke-1"></a>

Inside your VPC, you can invoke your API using the custom domain name. The following example is a curl command to invoke your private custom domain name:

```
curl https://private.example.com
```

### Use endpoint-specific private DNS hostnames
<a name="apigateway-private-custom-domains-invoke-2"></a>

You can invoke your API using the custom domain name and the endpoint-specific private DNS hostname.

```
curl https://private-dns-hostname.execute-api.region.vpce.amazonaws.com/basepath -H 'Host:custom-domain-name'
```

The following example is a curl command to invoke your custom domain name using an endpoint-specific private DNS hostname:

```
curl https://vpce-123456-abc000.execute-api.us-east-2.vpce.amazonaws.com/test -H 'Host:private.example.com'
```

## Invoke a private API without using a custom domain name
<a name="apigateway-private-api-invoke-without-custom-domain-name"></a>

To invoke your private API without using a custom domain name, you need to identify the DNS names for your API. The following procedure shows how to find your DNS names.

------
#### [ AWS Management Console ]

**To find the DNS names**

1. Sign in to the AWS Management Console and open the Amazon VPC console at [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/).

1. In the main navigation pane, choose **Endpoints** and then choose your interface VPC endpoint for API Gateway.

1. In the **Details** pane, you'll see five values in the **DNS names** field. The first three are the public DNS names for your API. The other two are the private DNS names for it.

------
#### [ AWS CLI ]

Use the following [describe-vpc-endpoints](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-vpc-endpoints.html) command to list your DNS values.

```
aws ec2 describe-vpc-endpoints --vpc-endpoint-ids vpce-01234567abcdef012
```

The first three are the public DNS names for your API. The other two are the private DNS names for it.

------

### Invoke a private API using a Route53 alias
<a name="apigateway-private-api-route53-alias"></a>

You can associate or disassociate a VPC endpoint with your private API. For more information, see [(Optional) Associate or disassociate a VPC endpoint with a private API](apigateway-private-api-create.md#associate-private-api-with-vpc-endpoint).

After you associate your VPC endpoints with your private API, you can use the following base URL to invoke the API:

```
https://{rest-api-id}-{vpce-id}.execute-api.{region}.amazonaws.com/{stage}
```

For example, if you set up the `GET /pets` method for the `test` stage, and your REST API ID was `01234567ab`, and your VPC endpoint ID was `vpce-01234567abcdef012`, and your Region was `us-west-2`, you can invoke your API as:

```
curl -v https://01234567ab-vpce-01234567abcdef012.execute-api.us-west-2.amazonaws.com/test/pets
```

### Invoke a private API using private DNS names
<a name="w2aac15c20c17c17b9b9"></a>

If you've enabled private DNS, you can access your private API using the following private DNS name:

```
{restapi-id}.execute-api.{region}.amazonaws.com
```

The base URL to invoke the API is in the following format:

```
https://{restapi-id}.execute-api.{region}.amazonaws.com/{stage}
```

For example, if you set up the `GET /pets` method for the `test` stage, and your REST API ID was `01234567ab` and your Region was `us-west-2`, you could invoke your private API by entering the following URL in a browser:

```
https://01234567ab.execute-api.us-west-2.amazonaws.com/test/pets
```

Alternatively, you could use the following cURL command to invoke your private API:

```
curl -X GET https://01234567ab.execute-api.us-west-2.amazonaws.com/test/pets 
```

**Warning**  
If you enable private DNS for your VPC endpoint, you won't be able to access the default endpoint for public APIs. For more information, see [Why can't I connect to my public API from an API Gateway VPC endpoint?](https://repost.aws/knowledge-center/api-gateway-vpc-connections).

### Invoke a private API using Direct Connect
<a name="w2aac15c20c17c17b9c11"></a>

You can use Direct Connect to establish a dedicated private connection from an on-premises network to Amazon VPC and access your private API endpoint over that connection by using public DNS names.

You can also use private DNS names to access your private API from an on-premises network by setting up an Amazon Route 53 Resolver inbound endpoint and forwarding it all DNS queries of the private DNS from your remote network. For more information, see [Forwarding inbound DNS queries to your VPCs](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver-forwarding-inbound-queries.html) in the *Amazon Route 53 Developer Guide*.

### Invoke a private API using endpoint-specific public DNS hostnames
<a name="apigateway-private-api-public-dns"></a>

You can access your private API using endpoint-specific DNS hostnames. These are public DNS hostnames containing the VPC endpoint ID or API ID for your private API.

The generated base URL is in the following format:

```
https://{public-dns-hostname}.execute-api.{region}.vpce.amazonaws.com/{stage}
```

For example, if you set up the `GET /pets` method for the `test` stage, and your REST API ID was `abc1234`, its public DNS hostname was `vpce-def-01234567`, and your Region was `us-west-2`, you could invoke your private API using its VPCe ID by using the `Host` header in a cURL command:

```
curl -v https://vpce-def-01234567.execute-api.us-west-2.vpce.amazonaws.com/test/pets -H 'Host: abc1234.execute-api.us-west-2.amazonaws.com'
```

Alternatively, you can invoke your private API via its API ID by using the `x-apigw-api-id` header in a cURL command in the following format:

```
curl -v https://{public-dns-hostname}.execute-api.{region}.vpce.amazonaws.com/{stage} -H 'x-apigw-api-id:{api-id}'
```

# Monitor REST APIs in API Gateway
<a name="rest-api-monitor"></a>

In this section, you can learn how to monitor your API by using CloudWatch metrics, CloudWatch Logs, Firehose, and AWS X-Ray. By combining CloudWatch execution logs and CloudWatch metrics, you can log errors and execution traces, and monitor your API's performance. You might also want to log API calls to Firehose. You can also use AWS X-Ray to trace calls through the downstream services that make up your API.

**Note**  
API Gateway might not generate logs and metrics in the following cases:  
413 Request Entity Too Large errors
431 Request Header Fields Too Large errors
Excessive 429 Too Many Requests errors
400 series errors from requests sent to a custom domain that has no API mapping
500 series errors caused by internal failures
API Gateway will not generate logs and metrics when testing a REST API method. The CloudWatch entries are simulated. For more information, see [Use the API Gateway console to test a REST API method](how-to-test-method.md).

**Topics**
+ [Monitor REST API execution with Amazon CloudWatch metrics](monitoring-cloudwatch.md)
+ [Set up CloudWatch logging for REST APIs in API Gateway](set-up-logging.md)
+ [Log REST API calls to Amazon Data Firehose in API Gateway](apigateway-logging-to-kinesis.md)
+ [Variables for access logging for API Gateway](api-gateway-variables-for-access-logging.md)
+ [Trace user requests to REST APIs using X-Ray in API Gateway](apigateway-xray.md)

# Monitor REST API execution with Amazon CloudWatch metrics
<a name="monitoring-cloudwatch"></a>

You can monitor API execution by using CloudWatch, which collects and processes raw data from API Gateway into readable, near-real-time metrics. These statistics are recorded for a period of 15 months so you can access historical information and gain a better perspective on how your web application or service is performing. By default, API Gateway metric data is automatically sent to CloudWatch in one-minute periods. For more information, see [What Is Amazon CloudWatch?](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) in the *Amazon CloudWatch User Guide*.

The metrics reported by API Gateway provide information that you can analyze in different ways. The following list shows some common uses for the metrics that are suggestions to get you started:
+ Monitor the **IntegrationLatency** metrics to measure the responsiveness of the backend.
+ Monitor the **Latency** metrics to measure the overall responsiveness of your API calls.
+ Monitor the **CacheHitCount** and **CacheMissCount** metrics to optimize cache capacities to achieve a desired performance.

**Topics**
+ [Amazon API Gateway dimensions and metrics](api-gateway-metrics-and-dimensions.md)
+ [View CloudWatch metrics with the API dashboard in API Gateway](how-to-api-dashboard.md)
+ [View API Gateway metrics in the CloudWatch console](metrics_dimensions_view_in_cloud_watch.md)
+ [View API Gateway log events in the CloudWatch console](view-cloudwatch-log-events-in-cloudwatch-console.md)
+ [Monitoring tools in AWS for API Gateway](monitoring_automated_manual.md)

# Amazon API Gateway dimensions and metrics
<a name="api-gateway-metrics-and-dimensions"></a>

The metrics and dimensions that API Gateway sends to Amazon CloudWatch are listed below. For more information, see [Monitor REST API execution with Amazon CloudWatch metrics](monitoring-cloudwatch.md). 

## API Gateway metrics
<a name="api-gateway-metrics"></a>

Amazon API Gateway sends metric data to CloudWatch every minute.

The `AWS/ApiGateway` namespace includes the following metrics.


| Metric | Description | 
| --- | --- | 
|  4XXError |  The number of client-side errors captured in a given period. API Gateway counts modified gateway response status codes as 4XXError errors. The `Sum` statistic represents this metric, namely, the total count of the 4XXError errors in the given period. The `Average` statistic represents the 4XXError error rate, namely, the total count of the 4XXError errors divided by the total number of requests during the period. The denominator corresponds to the Count metric (below). Unit: Count  | 
|  5XXError  |  The number of server-side errors captured in a given period. The `Sum` statistic represents this metric, namely, the total count of the 5XXError errors in the given period. The `Average` statistic represents the 5XXError error rate, namely, the total count of the 5XXError errors divided by the total number of requests during the period. The denominator corresponds to the Count metric (below). Unit: Count  | 
|  CacheHitCount  |  The number of requests served from the API cache in a given period. The `Sum` statistic represents this metric, namely, the total count of the cache hits in the given period. The `Average` statistic represents the cache hit rate, namely, the total count of the cache hits divided by the total number of requests during the period. The denominator corresponds to the Count metric (below). Unit: Count  | 
|  CacheMissCount  |  The number of requests served from the backend in a given period, when API caching is enabled. The `Sum` statistic represents this metric, namely, the total count of the cache misses in the given period. The `Average` statistic represents the cache miss rate, namely, the total count of the cache misses divided by the total number of requests during the period. The denominator corresponds to the Count metric (below). Unit: Count  | 
|  Count  |  The total number API requests in a given period. The `SampleCount` statistic represents this metric. Unit: Count  | 
|  IntegrationLatency  |  The time between when API Gateway relays a request to the backend and when it receives a response from the backend. Unit: Millisecond  | 
|  Latency  |  The time between when API Gateway receives a request from a client and when it returns a response to the client. The latency includes the integration latency and other API Gateway overhead. Unit: Millisecond  | 

## Dimensions for metrics
<a name="api-gateway-metricdimensions"></a>

You can use the dimensions in the following table to filter API Gateway metrics.

**Note**  
API Gateway removes non-ASCII characters from the ApiName dimension before sending metrics to CloudWatch. If the APIName contains no ASCII characters, the API ID is used as the ApiName.


| Dimension | Description | 
| --- | --- | 
|  ApiName  |  Filters API Gateway metrics for the REST API with the specified API name.  | 
|  ApiName, Method, Resource, Stage  |  Filters API Gateway metrics for the API method with the specified API name, stage, resource, and method. API Gateway will not send these metrics unless you have explicitly enabled detailed CloudWatch metrics. In the console, choose a stage, and then for **Logs and tracing**, select **Edit**. Select **Detailed metrics**, and then choose **Save changes**. Alternatively, you can call the [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) AWS CLI command to update the `metricsEnabled` property to `true`. Enabling these metrics will incur additional charges to your account. For pricing information, see [Amazon CloudWatch Pricing](https://aws.amazon.com/cloudwatch/pricing/).  | 
|  ApiName, Stage  |  Filters API Gateway metrics for the API stage resource with the specified API name and stage.  | 

# View CloudWatch metrics with the API dashboard in API Gateway
<a name="how-to-api-dashboard"></a>

You can use the API dashboard in the API Gateway Console to display the CloudWatch metrics of your deployed API in API Gateway. These are shown as a summary of API activity over time. 

**Topics**
+ [Prerequisites](#how-to-api-dashboard-prerequisites)
+ [Examine API activities in the dashboard](#how-to-api-dashboard-console)

## Prerequisites
<a name="how-to-api-dashboard-prerequisites"></a>

1. You must have an API created in API Gateway. Follow the instructions in [Develop REST APIs in API Gateway](rest-api-develop.md).

1. You must have the API deployed at least once. Follow the instructions in [Deploy REST APIs in API Gateway](how-to-deploy-api.md).

## Examine API activities in the dashboard
<a name="how-to-api-dashboard-console"></a>

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose an API.

1. In the main navigation pane, choose **Dashboard**.

1. For **Stage**, choose the desired stage.

1. Choose **Date range** to specify a range of dates.

1. Refresh, if needed, and view individual metrics displayed in separate graphs titled **API calls**, **Latency**, **Integration latency**, **Latency**, **4xx error** and **5xx error**.
**Tip**  
To examine method-level CloudWatch metrics, make sure that you have enabled CloudWatch Logs on a method level. For more information about how to set up method-level logging, see [Override stage-level settings](set-up-stages.md#how-to-method-override).

# View API Gateway metrics in the CloudWatch console
<a name="metrics_dimensions_view_in_cloud_watch"></a>

Metrics are grouped first by the service namespace, and then by the various dimension combinations within each namespace. To view the metrics at the method-level for your API, turn on detailed metrics. For more information, see [Modify stage settings](set-up-stages.md#how-to-stage-settings).

**To view API Gateway metrics using the CloudWatch console**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. If necessary, change the AWS Region. From the navigation bar, select the Region where your AWS resources reside.

1. In the navigation pane, choose **Metrics**.

1. In the **All metrics** tab, choose **API Gateway**. 

1.  To view metrics by stage, choose the **By Stage** panel. Then, select your APIs and metric names. 

1. To view metrics by specific API, choose the **By Api Name** panel. Then, select your APIs and metric names.

**To view metrics using the AWS CLI**

1. Use the following [list-metrics](https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/list-metrics.html) command to list metrics:

   ```
   aws cloudwatch list-metrics --namespace "AWS/ApiGateway"
   ```

   After you create a metric, allow up to 15 minutes for the metric to appear. To see metric statistics sooner, use [get-metric-data](https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/update-domain-name.html) or [get-metric-statistics](https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/update-domain-name.html).

1. Use the following [get-metrics-statistics](https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/get-metric-statistics.html) command to view the average over a period of time using 5 minute intervals:

   ```
   aws cloudwatch get-metric-statistics --namespace AWS/ApiGateway --metric-name Count --start-time 2011-10-03T23:00:00Z --end-time 2017-10-05T23:00:00Z --period 300 --statistics Average
   ```

# View API Gateway log events in the CloudWatch console
<a name="view-cloudwatch-log-events-in-cloudwatch-console"></a>

The following section explains the necessary prerequisites and how to view API Gateway log events in the CloudWatch console.

## Prerequisites
<a name="view-cloudwatch-log-event-prerequisites"></a>

1. You must have an API created in API Gateway. Follow the instructions in [Develop REST APIs in API Gateway](rest-api-develop.md).

1. You must have the API deployed and invoked at least once. Follow the instructions in [Deploy REST APIs in API Gateway](how-to-deploy-api.md) and [Invoke REST APIs in API Gateway](how-to-call-api.md).

1. You must have CloudWatch Logs enabled for a stage. Follow the instructions in [Set up CloudWatch logging for REST APIs in API Gateway](set-up-logging.md).

## To view logged API requests and responses using the CloudWatch console
<a name="view-cloudwatch-log-event"></a>

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. If necessary, change the AWS Region. From the navigation bar, select the Region where your AWS resources reside. For more information, see [Regions and Endpoints](http://docs.aws.amazon.com/general/latest/gr/rande.html).

1. In the navigation pane, choose **Logs**, **Log groups**.

1. Under the **Log Groups** table, choose a log group of the **API-Gateway-Execution-Logs\$1\$1rest-api-id\$1/\$1stage-name\$1** name. 

1.  Under the **Log Streams** table, choose a log stream. You can use the timestamp to help locate the log stream of your interest. 

1. Choose **Text** to view raw text or choose **Row** to view the event row by row.

**Important**  
 CloudWatch lets you delete log groups or streams. Do not manually delete API Gateway API log groups or streams; let API Gateway manage these resources. Manually deleting log groups or streams may cause API requests and responses not to be logged. If that happens, you can delete the entire log group for the API and redeploy the API. This is because API Gateway creates log groups or log streams for an API stage at the time when it is deployed. 

# Monitoring tools in AWS for API Gateway
<a name="monitoring_automated_manual"></a>

AWS provides various tools that you can use to monitor API Gateway. You can configure some of these tools to do the monitoring for you automatically, while other tools require manual intervention. We recommend that you automate monitoring tasks as much as possible.

## Automated monitoring tools in AWS
<a name="monitoring_automated_tools"></a>

You can use the following automated monitoring tools to watch API Gateway and report when something is wrong:
+ **Amazon CloudWatch Alarms** – Watch a single metric over a time period that you specify, and perform one or more actions based on the value of the metric relative to a given threshold over a number of time periods. The action is a notification sent to an Amazon Simple Notification Service (Amazon SNS) topic or Amazon EC2 Auto Scaling policy. CloudWatch alarms do not invoke actions simply because they are in a particular state; the state must have changed and been maintained for a specified number of periods. For more information, see [Monitor REST API execution with Amazon CloudWatch metrics](monitoring-cloudwatch.md).
+ **Amazon CloudWatch Logs** – Monitor, store, and access your log files from AWS CloudTrail or other sources. For more information, see [What is CloudWatch Logs?](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html) in the *Amazon CloudWatch User Guide*.
+ **Amazon EventBridge (formerly called CloudWatch Events)** – Match events and route them to one or more target functions or streams to make changes, capture state information, and take corrective action. For more information, see [What Is Amazon EventBridge?](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html) in the *EventBridge User Guide*.
+ **AWS CloudTrail Log Monitoring** – Share log files between accounts, monitor CloudTrail log files in real time by sending them to CloudWatch Logs, write log processing applications in Java, and validate that your log files have not changed after delivery by CloudTrail. For more information, see [Working with CloudTrail Log Files](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-working-with-log-files.html) in the *AWS CloudTrail User Guide*. 

## Manual monitoring tools
<a name="monitoring_manual_tools"></a>

Another important part of monitoring API Gateway involves manually monitoring those items that the CloudWatch alarms don't cover. The API Gateway, CloudWatch, and other AWS console dashboards provide an at-a-glance view of the state of your AWS environment. We recommend that you also check the log files on API execution.
+ API Gateway dashboard shows the following statistics for a given API stage during a specified period of time:
  + **API Calls**
  + **Cache Hit**, only when API caching is enabled.
  + **Cache Miss**, only when API caching is enabled.
  + **Latency**
  + **Integration Latency**
  + **4XX Error**
  + **5XX Error**
+ The CloudWatch home page shows:
  + Current alarms and status
  + Graphs of alarms and resources
  + Service health status

  In addition, you can use CloudWatch to do the following: 
  + Create [customized dashboards](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html) to monitor the services you care about
  + Graph metric data to troubleshoot issues and discover trends
  + Search and browse all your AWS resource metrics
  + Create and edit alarms to be notified of problems

## Creating CloudWatch alarms to monitor API Gateway
<a name="creating_alarms"></a>

You can create a CloudWatch alarm that sends an Amazon SNS message when the alarm changes state. An alarm watches a single metric over a time period you specify, and performs one or more actions based on the value of the metric relative to a given threshold over a number of time periods. The action is a notification sent to an Amazon SNS topic or Auto Scaling policy. Alarms invoke actions for sustained state changes only. CloudWatch alarms do not invoke actions simply because they are in a particular state; the state must have changed and been maintained for a specified number of periods.

# Set up CloudWatch logging for REST APIs in API Gateway
<a name="set-up-logging"></a>

 To help debug issues related to request execution or client access to your API, you can enable Amazon CloudWatch Logs to log API calls. For more information about CloudWatch, see [Monitor REST API execution with Amazon CloudWatch metrics](monitoring-cloudwatch.md).

## CloudWatch log formats for API Gateway
<a name="apigateway-cloudwatch-log-formats"></a>

 There are two types of API logging in CloudWatch: execution logging and access logging. In execution logging, API Gateway manages the CloudWatch Logs. The process includes creating log groups and log streams, and reporting to the log streams any caller's requests and responses. 

The logged data includes errors or execution traces (such as request or response parameter values or payloads), data used by Lambda authorizers (formerly known as custom authorizers), whether API keys are required, whether usage plans are enabled, and other information. API Gateway redacts authorization headers, API key values, and similar sensitive request parameters from the logged data.

To improve your security posture, we recommend that you use execution logging at the `ERROR` or `INFO` level. You might need to do this to comply with various compliance frameworks. For more information, see [Amazon API Gateway controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html) in the *AWS Security Hub User Guide*.

When you deploy an API, API Gateway creates a log group and log streams under the log group. The log group is named following the `API-Gateway-Execution-Logs_{rest-api-id}/{stage_name}` format. Within each log group, the logs are further divided into log streams, which are ordered by **Last Event Time** as logged data is reported. 

In access logging, you, as an API developer, want to log who has accessed your API and how the caller accessed the API. You can create your own log group or choose an existing log group that could be managed by API Gateway. To specify the access details, you select [`$context`](api-gateway-variables-for-access-logging.md) variables, a log format, and a log group destination.

The access log format must include at least `$context.requestId` or `$context.extendedRequestId`. As a best practice, include `$context.requestId` and `$context.extendedRequestId` in your log format.

**`$context.requestId`**  
This logs the value in the `x-amzn-RequestId` header. Clients can override the value in the `x-amzn-RequestId` header with a value in the format of a universally unique identifier (UUID). API Gateway returns this request ID in the `x-amzn-RequestId` response header. API Gateway replaces overridden request IDs that aren't in the format of a UUID with `UUID_REPLACED_INVALID_REQUEST_ID` in your access logs.

**`$context.extendedRequestId`**  
The extendedRequestID is a unique ID that API Gateway generates. API Gateway returns this request ID in the `x-amz-apigw-id` response header. An API caller can't provide or override this request ID. You might need to provide this value to AWS Support to help troubleshoot your API. For more information, see [Variables for access logging for API Gateway](api-gateway-variables-for-access-logging.md).

Choose a log format that is also adopted by your analytic backend, such as [Common Log Format](https://httpd.apache.org/docs/current/logs.html#common) (CLF), JSON, XML, or CSV. You can then feed the access logs to it directly to have your metrics computed and rendered. To define the log format, set the log group ARN on the [accessLogSettings/destinationArn](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#destinationArn) property on the [stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html). You can obtain a log group ARN in the CloudWatch console. To define the access log format, set a chosen format on the [accessLogSetting/format](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html#format) property on the [stage](https://docs.aws.amazon.com/apigateway/latest/api/API_Stage.html). 

Examples of some commonly used access log formats are shown in the API Gateway console and are listed as follows.
+ `CLF` ([Common Log Format](https://httpd.apache.org/docs/current/logs.html#common)):

  ```
  $context.identity.sourceIp $context.identity.caller $context.identity.user [$context.requestTime]"$context.httpMethod $context.resourcePath $context.protocol" $context.status $context.responseLength $context.requestId $context.extendedRequestId
  ```
+  `JSON`: 

  ```
  { "requestId":"$context.requestId", "extendedRequestId":"$context.extendedRequestId","ip": "$context.identity.sourceIp", "caller":"$context.identity.caller", "user":"$context.identity.user", "requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod", "resourcePath":"$context.resourcePath", "status":"$context.status", "protocol":"$context.protocol", "responseLength":"$context.responseLength" }
  ```
+ `XML`: 

  ```
  <request id="$context.requestId"> <extendedRequestId>$context.extendedRequestId</extendedRequestId> <ip>$context.identity.sourceIp</ip> <caller>$context.identity.caller</caller> <user>$context.identity.user</user> <requestTime>$context.requestTime</requestTime> <httpMethod>$context.httpMethod</httpMethod> <resourcePath>$context.resourcePath</resourcePath> <status>$context.status</status> <protocol>$context.protocol</protocol> <responseLength>$context.responseLength</responseLength> </request>
  ```
+ `CSV` (comma-separated values):

  ```
  $context.identity.sourceIp,$context.identity.caller,$context.identity.user,$context.requestTime,$context.httpMethod,$context.resourcePath,$context.protocol,$context.status,$context.responseLength,$context.requestId,$context.extendedRequestId
  ```

## Permissions for CloudWatch logging
<a name="set-up-access-logging-permissions"></a>

To enable CloudWatch Logs, you must grant API Gateway permission to read and write logs to CloudWatch for your account. The [AmazonAPIGatewayPushToCloudWatchLogs](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonAPIGatewayPushToCloudWatchLogs.html) has all the required permissions.

**Note**  
API Gateway calls AWS Security Token Service in order to assume the IAM role, so make sure that AWS STS is enabled for the Region. For more information, see [Managing AWS STS in an AWS Region](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html).

To grant these permissions to your account, create an IAM role with `apigateway.amazonaws.com` as its trusted entity, attach the preceding policy to the IAM role, and set the IAM role ARN on the [cloudWatchRoleArn](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateAccount.html#cloudWatchRoleArn) property on your [Account](https://docs.aws.amazon.com/apigateway/latest/api/API_GetAccount.html). You must set the [cloudWatchRoleArn](https://docs.aws.amazon.com/apigateway/latest/api/API_UpdateAccount.html#cloudWatchRoleArn) property separately for each AWS Region in which you want to enable CloudWatch Logs.

If you receive an error when setting the IAM role ARN, check your AWS Security Token Service account settings to make sure that AWS STS is enabled in the Region that you're using. For more information about enabling AWS STS, see [Managing AWS STS in an AWS Region](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html#sts-regions-activate-deactivate) in the *IAM User Guide*.

## Set up CloudWatch API logging using the API Gateway console
<a name="set-up-access-logging-using-console"></a>

To set up CloudWatch API logging, you must have deployed the API to a stage. You must also have configured [an appropriate CloudWatch Logs role](#set-up-access-logging-permissions) ARN for your account. 

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. On the main navigation pane, choose **Settings**, and then under **Logging**, choose **Edit**. 

1. For **CloudWatch log role ARN**, enter an ARN of an IAM role with appropriate permissions. You need to do this once for each AWS account that creates APIs using API Gateway. 

1. In the main navigation pane, choose **APIs**, and then do one of the following:

   1.  Choose an existing API, and then choose a stage.

   1.  Create an API, and then deploy it to a stage.

1. In the main navigation pane, choose **Stages**.

1.  In the **Logs and tracing** section, choose **Edit**.

1. To enable execution logging:

   1. Select a logging level from the **CloudWatch Logs** dropdown menu. The logging levels are the following:
      + **Off** – Logging is not turned on for this stage. 
      + **Errors only** – Logging is enabled for errors only. 
      + **Errors and info logs** – Logging is enabled for all events.

   1. (Optional) Select **Data tracing** to turn on data trace logging for your stage. This can be useful to troubleshoot APIs, but can result in logging sensitive data.
**Note**  
We recommend that you don't use **Data tracing** for production APIs.

   1. (Optional) Select **Detailed metrics** to turn on detailed CloudWatch metrics.

   For more information about CloudWatch metrics, see [Monitor REST API execution with Amazon CloudWatch metrics](monitoring-cloudwatch.md).

1. To enable access logging:

   1. Turn on **Custom access logging**.

   1. For **Access log destination ARN**, enter the ARN of a log group. The ARN format is `arn:aws:logs:{region}:{account-id}:log-group:log-group-name`.

   1. For **Log Format**, enter a log format. You can choose **CLF**, **JSON**, **XML**, or **CSV**. To learn more about example log formats, see [CloudWatch log formats for API Gateway](#apigateway-cloudwatch-log-formats).

1. Choose **Save changes**.

**Note**  
You can enable execution logging and access logging independently of each other.

API Gateway is now ready to log requests to your API. You don't need to redeploy the API when you update the stage settings, logs, or stage variables. 

## Set up CloudWatch API logging using CloudFormation
<a name="set-up-access-logging-using-cloudformation"></a>

Use the following example CloudFormation template to create an Amazon CloudWatch Logs log group and configure execution and access logging for a stage. To enable CloudWatch Logs, you must grant API Gateway permission to read and write logs to CloudWatch for your account. To learn more, see [Associate account with IAM role](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-account.html#aws-resource-apigateway-account--examples) in the *AWS CloudFormation User Guide*.

```
  TestStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      StageName: test
      RestApiId: !Ref MyAPI
      DeploymentId: !Ref Deployment
      Description: "test stage description"
      MethodSettings:
        - ResourcePath: "/*"
          HttpMethod: "*"
          LoggingLevel: INFO
      AccessLogSetting:
        DestinationArn: !GetAtt MyLogGroup.Arn
        Format: $context.extendedRequestId $context.identity.sourceIp $context.identity.caller $context.identity.user [$context.requestTime] "$context.httpMethod $context.resourcePath $context.protocol" $context.status $context.responseLength $context.requestId
  MyLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Join
        - '-'
        - - !Ref MyAPI
          - access-logs
```

# Log REST API calls to Amazon Data Firehose in API Gateway
<a name="apigateway-logging-to-kinesis"></a>

To help debug issues related to client access to your API, you can log API calls to Amazon Data Firehose. For more information about Firehose, see [What Is Amazon Data Firehose?](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html).

For access logging, you can only enable CloudWatch or Firehose—you can't enable both. However, you can enable CloudWatch for execution logging and Firehose for access logging.

**Topics**
+ [Firehose log formats for API Gateway](#apigateway-kinesis-log-formats)
+ [Permissions for Firehose logging](#set-up-kinesis-access-logging-permissions)
+ [Set up Firehose access logging by using the API Gateway console](#set-up-kinesis-access-logging-using-console)

## Firehose log formats for API Gateway
<a name="apigateway-kinesis-log-formats"></a>

Firehose logging uses the same format as [CloudWatch logging](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html).

## Permissions for Firehose logging
<a name="set-up-kinesis-access-logging-permissions"></a>

When Firehose access logging is enabled on a stage, API Gateway creates a service-linked role in your account if the role doesn't exist already. The role is named `AWSServiceRoleForAPIGateway` and has the `APIGatewayServiceRolePolicy` managed policy attached to it. For more information about service-linked roles, see [Using Service-Linked Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html).

**Note**  
The name of your Firehose stream must be `amazon-apigateway-{your-stream-name}`.

## Set up Firehose access logging by using the API Gateway console
<a name="set-up-kinesis-access-logging-using-console"></a>

To set up API logging, you must have deployed the API to a stage. You must also have created a Firehose stream. 

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1.  Do one of the following:

   1.  Choose an existing API, and then choose a stage.

   1.  Create an API and deploy it to a stage.

1. In the main navigation pane, choose **Stages**.

1.  In the **Logs and tracing** section, choose **Edit**.

1. To enable access logging to a Firehose stream:

   1. Turn on **Custom access logging**.

   1. For **Access log destination ARN**, enter the ARN of a Firehose stream. The ARN format is `arn:aws:firehose:{region}:{account-id}:deliverystream/amazon-apigateway-{your-stream-name}`.
**Note**  
The name of your Firehose stream must be `amazon-apigateway-{your-stream-name}`.

   1. For **Log format**, enter a log format. You can choose **CLF**, **JSON**, **XML**, or **CSV**. To learn more about example log formats, see [CloudWatch log formats for API Gateway](set-up-logging.md#apigateway-cloudwatch-log-formats).

1. Choose **Save changes**.

API Gateway is now ready to log requests to your API to Firehose. You don't need to redeploy the API when you update the stage settings, logs, or stage variables. 

# Variables for access logging for API Gateway
<a name="api-gateway-variables-for-access-logging"></a>

 In access logging, you, as an API developer, want to log who has accessed your API and how the caller accessed the API. You can create your own log group or choose an existing log group that could be managed by API Gateway. To specify the access details, you can use the following case-sensitive `$context` variables.

For a list of reference variables for data transformations, see [Variables for data transformations for API Gateway](api-gateway-mapping-template-reference.md).


| Parameter | Description | 
| --- | --- | 
| \$1context.accountId |  The API owner's AWS account ID.  | 
| \$1context.apiId |  The identifier API Gateway assigns to your API.  | 
| \$1context.authorize.error | The authorization error message. | 
| \$1context.authorize.latency | The authorization latency in ms. | 
| \$1context.authorize.status | The status code returned from an authorization attempt. | 
| \$1context.authorizer.claims.property |  A property of the claims returned from the Amazon Cognito user pool after the method caller is successfully authenticated. For more information, see [Control access to REST APIs using Amazon Cognito user pools as an authorizer](apigateway-integrate-with-cognito.md).  Calling `$context.authorizer.claims` returns null.   | 
| \$1context.authorizer.error | The error message returned from an authorizer. | 
| \$1context.authorizer.integrationLatency | The authorizer integration latency in ms. | 
| \$1context.authorizer.integrationStatus | The status code returned from a Lambda authorizer. | 
| \$1context.authorizer.latency | The authorizer latency in ms. | 
| \$1context.authorizer.principalId |  The principal user identification associated with the token sent by the client and returned from an API Gateway Lambda authorizer (formerly known as a custom authorizer). For more information, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).  | 
| \$1context.authorizer.property |  The stringified value of the specified key-value pair of the `context` map returned from an API Gateway Lambda authorizer function. For example, if the authorizer returns the following `context` map:  <pre>"context" : {<br />  "key": "value",<br />  "numKey": 1,<br />  "boolKey": true<br />}</pre> Calling `$context.authorizer.key` returns the `"value"` string, calling `$context.authorizer.numKey` returns the `"1"` string, and calling `$context.authorizer.boolKey` returns the `"true"` string. For *property*, the only supported special character is the underscore `(_)` character. For more information, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).  | 
| \$1context.authorizer.requestId | The AWS endpoint's request ID. | 
| \$1context.authorizer.status | The status code returned from an authorizer. | 
| \$1context.authenticate.error | The error message returned from an authentication attempt. | 
| \$1context.authenticate.latency | The authentication latency in ms. | 
| \$1context.authenticate.status | The status code returned from an authentication attempt. | 
| \$1context.awsEndpointRequestId |  The AWS endpoint's request ID.  | 
| \$1context.cipherSuite |  The cipher, in IANA format, that is negotiated during the TLS handshake between the client and API Gateway.  | 
| \$1context.customDomain.basePathMatched |  The path for an API mapping that an incoming request matched. Applicable when a client uses a custom domain name to access an API. For example if a client sends a request to `https://api.example.com/v1/orders/1234`, and the request matches the API mapping with the path `v1/orders`, the value is `v1/orders`. To learn more, see [Use API mappings to connect API stages to a custom domain name for REST APIs](rest-api-mappings.md).  | 
| \$1context.customDomain.routingRuleIdMatched | The routing rule that an incoming request matched. Applicable when a client uses a custom domain name to access an API. To learn more, see [Routing rules to connect API stages to a custom domain name for REST APIs](rest-api-routing-rules.md). | 
| \$1context.deploymentId | The ID of the API deployment. | 
| \$1context.domainName |  The full domain name used to invoke the API. This should be the same as the incoming `Host` header.  | 
| \$1context.domainPrefix |  The first label of the `$context.domainName`.  | 
| \$1context.endpointType | The endpoint type of the API. | 
| \$1context.error.message |  A string containing an API Gateway error message. This variable can only be used for simple variable substitution in a [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) body-mapping template, which is not processed by the Velocity Template Language engine, and in access logging. For more information, see [Monitor WebSocket API execution with CloudWatch metrics](apigateway-websocket-api-logging.md) and [Setting up gateway responses to customize error responses](api-gateway-gatewayResponse-definition.md#customize-gateway-responses).  | 
| \$1context.error.messageString | The quoted value of \$1context.error.message, namely "\$1context.error.message". | 
| \$1context.error.responseType |  A [type](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseType) of [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html). This variable can only be used for simple variable substitution in a [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) body-mapping template, which is not processed by the Velocity Template Language engine, and in access logging. For more information, see [Monitor WebSocket API execution with CloudWatch metrics](apigateway-websocket-api-logging.md) and [Setting up gateway responses to customize error responses](api-gateway-gatewayResponse-definition.md#customize-gateway-responses).  | 
| \$1context.error.validationErrorString |  A string containing a detailed validation error message.  | 
| \$1context.extendedRequestId | The extended ID that API Gateway generates and assigns to the API request. The extended request ID contains useful information for debugging and troubleshooting. | 
| \$1context.httpMethod |  The HTTP method used. Valid values include: `DELETE`, `GET`, `HEAD`, `OPTIONS`, `PATCH`, `POST`, and `PUT`.  | 
| \$1context.identity.accountId |  The AWS account ID associated with the request.  | 
| \$1context.identity.apiKey |  For API methods that require an API key, this variable is the API key associated with the method request. For methods that don't require an API key, this variable is null. For more information, see [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md).  | 
| \$1context.identity.apiKeyId | The API key ID associated with an API request that requires an API key. | 
| \$1context.identity.caller |  The principal identifier of the caller that signed the request. Supported for resources that use IAM authorization.  | 
| \$1context.identity.cognitoAuthenticationProvider |  A comma-separated list of all the Amazon Cognito authentication providers used by the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  For example, for an identity from an Amazon Cognito user pool, `cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` For information about the available Amazon Cognito authentication providers, see [Using Federated Identities](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) in the *Amazon Cognito Developer Guide*. | 
| \$1context.identity.cognitoAuthenticationType |  The Amazon Cognito authentication type of the caller making the request. Available only if the request was signed with Amazon Cognito credentials. Possible values include `authenticated` for authenticated identities and `unauthenticated` for unauthenticated identities. | 
| \$1context.identity.cognitoIdentityId |  The Amazon Cognito identity ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.cognitoIdentityPoolId |  The Amazon Cognito identity pool ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.principalOrgId |  The [AWS organization ID](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html).  | 
| \$1context.identity.sourceIp |  The source IP address of the immediate TCP connection making the request to the API Gateway endpoint.  | 
| \$1context.identity.clientCert.clientCertPem |  The PEM-encoded client certificate that the client presented during mutual TLS authentication. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.subjectDN |  The distinguished name of the subject of the certificate that a client presents. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.issuerDN |  The distinguished name of the issuer of the certificate that a client presents. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.serialNumber |  The serial number of the certificate. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.validity.notBefore |  The date before which the certificate is invalid. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.validity.notAfter |  The date after which the certificate is invalid. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
|  \$1context.identity.vpcId | The VPC ID of the VPC making the request to the API Gateway endpoint. | 
|  \$1context.identity.vpceId |  The VPC endpoint ID of the VPC endpoint making the request to the API Gateway endpoint. Present only when you have a private API.  | 
| \$1context.identity.user |  The principal identifier of the user that will be authorized against resource access. Supported for resources that use IAM authorization.  | 
| \$1context.identity.userAgent |  The [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) header of the API caller.  | 
| \$1context.identity.userArn |  The Amazon Resource Name (ARN) of the effective user identified after authentication. For more information, see [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html).  | 
| \$1context.integration.error | The error message returned from an integration. | 
| \$1context.integration.integrationStatus | For Lambda proxy integration, the status code returned from AWS Lambda, not from the backend Lambda function code. | 
| \$1context.integration.latency | The integration latency in ms. Equivalent to \$1context.integrationLatency. | 
| \$1context.integration.requestId | The AWS endpoint's request ID. Equivalent to \$1context.awsEndpointRequestId. | 
| \$1context.integration.responseTransferMode | The response transfer mode of your integration. This can be either BUFFERED or STREAMED. | 
| \$1context.integration.status | The status code returned from an integration. For Lambda proxy integrations, this is the status code that your Lambda function code returns.  | 
| \$1context.integration.timeToAllHeaders | The time between when API Gateway establishes the integration connection to when it receives all integration response headers from the client.  | 
| \$1context.integration.timeToFirstContent | The time between when API Gateway establishes the integration connection to when it receives the first content bytes. | 
| \$1context.integrationLatency | The integration latency in ms. | 
| \$1context.integrationStatus | For Lambda proxy integration, this parameter represents the status code returned from AWS Lambda, not from the backend Lambda function code. | 
| \$1context.isCanaryRequest |  Returns `true` if the request was directed to the canary and `false` if the request was not directed to the canary. Present only when you have a canary enabled. | 
| \$1context.path | The request path. For example, for a non-proxy request URL of https://\$1rest-api-id\$1.execute-api.\$1region\$1.amazonaws.com/\$1stage\$1/root/child, the \$1context.path value is /\$1stage\$1/root/child.  | 
| \$1context.protocol | The request protocol, for example, HTTP/1.1.  API Gateway APIs can accept HTTP/2 requests, but API Gateway sends requests to backend integrations using HTTP/1.1. As a result, the request protocol is logged as HTTP/1.1 even if a client sends a request that uses HTTP/2.   | 
| \$1context.requestId |  An ID for the request. Clients can override this request ID. Use `$context.extendedRequestId` for a unique request ID that API Gateway generates.  | 
| \$1context.requestOverride.header.header\$1name |  The request header override. If this parameter is defined, it contains the headers to be used instead of the **HTTP Headers** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.requestOverride.path.path\$1name |  The request path override. If this parameter is defined, it contains the request path to be used instead of the **URL Path Parameters** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.requestOverride.querystring.querystring\$1name |  The request query string override. If this parameter is defined, it contains the request query strings to be used instead of the **URL Query String Parameters** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.responseLatency | The response latency in ms. | 
| \$1context.responseLength | The response payload length in bytes. | 
| \$1context.responseOverride.header.header\$1name | The response header override. If this parameter is defined, it contains the header to be returned instead of the Response header that is defined as the Default mapping in the Integration Response pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md). | 
| \$1context.responseOverride.status | The response status code override. If this parameter is defined, it contains the status code to be returned instead of the Method response status that is defined as the Default mapping in the Integration Response pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md). | 
| \$1context.requestTime | The [CLF](https://httpd.apache.org/docs/current/logs.html#common)-formatted request time (dd/MMM/yyyy:HH:mm:ss \$1-hhmm). | 
| \$1context.requestTimeEpoch | The [Epoch](https://en.wikipedia.org/wiki/Unix_time)-formatted request time, in milliseconds. | 
| \$1context.resourceId |  The identifier that API Gateway assigns to your resource.  | 
| \$1context.resourcePath |  The path to your resource. For example, for the non-proxy request URI of `https://{rest-api-id}.execute-api.{region}.amazonaws.com/{stage}/root/child`, The `$context.resourcePath` value is `/root/child`. For more information, see [Tutorial: Create a REST API with an HTTP non-proxy integration](api-gateway-create-api-step-by-step.md).   | 
| \$1context.stage |  The deployment stage of the API request (for example, `Beta` or `Prod`).  | 
| \$1context.status | The method response status. | 
| \$1context.tlsVersion |  The TLS version that is negotiated during the TLS handshake between the client and API Gateway. | 
| \$1context.waf.error | The error message returned from AWS WAF. | 
| \$1context.waf.latency | The AWS WAF latency in ms. | 
| \$1context.waf.status | The status code returned from AWS WAF. | 
| \$1context.xrayTraceId |  The trace ID for the X-Ray trace. For more information, see [Set up AWS X-Ray with API Gateway REST APIs](apigateway-enabling-xray.md).  | 
| \$1context.wafResponseCode |  The response received from [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html): `WAF_ALLOW` or `WAF_BLOCK`. Will not be set if the stage is not associated with a web ACL. For more information, see [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md).  | 
| \$1context.webaclArn |  The complete ARN of the web ACL that is used to decide whether to allow or block the request. Will not be set if the stage is not associated with a web ACL. For more information, see [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md).  | 

# Trace user requests to REST APIs using X-Ray in API Gateway
<a name="apigateway-xray"></a>

You can use [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-services-apigateway.html) to trace and analyze user requests as they travel through your Amazon API Gateway REST APIs to the underlying services. API Gateway supports X-Ray tracing for all API Gateway REST API endpoint types: Regional, edge-optimized, and private. You can use X-Ray with Amazon API Gateway in all AWS Regions where X-Ray is available.

Because X-Ray gives you an end-to-end view of an entire request, you can analyze latencies in your APIs and their backend services. You can use an X-Ray service map to view the latency of an entire request and that of the downstream services that are integrated with X-Ray. You can also configure sampling rules to tell X-Ray which requests to record and at what sampling rates, according to criteria that you specify. 

If you call an API Gateway API from a service that's already being traced, API Gateway passes the trace through, even if X-Ray tracing isn't enabled on the API.

You can enable X-Ray for an API stage by using the API Gateway console, or by using the API Gateway API or CLI.

**Topics**
+ [Set up AWS X-Ray with API Gateway REST APIs](apigateway-enabling-xray.md)
+ [Use AWS X-Ray service maps and trace views with API Gateway](apigateway-using-xray-maps.md)
+ [Configure AWS X-Ray sampling rules for API Gateway APIs](apigateway-configuring-xray-sampling-rules.md)
+ [AWS X-Ray traces for Amazon API Gateway APIs](apigateway-understanding-xray-traces.md)

# Set up AWS X-Ray with API Gateway REST APIs
<a name="apigateway-enabling-xray"></a>

In this section you can find detailed information on how to set up [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-services-apigateway.html) with API Gateway REST APIs.

**Topics**
+ [X-Ray tracing modes for API Gateway](#apigateway-tracing-modes)
+ [Permissions for X-Ray tracing](#set-up-xray-tracing-permissions)
+ [Enabling X-Ray tracing in the API Gateway console](#apigateway-xray-console-setup)
+ [Enabling AWS X-Ray tracing using the API Gateway CLI](#apigateway-xray-cli-setup)

## X-Ray tracing modes for API Gateway
<a name="apigateway-tracing-modes"></a>

The path of a request through your application is tracked with a trace ID. A trace collects all of the segments generated by a single request, typically an HTTP `GET` or `POST` request.

There are two modes of tracing for an API Gateway API:
+ **Passive**: This is the default setting if you have not enabled X-Ray tracing on an API stage. This approach means that the API Gateway API is only traced if X-Ray has been enabled on an upstream service.
+ **Active**: When an API Gateway API stage has this setting, API Gateway automatically samples API invocation requests, based on the sampling algorithm specified by X-Ray.

  When active tracing is enabled on a stage, API Gateway creates a service-linked role in your account, if the role does not exist already. The role is named `AWSServiceRoleForAPIGateway` and will have the `APIGatewayServiceRolePolicy` managed policy attached to it. For more information about service-linked roles, see [Using Service-Linked Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html).
**Note**  
X-Ray applies a sampling algorithm to ensure that tracing is efficient, while still providing a representative sample of the requests that your API receives. The default sampling algorithm is 1 request per second, with 5 percent of requests sampled past that limit.

You can change the tracing mode for your API by using the API Gateway management console, the API Gateway CLI, or an AWS SDK.

## Permissions for X-Ray tracing
<a name="set-up-xray-tracing-permissions"></a>

When you enable X-Ray tracing on a stage, API Gateway creates a service-linked role in your account, if the role does not exist already. The role is named `AWSServiceRoleForAPIGateway` and will have the `APIGatewayServiceRolePolicy` managed policy attached to it. For more information about service-linked roles, see [Using Service-Linked Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html).

## Enabling X-Ray tracing in the API Gateway console
<a name="apigateway-xray-console-setup"></a>

You can use the Amazon API Gateway console to enable active tracing on an API stage.

These steps assume that you have already deployed the API to a stage.

1. Sign in to the API Gateway console at [https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway).

1. Choose your API, and then in the main navigation pane, choose **Stages**.

1. In the **Stages** pane, choose a stage.

1. In the **Logs and tracing** section, choose **Edit**.

1. To enable active X-Ray tracing, select **X-Ray tracing** to turn on X-Ray tracing.

1. Choose **Save changes**.

Once you've enabled X-Ray for your API stage, you can use the X-Ray management console to view the traces and service maps.

## Enabling AWS X-Ray tracing using the API Gateway CLI
<a name="apigateway-xray-cli-setup"></a>

The following [create-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-stage.html) command creates a stage with active X-Ray tracing:

```
aws apigateway create-stage \
    --rest-api-id rest-api-id \
    --stage-name stage-name \
    --deployment-id deployment-id \
    --region region \
    --tracing-enabled=true
```

The output will look like the following:

```
{
    "tracingEnabled": true, 
    "stageName": stage-name, 
    "cacheClusterEnabled": false, 
    "cacheClusterStatus": "NOT_AVAILABLE", 
    "deploymentId": deployment-id, 
    "lastUpdatedDate": 1533849811, 
    "createdDate": 1533849811, 
    "methodSettings": {}
}
```

The following [create-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-stage.html) command creates a stage without active X-Ray tracing:

```
aws apigateway create-stage \
    --rest-api-id rest-api-id \
    --stage-name stage-name \
    --deployment-id deployment-id \
    --region region \
    --tracing-enabled=false
```

The output will look like the following:

```
{
    "tracingEnabled": false, 
    "stageName": stage-name, 
    "cacheClusterEnabled": false, 
    "cacheClusterStatus": "NOT_AVAILABLE", 
    "deploymentId": deployment-id, 
    "lastUpdatedDate": 1533849811, 
    "createdDate": 1533849811, 
    "methodSettings": {}
}
```

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) turns on active X-Ray tracing for a deployed API: 

```
aws apigateway update-stage \
    --rest-api-id rest-api-id \
    --stage-name stage-name \
    --patch-operations op=replace,path=/tracingEnabled,value=true
```

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-stage.html) turns off active X-Ray tracing for a deployed API: 

```
aws apigateway update-stage \
    --rest-api-id rest-api-id \
    --stage-name stage-name \
    --region region \
    --patch-operations op=replace,path=/tracingEnabled,value=false
```

The output will look like the following:

```
{
    "tracingEnabled": false, 
    "stageName": stage-name, 
    "cacheClusterEnabled": false, 
    "cacheClusterStatus": "NOT_AVAILABLE", 
    "deploymentId": deployment-id, 
    "lastUpdatedDate": 1533850033, 
    "createdDate": 1533849811, 
    "methodSettings": {}
}
```

Once you've enabled X-Ray for your API stage, use the X-Ray CLI to retrieve trace information. For more information, see [Using the X-Ray API with the AWS CLI](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-api.html#xray-api-tutorial).

# Use AWS X-Ray service maps and trace views with API Gateway
<a name="apigateway-using-xray-maps"></a>

In this section you can find detailed information on how to use [AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-services-apigateway.html) service maps and trace views with API Gateway.

**Topics**
+ [Example X-Ray service map](#apigateway-using-xray-maps-active)
+ [Example X-Ray trace view](#apigateway-using-xray-trace-view-active)

## Example X-Ray service map
<a name="apigateway-using-xray-maps-active"></a>

AWS X-Ray service maps show information about your API and all of its downstream services. When X-Ray is enabled for an API stage in API Gateway, you'll see a node in the service map containing information about the overall time spent in the API Gateway service. You can get detailed information about the response status and a histogram of the API response time for the selected timeframe. For APIs integrating with AWS services such as AWS Lambda and Amazon DynamoDB, you will see more nodes providing performance metrics related to those services. There will be a service map for each API stage.

The following example shows a service map for the `test` stage of an API called `xray`. This API has two Lambda integrations. The nodes represent the API Gateway service and the two Lambda functions.

For a detailed explanation of service map structure, see [Use the X-Ray trace map](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html#xray-console-servicemap).

![\[Service map example of an API Gateway API stage\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/apigateway-xray-servicemap-2.png)


From the service map, you can zoom in to see a trace view of your API stage. The trace will display in-depth information regarding your API, represented as segments and subsegments. For example, the trace for the service map shown above would include segments for the Lambda service and Lambda function. For more information, see [AWS Lambda and AWS X-Ray](https://docs.aws.amazon.com/xray/latest/devguide/xray-services-lambda.html).

If you choose a node or edge on an X-Ray service map, the X-Ray console shows a latency distribution histogram. You can use a latency histogram to see how long it takes for a service to complete its requests. Following is a histogram of the API Gateway stage named `xray/test` in the previous service map. For a detailed explanation of latency distribution histograms, see [Use Latency Histograms](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html#xray-console-histograms).

![\[X-Ray histogram of an API Gateway API stage\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/apigateway-xray-histogram-1.png)


## Example X-Ray trace view
<a name="apigateway-using-xray-trace-view-active"></a>

The following diagram shows a trace view generated for the example API described above, with a Lambda backend function. A successful API method request is shown with a response code of 200.

For a detailed explanation of trace views, see [View traces and trace details](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html#xray-console-traces).

![\[API Gateway with active tracing enabled\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/apigateway-xray-traceview-1.png)


# Configure AWS X-Ray sampling rules for API Gateway APIs
<a name="apigateway-configuring-xray-sampling-rules"></a>

You can use AWS X-Ray console or SDK to configure sampling rules for your Amazon API Gateway API. A sampling rule specifies which requests X-Ray should record for your API. By customizing sampling rules, you can control the amount of data that you record, and modify sampling behavior on the fly without modifying or redeploying your code.

Before you specify your X-Ray sampling rules, read the following topics in the X-Ray Developer Guide:
+ [Configure sampling rules](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html#xray-console-sampling)
+ [Using Sampling Rules with the X-Ray API](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-api.html#xray-api-sampling)

**Topics**
+ [X-Ray sampling rule option values for API Gateway APIs](#apigateway-xray-sampling-rule-options)
+ [X-Ray sampling rule examples](#apigateway-xray-sampling-rules-examples)

## X-Ray sampling rule option values for API Gateway APIs
<a name="apigateway-xray-sampling-rule-options"></a>

The following X-Ray sampling options are relevant for API Gateway. String values can use wildcards to match a single character (?) or zero or more characters (\$1). For more details, including a detailed explanation of how the **Reservoir** and **Rate** settings are used, [Configure sampling rules](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html#xray-console-sampling).
+ **Rule name** (string) — A unique name for the rule.
+ **Priority** (integer between 1 and 9999) — The priority of the sampling rule. Services evaluate rules in ascending order of priority, and make a sampling decision with the first rule that matches.
+ **Reservoir** (nonnegative integer) — A fixed number of matching requests to instrument per second, before applying the fixed rate. The reservoir is not used directly by services, but applies to all services using the rule collectively.
+ **Rate** (number between 0 and 100) — The percentage of matching requests to instrument, after the reservoir is exhausted.
+ **Service name** (string) — API stage name, in the form ***\$1api-name\$1*/*\$1stage-name\$1***. For example, if you were to deploy the [PetStore](api-gateway-create-api-from-example.md) sample API to a stage named `test`, the **Service name** value to specify in your sampling rule would be **pets/test**.
+ **Service type** (string) — For an API Gateway API, either **AWS::ApiGateway::Stage** or **AWS::ApiGateway::\$1** can be specified.
+ **Host** (string) — The hostname from the HTTP host header. Set this to **\$1** to match against all hostnames. Or you can specify a full or partial hostname to match, for example, **api.example.com** or **\$1.example.com**.
+ **Resource ARN** (string) — The ARN of the API stage, for example, **arn:aws:apigateway:*region*::/restapis/*api-id*/stages/*stage-name***.

  The stage name can be obtained from the console or the API Gateway CLI or API. For more information about ARN formats, see the [Amazon Web Services General Reference](https://docs.aws.amazon.com/general/latest/gr/).
+ **HTTP method** (string) — The method to be sampled, for example, **GET**.
+ **URL path** (string) — The URL path of the request.
+ (optional) **Attributes** (key and value) — Headers from the original HTTP request, for example, **Connection**, **Content-Length**, or **Content-Type**. Each attribute value can be up to 32 characters long.

## X-Ray sampling rule examples
<a name="apigateway-xray-sampling-rules-examples"></a>

**Sampling rule example \$11**

This rule samples all `GET` requests for the `testxray` API at the `test` stage.
+ **Rule name — ****test-sampling**
+ **Priority — ****17**
+ **Reservoir size — ****10**
+ **Fixed rate — ****10**
+ **Service name — ****testxray/test**
+ **Service type — ****AWS::ApiGateway::Stage**
+ **HTTP method — ****GET**
+ **Resource ARN — ****\$1**
+ **Host — ****\$1**

**Sampling rule example \$12**

This rule samples all requests for the `testxray` API at the `prod` stage.
+ **Rule name — ****prod-sampling**
+ **Priority — ****478**
+ **Reservoir size — ****1**
+ **Fixed rate — ****60**
+ **Service name — ****testxray/prod**
+ **Service type — ****AWS::ApiGateway::Stage**
+ **HTTP method — ****\$1**
+ **Resource ARN — ****\$1**
+ **Host — ****\$1**
+ **Attributes** — **\$1\$1**

# AWS X-Ray traces for Amazon API Gateway APIs
<a name="apigateway-understanding-xray-traces"></a>

This section discusses AWS X-Ray trace segments, subsegments, and other trace fields for Amazon API Gateway APIs.

Before you read this section, review the following topics in the X-Ray Developer Guide:
+  [Use an AWS Management Console](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html)
+  [X-Ray segment documents](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-api.html#xray-api-segmentdocuments)
+ [Concepts](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html#xray-concepts)

**Topics**
+ [Examples of trace objects for an API Gateway API](#apigateway-understanding-xray-traces-example-segments)
+ [Understanding the trace](#apigateway-understanding-xray-traces-segments)

## Examples of trace objects for an API Gateway API
<a name="apigateway-understanding-xray-traces-example-segments"></a>

This section discusses some of the objects you may see in a trace for an API Gateway API.

**Annotations**

Annotations can appear in segments and subsegments. They are used as filtering expressions in sampling rules to filter traces. For more information, see [Configure sampling rules](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html#xray-console-sampling).

Following is an example of an `annotations` object, in which an API stage is identified by the API ID and the API stage name:

```
"annotations": {
    "aws:api_id": "a1b2c3d4e5",
    "aws:api_stage": "dev"
}
```

For more information about annotations, see [X-Ray segment documents](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-api.html#xray-api-segmentdocuments), and then choose **X-Ray segment documents**, **Annotations**.

**AWS resource data**

The `aws` object appears only in segments. Following is an example of an `aws` object that matches the Default sampling rule. For an in-depth explanation of sampling rules, see [Configure sampling rules](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-console.html#xray-console-sampling).

```
"aws": {
    "xray": {
        "sampling_rule_name": "Default"
    },
    "api_gateway": {
        "account_id": "123412341234",
        "rest_api_id": "a1b2c3d4e5",
        "stage": "dev",
        "request_id": "a1b2c3d4-a1b2-a1b2-a1b2-a1b2c3d4e5f6"
    }
}
```

For more information about the `aws` object, see [X-Ray segment documents](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-api.html#xray-api-segmentdocuments), and then choose **X-Ray segment documents**, **AWS resource data**.

## Understanding the trace
<a name="apigateway-understanding-xray-traces-segments"></a>

Following is a trace segment for an API Gateway stage. For a detailed explanation of the fields that make up the trace segment, see [X-Ray segment documents](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray-interface-api.html#xray-api-segmentdocuments).

```
        {
            "Document": {
                "id": "a1b2c3d4a1b2c3d4",
                "name": "testxray/dev",
                "start_time": 1533928226.229,
                "end_time": 1533928226.614,
                "metadata": {
                    "default": {
                        "extended_request_id": "abcde12345abcde=",
                        "request_id": "a1b2c3d4-a1b2-a1b2-a1b2-a1b2c3d4e5f6"
                    }
                },
                "http": {
                    "request": {
                        "url": "https://example.com/dev?username=demo&message=hellofromdemo/",
                        "method": "GET",
                        "client_ip": "192.0.2.0",
                        "x_forwarded_for": true
                    },
                    "response": {
                        "status": 200,
                        "content_length": 0
                    }
                },
                "aws": {
                    "xray": {
                        "sampling_rule_name": "Default"
                    },
                    "api_gateway": {
                        "account_id": "123412341234",
                        "rest_api_id": "a1b2c3d4e5",
                        "stage": "dev",
                        "request_id": "a1b2c3d4-a1b2-a1b2-a1b2-a1b2c3d4e5f6"
                    }
                },
                "annotations": {
                    "aws:api_id": "a1b2c3d4e5",
                    "aws:api_stage": "dev"
                },
                "trace_id": "1-a1b2c3d4-a1b2c3d4a1b2c3d4a1b2c3d4",
                "origin": "AWS::ApiGateway::Stage",
                "resource_arn": "arn:aws:apigateway:us-east-1::/restapis/a1b2c3d4e5/stages/dev",
                "subsegments": [
                    {
                        "id": "abcdefgh12345678",
                        "name": "Lambda",
                        "start_time": 1533928226.233,
                        "end_time": 1533928226.6130002,
                        "http": {
                            "request": {
                                "url": "https://example.com/2015-03-31/functions/arn:aws:lambda:us-east-1:123412341234:function:xray123/invocations",
                                "method": "GET"
                            },
                            "response": {
                                "status": 200,
                                "content_length": 62
                            }
                        },
                        "aws": {
                            "function_name": "xray123",
                            "region": "us-east-1",
                            "operation": "Invoke",
                            "resource_names": [
                                "xray123"
                            ]
                        },
                        "namespace": "aws"
                    }
                ]
            },
            "Id": "a1b2c3d4a1b2c3d4"
        }
```