

# API Gateway HTTP APIs
<a name="http-api"></a>

REST APIs and HTTP APIs are both RESTful API products. REST APIs support more features than HTTP APIs, while HTTP APIs are designed with minimal features so that they can be offered at a lower price. For more information, see [Choose between REST APIs and HTTP APIs](http-api-vs-rest.md).

You can use HTTP APIs to send requests to AWS Lambda functions or to any routable HTTP endpoint. For example, you can create an HTTP API that integrates with a Lambda function on the backend. When a client calls your API, API Gateway sends the request to the Lambda function and returns the function's response to the client.

HTTP APIs support [OpenID Connect](https://openid.net/developers/how-connect-works/) and [OAuth 2.0](https://oauth.net/2/) authorization. They come with built-in support for cross-origin resource sharing (CORS) and automatic deployments.

You can create HTTP APIs by using the AWS Management Console, the AWS CLI, APIs, CloudFormation, or SDKs.

**Topics**
+ [

# Develop HTTP APIs in API Gateway
](http-api-develop.md)
+ [

# Publish HTTP APIs for customers to invoke
](http-api-publish.md)
+ [

# Protect your HTTP APIs in API Gateway
](http-api-protect.md)
+ [

# Monitor HTTP APIs in API Gateway
](http-api-monitor.md)
+ [

# Troubleshooting issues with HTTP APIs in API Gateway
](http-api-troubleshooting.md)

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

This section provides details about API Gateway capabilities that you need while you're developing your API Gateway APIs.

As you're developing your API Gateway API, you decide on a number of characteristics of your API. These characteristics depend on the use case of your API. For example, you might want to only allow certain clients to call your API, or you might want it to be available to everyone. You might want an API call to execute a Lambda function, make a database query, or call an application.

**Topics**
+ [

## Create an HTTP API
](#http-api-examples)
+ [

# Create routes for HTTP APIs in API Gateway
](http-api-develop-routes.md)
+ [

# IP address types for HTTP APIs in API Gateway
](http-api-ip-address-type.md)
+ [

# Control and manage access to HTTP APIs in API Gateway
](http-api-access-control.md)
+ [

# Create integrations for HTTP APIs in API Gateway
](http-api-develop-integrations.md)
+ [

# Configure CORS for HTTP APIs in API Gateway
](http-api-cors.md)
+ [

# Transform API requests and responses for HTTP APIs in API Gateway
](http-api-parameter-mapping.md)
+ [

# Use OpenAPI definitions for HTTP APIs in API Gateway
](http-api-open-api.md)

## Create an HTTP API
<a name="http-api-examples"></a>

To create a functional API, you must have at least one route, integration, stage, and deployment.

The following examples show how to create an API with an AWS Lambda or HTTP integration, a route, and a default stage that is configured to automatically deploy changes.

This guide assumes that you're already familiar with API Gateway and Lambda. For a more detailed guide, see [Get started with API Gateway](getting-started.md).

**Topics**
+ [

### Create an HTTP API by using the AWS Management Console
](#apigateway-http-api-create.console)
+ [

### Create an HTTP API by using the AWS CLI
](#http-api-examples.cli.quick-create)

### Create an HTTP API by using the AWS Management Console
<a name="apigateway-http-api-create.console"></a>

1. Open the [API Gateway console](https://console.aws.amazon.com/apigateway).

1. Choose **Create API**.

1. Under **HTTP API**, choose **Build**.

1. Choose **Add integration**, and then choose an AWS Lambda function or enter an HTTP endpoint.

1. For **Name**, enter a name for your API.

1. Choose **Review and create**.

1. Choose **Create**.

Now your API is ready to invoke. You can test your API by entering its invoke URL in a browser, or by using Curl.

```
curl https://api-id.execute-api.us-east-2.amazonaws.com
```

### Create an HTTP API by using the AWS CLI
<a name="http-api-examples.cli.quick-create"></a>

You can use quick create to create an API with a Lambda or HTTP integration, a default catch-all route, and a default stage that is configured to automatically deploy changes. The following [create-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) command uses quick create to create an API that integrates with a Lambda function on the backend.

**Note**  
To invoke a Lambda integration, API Gateway must have the required permissions. You can use a resource-based policy or an IAM role to grant API Gateway permissions to invoke a Lambda function. To learn more, see [AWS Lambda Permissions](https://docs.aws.amazon.com/lambda/latest/dg/lambda-permissions.html) in the * AWS Lambda Developer Guide*.

**Example**  

```
aws apigatewayv2 create-api --name my-api --protocol-type HTTP --target arn:aws:lambda:us-east-2:123456789012:function:function-name
```

Now your API is ready to invoke. You can test your API by entering its invoke URL in a browser, or by using Curl.

```
curl https://api-id.execute-api.us-east-2.amazonaws.com
```

# Create routes for HTTP APIs in API Gateway
<a name="http-api-develop-routes"></a>

Routes direct incoming API requests to backend resources. Routes consist of two parts: an HTTP method and a resource path—for example, `GET /pets`. You can define specific HTTP methods for your route. Or, you can use the `ANY` method to match all methods that you haven't defined for a resource. You can create a `$default` route that acts as a catch-all for requests that don’t match any other routes.

**Note**  
API Gateway decodes URL-encoded request parameters before passing them to your backend integration.

## Working with path variables
<a name="http-api-routes-path-variables"></a>

You can use path variables in HTTP API routes.

For example, the `GET /pets/{petID}` route catches a `GET` request that a client submits to `https://api-id.execute-api.us-east-2.amazonaws.com/pets/6`. 

A *greedy path variable* catches all child resources of a route. To create a greedy path variable, add `+` to the variable name—for example, `{proxy+}`. The greedy path variable must be at the end of the resource path.

## Working with query string parameters
<a name="http-api-routes-query-string-parameters"></a>

By default, API Gateway sends query string parameters to your backend integration if they are included in a request to an HTTP API.

For example, when a client sends a request to `https://api-id.execute-api.us-east-2.amazonaws.com/pets?id=4&type=dog`, the query string parameters `?id=4&type=dog` are sent to your integration.

## Working with the `$default` route
<a name="http-api-develop-routes.default"></a>

The `$default` route catches requests that don't explicitly match other routes in your API.

When the `$default` route receives a request, API Gateway sends the full request path to the integration. For example, you can create an API with only a `$default` route and integrate it on the `ANY` method with the `https://petstore-demo-endpoint.execute-api.com` HTTP endpoint. When you send a request to `https://api-id.execute-api.us-east-2.amazonaws.com/store/checkout`, API Gateway sends a request to `https://petstore-demo-endpoint.execute-api.com/store/checkout`.

To learn more about HTTP integrations, see [Create HTTP proxy integrations for HTTP APIs](http-api-develop-integrations-http.md).

## Routing API requests
<a name="http-api-develop-routes.evaluation"></a>

When a client sends an API request, API Gateway first determines which [stage](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-stages.html) to route the request to. If the request explicitly matches a stage, API Gateway sends the request to that stage. If no stage fully matches the request, API Gateway sends the request to the `$default` stage. If there's no `$default` stage, then the API returns `{"message":"Not Found"}` and does not generate CloudWatch logs.

After selecting a stage, API Gateway selects a route. API Gateway selects the route with the most-specific match, using the following priorities:

1. Full match for a route and method.

1. Match for a route and method with a greedy path variable (`{proxy+}`).

1. The `$default` route.

If no routes match a request, API Gateway returns `{"message":"Not Found"}` to the client.

For example, consider an API with a `$default` stage and the following example routes:

1. `GET /pets/dog/1`

1. `GET /pets/dog/{id}`

1. `GET /pets/{proxy+}`

1. `ANY /{proxy+}`

1. `$default`

   The following table summarizes how API Gateway routes requests to the example routes.


| Request | Selected route | Explanation | 
| --- | --- | --- | 
|  `GET https://api-id.execute-api.region.amazonaws.com/pets/dog/1`  |  `GET /pets/dog/1`  |  The request fully matches this static route.  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/pets/dog/2`  |  `GET /pets/dog/{id}`  |  The request fully matches this route.  | 
|  `GET https://api-id.execute-api.region.amazonaws.com/pets/cat/1`  |  `GET /pets/{proxy+}`  |  The request doesn't fully match a route. The route with a `GET` method and a greedy path variable catches this request.  | 
| `POST https://api-id.execute-api.region.amazonaws.com/test/5` | `ANY /{proxy+}` |  The `ANY` method matches all methods that you haven't defined for a route. Routes with greedy path variables have higher priority than the `$default` route.  | 

# IP address types for HTTP APIs in API Gateway
<a name="http-api-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. You might want to 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).

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

The following considerations might impact your use of IP address types:
+ The default IP address type for HTTP APIs is IPv4.
+ 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. 
+ 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.

## Change the IP address type of an HTTP API
<a name="http-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.

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

**To change the IP address type of an HTTP API**

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

1. Choose an HTTP API.

1. For **API settings**, choose **Edit**.

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

1. Choose **Save**.

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

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

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

```
aws apigatewayv2 update-api \
    --api-id abcd1234 \
    --ip-address-type dualstack
```

The output will look like the following:

```
{
    "ApiEndpoint": "https://abcd1234.execute-api.us-east-1.amazonaws.com",
    "ApiId": "abcd1234",
    "ApiKeySelectionExpression": "$request.header.x-api-key",
    "CreatedDate": "2025-02-04T22:20:20+00:00",
    "DisableExecuteApiEndpoint": false,
    "Name": "My-HTTP-API",
    "ProtocolType": "HTTP",
    "RouteSelectionExpression": "$request.method $request.path",
    "Tags": {},
    "NotificationUris": [],
    "IpAddressType": "dualstack"
}
```

------

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

API Gateway supports multiple mechanisms for controlling and managing access to your HTTP API:
+ **Lambda authorizers** use Lambda functions to control access to APIs. For more information, see [Control access to HTTP APIs with AWS Lambda authorizers](http-api-lambda-authorizer.md).
+ **JWT authorizers** use JSON web tokens to control access to APIs. For more information, see [Control access to HTTP APIs with JWT authorizers in API Gateway](http-api-jwt-authorizer.md).
+ **Standard AWS IAM roles and policies** offer flexible and robust access controls. You can use IAM roles and policies to control who can create and manage your APIs, as well as who can invoke them. For more information, see [Control access to HTTP APIs with IAM authorization in API Gateway](http-api-access-control-iam.md).

To improve your security posture, we recommend that you configure an authorizer for all routes on your HTTP API. 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*.

# Control access to HTTP APIs with AWS Lambda authorizers
<a name="http-api-lambda-authorizer"></a>

You use a Lambda authorizer to use a Lambda function to control access to your HTTP API. Then, when a client calls your API, API Gateway invokes your Lambda function. API Gateway uses the response from your Lambda function to determine whether the client can access your API.

## Payload format version
<a name="http-api-lambda-authorizer.payload-format"></a>

The authorizer payload format version specifies the format of the data that API Gateway sends to a Lambda authorizer, and how API Gateway interprets the response from Lambda. If you don't specify a payload format version, the AWS Management Console uses the latest version by default. If you create a Lambda authorizer by using the AWS CLI, CloudFormation, or an SDK, you must specify an `authorizerPayloadFormatVersion`. The supported values are `1.0` and `2.0`. 

 If you need compatibility with REST APIs, use version `1.0`.

The following examples show the structure of each payload format version.

------
#### [ 2.0 ]

```
{
  "version": "2.0",
  "type": "REQUEST",
  "routeArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": ["user1", "123"],
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": ["cookie1", "cookie2"],
  "headers": {
    "header1": "value1",
    "header2": "value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "authentication": {
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "IP",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "pathParameters": { "parameter1": "value1" },
  "stageVariables": { "stageVariable1": "value1", "stageVariable2": "value2" }
}
```

------
#### [ 1.0 ]

```
{
  "version": "1.0",
  "type": "REQUEST",
  "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": "user1,123",
  "authorizationToken": "user1,123",
  "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"
  }
}
```

------

## Lambda authorizer response format
<a name="http-api-lambda-authorizer.payload-format-response"></a>

The payload format version also determines the structure of the response that you must return from your Lambda function.

### Lambda function response for format 1.0
<a name="http-api-lambda-authorizer.v1"></a>

If you choose the `1.0` format version, Lambda authorizers must return an IAM policy that allows or denies access to your API route. You can use standard IAM policy syntax in the policy. For examples of IAM policies, see [Control access for invoking an API](api-gateway-control-access-using-iam-policies-to-invoke-api.md). You can pass context properties to Lambda integrations or access logs by using `$context.authorizer.property`. The `context` object is optional and `claims` is a reserved placeholder and cannot be used as the context object. To learn more, see [Customize HTTP API access logs](http-api-logging-variables.md).

**Example**    
****  

```
{
  "principalId": "abcdef", 
  "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": {
    "exampleKey": "exampleValue"
  }
}
```

### Lambda function response for format 2.0
<a name="http-api-lambda-authorizer.v2"></a>

If you choose the `2.0` format version, you can return a Boolean value or an IAM policy that uses standard IAM policy syntax from your Lambda function. To return a Boolean value, enable simple responses for the authorizer. The following examples demonstrate the format that you must code your Lambda function to return. The `context` object is optional. You can pass context properties to Lambda integrations or access logs by using `$context.authorizer.property`. To learn more, see [Customize HTTP API access logs](http-api-logging-variables.md).

------
#### [ Simple response ]

```
{
  "isAuthorized": true/false,
  "context": {
    "exampleKey": "exampleValue"
  }
}
```

------
#### [ IAM policy ]

****  

```
{
  "principalId": "abcdef", 
  "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": {
    "exampleKey": "exampleValue"
  }
}
```

------

## Example Lambda authorizer functions
<a name="http-api-lambda-authorizer.example-code"></a>

The following example Node.js Lambda functions demonstrate the required response formats you need to return from your Lambda function for the `2.0` payload format version.

------
#### [ Simple response - Node.js ]

```
export const handler = async(event) => {
    let response = {
        "isAuthorized": false,
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": true,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    };
    
    if (event.headers.authorization === "secretToken") {
        console.log("allowed");
        response = {
            "isAuthorized": true,
            "context": {
                "stringKey": "value",
                "numberKey": 1,
                "booleanKey": true,
                "arrayKey": ["value1", "value2"],
                "mapKey": {"value1": "value2"}
            }
        };
    }

    return response;

};
```

------
#### [ Simple response - Python ]

```
import json


def lambda_handler(event, context):
    response = {
        "isAuthorized": False,
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": True,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    }

    try:
        if (event["headers"]["authorization"] == "secretToken"):
            response = {
                "isAuthorized": True,
                "context": {
                    "stringKey": "value",
                    "numberKey": 1,
                    "booleanKey": True,
                    "arrayKey": ["value1", "value2"],
                    "mapKey": {"value1": "value2"}
                }
            }
            print('allowed')
            return response
        else:
            print('denied')
            return response
    except BaseException:
        print('denied')
        return response
```

------
#### [ IAM policy - Node.js ]

```
export const handler = async(event) => {
  if (event.headers.authorization == "secretToken") {
    console.log("allowed");
    return {
      "principalId": "abcdef", // The principal user identification associated with the token sent by the client.
      "policyDocument": {
        "Version": "2012-10-17",		 	 	 
        "Statement": [{
          "Action": "execute-api:Invoke",
          "Effect": "Allow",
          "Resource": event.routeArn
        }]
      },
      "context": {
        "stringKey": "value",
        "numberKey": 1,
        "booleanKey": true,
        "arrayKey": ["value1", "value2"],
        "mapKey": { "value1": "value2" }
      }
    };
  }
  else {
    console.log("denied");
    return {
      "principalId": "abcdef", // The principal user identification associated with the token sent by the client.
      "policyDocument": {
        "Version": "2012-10-17",		 	 	 
        "Statement": [{
          "Action": "execute-api:Invoke",
          "Effect": "Deny",
          "Resource": event.routeArn
        }]
      },
      "context": {
        "stringKey": "value",
        "numberKey": 1,
        "booleanKey": true,
        "arrayKey": ["value1", "value2"],
        "mapKey": { "value1": "value2" }
      }
    };
  }
};
```

------
#### [ IAM policy - Python ]

```
import json


def lambda_handler(event, context):
    response = {
        # The principal user identification associated with the token sent by
        # the client.
        "principalId": "abcdef",
        "policyDocument": {
            "Version": "2012-10-17",		 	 	 
            "Statement": [{
                "Action": "execute-api:Invoke",
                "Effect": "Deny",
                "Resource": event["routeArn"]
            }]
        },
        "context": {
            "stringKey": "value",
            "numberKey": 1,
            "booleanKey": True,
            "arrayKey": ["value1", "value2"],
            "mapKey": {"value1": "value2"}
        }
    }

    try:
        if (event["headers"]["authorization"] == "secretToken"):
            response = {
                # The principal user identification associated with the token
                # sent by the client.
                "principalId": "abcdef",
                "policyDocument": {
                    "Version": "2012-10-17",		 	 	 
                    "Statement": [{
                        "Action": "execute-api:Invoke",
                        "Effect": "Allow",
                        "Resource": event["routeArn"]
                    }]
                },
                "context": {
                    "stringKey": "value",
                    "numberKey": 1,
                    "booleanKey": True,
                    "arrayKey": ["value1", "value2"],
                    "mapKey": {"value1": "value2"}
                }
            }
            print('allowed')
            return response
        else:
            print('denied')
            return response
    except BaseException:
        print('denied')
        return response
```

------

## Identity sources
<a name="http-api-lambda-authorizer.identity-sources"></a>

You can optionally specify identity sources for a Lambda authorizer. Identity sources specify the location of data that's required to authorize a request. For example, you can specify header or query string values as identity sources. If you specify identity sources, clients must include them in the request. If the client's request doesn't include the identity sources, API Gateway doesn't invoke your Lambda authorizer, and the client receives a `401` error.

The following table describes the supported identity sources for a Lambda authorizer.


| **Type** | **Example** | **Notes** | 
| --- | --- | --- | 
| Header value | \$1request.header.name | Header names are case-insensitive. | 
| Query string value | \$1request.querystring.name | Query string names are case-sensitive. | 
| Context variable | \$1context.variableName | The value of a supported [context variable](http-api-logging-variables.md). | 
| Stage variable | \$1stageVariables.variableName | The value of a [stage variable](http-api-stages.stage-variables.md). | 

You can also directly return ` {"errorMessage" : "Unauthorized"}` from your Lambda function to return a `401` error to your clients. If you directly return a `401` error from your Lambda function to your clients, don't specify any identity sources when you create your Lambda authorizer.

## Caching authorizer responses
<a name="http-api-lambda-authorizer.caching"></a>

You can enable caching for a Lambda authorizer by specifying an [authorizerResultTtlInSeconds](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers.html#apis-apiid-authorizers-prop-createauthorizerinput-authorizerresultttlinseconds). When caching is enabled for an authorizer, API Gateway uses the authorizer's identity sources as the cache key. If a client specifies the same parameters in identity sources within the configured TTL, API Gateway uses the cached authorizer result, rather than invoking your Lambda function.

To enable caching, your authorizer must have at least one identity source.

If you enable simple responses for an authorizer, the authorizer's response fully allows or denies all API requests that match the cached identity source values. For more granular permissions, disable simple responses and return an IAM policy. Depending on your authorizer, your IAM policy might need to control access to multiple.

By default, API Gateway uses the cached authorizer response for all routes of an API that use the authorizer. To cache responses per route, add `$context.routeKey` to your authorizer's identity sources.

## Create a Lambda authorizer
<a name="http-api-lambda-authorizer.example-create"></a>

When you create a Lambda authorizer, you specify the Lambda function for API Gateway to use. You must grant API Gateway permission to invoke the Lambda function by using either the function's resource policy or an IAM role. The following [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-authorizer.html) command creates a Lambda authorizer:

```
aws apigatewayv2 create-authorizer \
    --api-id abcdef123 \
    --authorizer-type REQUEST \
    --identity-source '$request.header.Authorization' \
    --name lambda-authorizer \ 
    --authorizer-uri 'arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:my-function/invocations' \
    --authorizer-payload-format-version '2.0' \
    --enable-simple-responses
```

The following [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command updates the Lambda function's resource policy to grant API Gateway permission to invoke the function. If API Gateway doesn't have permission to invoke your function, clients receive a `500 Internal Server Error`.

```
aws lambda add-permission \
    --function-name my-authorizer-function \
    --statement-id apigateway-invoke-permissions-abc123 \ 
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/authorizers/authorizer-id"
```

After you've created an authorizer and granted API Gateway permission to invoke it, update your route to use the authorizer. The following [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) command adds the Lambda authorizer to the route. If your Lambda authorizer uses policy caching, make sure you update the policy to control access for the additional route.

```
aws apigatewayv2 update-route \
    --api-id abcdef123 \
    --route-id abc123 \
    --authorization-type CUSTOM \
    --authorizer-id def123
```

## Troubleshooting Lambda authorizers
<a name="http-api-lambda-authorizer.troubleshooting"></a>

If API Gateway can't invoke your Lambda authorizer, or your Lambda authorizer returns a response in an invalid format, clients receive a `500 Internal Server Error`.

To troubleshoot errors, [enable access logging](http-api-logging.md) for your API stage. Include the `$context.authorizer.error` logging variable in your log format.

If the logs indicate that API Gateway doesn't have permission to invoke your function, update your function's resource policy or provide an IAM role to grant API Gateway permission to invoke your authorizer.

If the logs indicate that your Lambda function returns an invalid response, verify that your Lambda function returns a response in the [required format](#http-api-lambda-authorizer.payload-format-response).

# Control access to HTTP APIs with JWT authorizers in API Gateway
<a name="http-api-jwt-authorizer"></a>

You can use JSON Web Tokens (JWTs) as a part of [OpenID Connect (OIDC)](https://openid.net/specs/openid-connect-core-1_0.html) and [OAuth 2.0](https://oauth.net/2/) frameworks to restrict client access to your APIs.

If you configure a JWT authorizer for a route of your API, API Gateway validates the JWTs that clients submit with API requests. API Gateway allows or denies requests based on token validation, and optionally, scopes in the token. If you configure scopes for a route, the token must include at least one of the route's scopes.

You can configure distinct authorizers for each route of an API, or use the same authorizer for multiple routes.

**Note**  
There is no standard mechanism to differentiate JWT access tokens from other types of JWTs, such as OpenID Connect ID tokens. Unless you require ID tokens for API authorization, we recommend that you configure your routes to require authorization scopes. You can also configure your JWT authorizers to require issuers or audiences that your identity provider uses only when issuing JWT access tokens.

## Authorizing API requests with a JWT authorizer
<a name="http-api-jwt-authorizer.evaluation"></a>

API Gateway uses the following general workflow to authorize requests to routes that are configured to use a JWT authorizer. 

1. Check the [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-prop-authorizer-identitysource) for a token. The `identitySource` can include only the token, or the token prefixed with `Bearer`.

1. Decode the token.

1. Check the token's algorithm and signature by using the public key that is fetched from the issuer's `jwks_uri`. Currently, only RSA-based algorithms are supported. API Gateway can cache the public key for two hours. As a best practice, when you rotate keys, allow a grace period during which both the old and new keys are valid. 

1. Validate claims. API Gateway evaluates the following token claims:
   +  [https://datatracker.ietf.org/doc/html/rfc7517#section-4.5](https://datatracker.ietf.org/doc/html/rfc7517#section-4.5) – The token must have a header claim that matches the key in the `jwks_uri` that signed the token.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1) – Must match the [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration) that is configured for the authorizer.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3) or `client_id` – Must match one of the [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-authorizers-authorizerid.html#apis-apiid-authorizers-authorizerid-model-jwtconfiguration) entries that is configured for the authorizer. API Gateway validates `client_id` only if `aud` is not present. When both `aud` and `client_id` are present, API Gateway evaluates `aud`.
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4) – Must be after the current time in UTC. 
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5) – Must be before the current time in UTC. 
   + [https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6) – Must be before the current time in UTC. 
   + [https://datatracker.ietf.org/doc/html/rfc6749#section-3.3](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3) or `scp` – The token must include at least one of the scopes in the route's [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid.html#apis-apiid-routes-routeid-prop-updaterouteinput-authorizationscopes).

If any of these steps fail, API Gateway denies the API request.

After validating the JWT, API Gateway passes the claims in the token to the API route’s integration. Backend resources, such as Lambda functions, can access the JWT claims. For example, if the JWT includes an identity claim `emailID`, it's available to a Lambda integration in `$event.requestContext.authorizer.jwt.claims.emailID`. For more information about the payload that API Gateway sends to Lambda integrations, see [Create AWS Lambda proxy integrations for HTTP APIs in API Gateway](http-api-develop-integrations-lambda.md).

## Create a JWT authorizer
<a name="http-api-jwt-authorizer.create"></a>

Before you create a JWT authorizer, you must register a client application with an identity provider. You must also have created an HTTP API. For examples of creating an HTTP API, see [Create an HTTP API](http-api-develop.md#http-api-examples).

### Create a JWT authorizer using the console
<a name="http-api-jwt-authorizer.create.console"></a>

The following steps show how to create JWT authorizer using the console.

**To create a JWT authorizer 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 an HTTP API.

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

1. Choose the **Manage authorizers** tab.

1. Choose **Create**.

1. For **Authorizer type**, choose **JWT**.

1. Configure your JWT authorizer, and specify an **Identity source** that defines the source of the token.

1. Choose **Create**.

#### Create a JWT authorizer using the AWS CLI
<a name="http-api-jwt-authorizer.create.cli"></a>

The following [create-authorizer](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-authorizer.html) command creates a JWT authorizer. For `jwt-configuration`, specify the `Audience` and `Issuer` for your identity provider. If you use Amazon Cognito as an identity provider, the `IssuerUrl` is `https://cognito-idp.us-east-2.amazonaws.com/userPoolID`.

```
aws apigatewayv2 create-authorizer \
    --name authorizer-name \
    --api-id api-id \
    --authorizer-type JWT \
    --identity-source '$request.header.Authorization' \
    --jwt-configuration Audience=audience,Issuer=IssuerUrl
```

##### Create a JWT authorizer using AWS CloudFormation
<a name="http-api-jwt-cfn.create"></a>

The following CloudFormation template creates an HTTP API with a JWT authorizer that uses Amazon Cognito as an identity provider.

The output of the CloudFormation template is a URL for an Amazon Cognito hosted UI where clients can sign up and sign in to receive a JWT. After a client signs in, the client is redirected to your HTTP API with an access token in the URL. To invoke the API with the access token, change the `#` in the URL to a `?` to use the token as a query string parameter.

##### Example CloudFormation template
<a name="http-api-jwt-cfn-example"></a>

```
AWSTemplateFormatVersion: '2010-09-09'
Description: |
  Example HTTP API with a JWT authorizer. This template includes an Amazon Cognito user pool as the issuer for the JWT authorizer 
  and an Amazon Cognito app client as the audience for the authorizer. The outputs include a URL for an Amazon Cognito hosted UI where clients can 
  sign up and sign in to receive a JWT. After a client signs in, the client is redirected to your HTTP API with an access token 
  in the URL. To invoke the API with the access token, change the '#' in the URL to a '?' to use the token as a query string parameter.

Resources:
  MyAPI:
    Type: AWS::ApiGatewayV2::Api
    Properties: 
      Description: Example HTTP API
      Name: api-with-auth
      ProtocolType: HTTP
      Target: !GetAtt MyLambdaFunction.Arn
  DefaultRouteOverrides:
    Type: AWS::ApiGatewayV2::ApiGatewayManagedOverrides
    Properties: 
      ApiId: !Ref MyAPI
      Route: 
        AuthorizationType: JWT
        AuthorizerId: !Ref JWTAuthorizer
  JWTAuthorizer:
    Type: AWS::ApiGatewayV2::Authorizer
    Properties: 
      ApiId: !Ref MyAPI
      AuthorizerType: JWT
      IdentitySource: 
        - '$request.querystring.access_token'
      JwtConfiguration: 
        Audience: 
        - !Ref AppClient
        Issuer: !Sub https://cognito-idp.${AWS::Region}.amazonaws.com/${UserPool}
      Name: test-jwt-authorizer
  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: nodejs18.x
      Role: !GetAtt FunctionExecutionRole.Arn
      Handler: index.handler
      Code:
        ZipFile: |
          exports.handler = async (event) => {
              const response = {
                  statusCode: 200,
                  body: JSON.stringify('Hello from the ' + event.routeKey + ' route!'),
              };
              return response;
          };
  APIInvokeLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref MyLambdaFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${MyAPI}/$default/$default
  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17		 	 	 '
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: http-api-user-pool
      AutoVerifiedAttributes:
        - email
      Schema:
        - Name: name
          AttributeDataType: String
          Mutable: true
          Required: true
        - Name: email
          AttributeDataType: String
          Mutable: false
          Required: true
  AppClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      AllowedOAuthFlows: 
        - implicit
      AllowedOAuthScopes: 
        - aws.cognito.signin.user.admin
        - email
        - openid
        - profile
      AllowedOAuthFlowsUserPoolClient: true
      ClientName: api-app-client
      CallbackURLs:
        - !Sub https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
      ExplicitAuthFlows:
        - ALLOW_USER_PASSWORD_AUTH
        - ALLOW_REFRESH_TOKEN_AUTH
      UserPoolId: !Ref UserPool
      SupportedIdentityProviders:
        - COGNITO 
  HostedUI:
    Type: AWS::Cognito::UserPoolDomain
    Properties: 
      Domain: !Join
        - '-'
        - - !Ref MyAPI
          - !Ref AppClient
      UserPoolId: !Ref UserPool
Outputs:
  SignupURL:
    Value: !Sub https://${HostedUI}.auth.${AWS::Region}.amazoncognito.com/login?client_id=${AppClient}&response_type=token&scope=email+profile&redirect_uri=https://${MyAPI}.execute-api.${AWS::Region}.amazonaws.com
```

## Update a route to use a JWT authorizer
<a name="http-api-jwt-authorizer.create.route"></a>

You can use the console, the AWS CLI, or an AWS SDK to update a route to use a JWT authorizer.

### Update a route to use a JWT authorizer by using the console
<a name="http-api-jwt-authorizer.create.route"></a>

The following steps show how to update a route to use JWT authorizer using the console.

**To create a JWT authorizer 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 an HTTP API.

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

1. Choose a method, and then select your authorizer from the dropdown menu, and choose **Attach authorizer**.

#### Update a route to use a JWT authorizer by using the AWS CLI
<a name="http-api-jwt-authorizer.create.route"></a>

The following [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) command updates a route to use a JWT authorizer:

```
aws apigatewayv2 update-route \
   --api-id api-id  \
   --route-id route-id  \
   --authorization-type JWT \
   --authorizer-id authorizer-id \
   --authorization-scopes user.email
```

# Control access to HTTP APIs with IAM authorization in API Gateway
<a name="http-api-access-control-iam"></a>

You can enable IAM authorization for HTTP API routes. When IAM authorization is enabled, clients must use [Signature Version 4 (SigV4)](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) to sign their requests with AWS credentials. API Gateway invokes your API route only if the client has `execute-api` permission for the route.

IAM authorization for HTTP APIs is similar to that for [REST APIs](api-gateway-control-access-using-iam-policies-to-invoke-api.md).

**Note**  
Resource policies aren't currently supported for HTTP APIs.

For examples of IAM policies that grant clients the permission to invoke APIs, see [Control access for invoking an API](api-gateway-control-access-using-iam-policies-to-invoke-api.md).

## Enable IAM authorization for a route
<a name="http-api-access-control-iam-example"></a>

The following [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) command enables IAM authorization for an HTTP API route:

```
aws apigatewayv2 update-route \
    --api-id abc123 \
    --route-id abcdef \
    --authorization-type AWS_IAM
```

# Create integrations for HTTP APIs in API Gateway
<a name="http-api-develop-integrations"></a>

*Integrations* connect a route to backend resources. HTTP APIs support Lambda proxy, AWS service, and HTTP proxy integrations. For example, you can configure a `POST` request to the `/signup` route of your API to integrate with a Lambda function that handles signing up customers.

**Topics**
+ [

# Create AWS Lambda proxy integrations for HTTP APIs in API Gateway
](http-api-develop-integrations-lambda.md)
+ [

# Create HTTP proxy integrations for HTTP APIs
](http-api-develop-integrations-http.md)
+ [

# Create AWS service integrations for HTTP APIs in API Gateway
](http-api-develop-integrations-aws-services.md)
+ [

# Create private integrations for HTTP APIs in API Gateway
](http-api-develop-integrations-private.md)

# Create AWS Lambda proxy integrations for HTTP APIs in API Gateway
<a name="http-api-develop-integrations-lambda"></a>

A Lambda proxy integration enables you to integrate an API route with a Lambda function. When a client calls your API, API Gateway sends the request to the Lambda function and returns the function's response to the client. For examples of creating an HTTP API, see [Create an HTTP API](http-api-develop.md#http-api-examples).

## Payload format version
<a name="http-api-develop-integrations-lambda.proxy-format"></a>

The payload format version specifies the format of the event that API Gateway sends to a Lambda integration, and how API Gateway interprets the response from Lambda. If you don't specify a payload format version, the AWS Management Console uses the latest version by default. If you create a Lambda integration by using the AWS CLI, CloudFormation, or an SDK, you must specify a `payloadFormatVersion`. The supported values are `1.0` and `2.0`.

For more information about how to set the `payloadFormatVersion`, see [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html). For more information about how to determine the `payloadFormatVersion` of an existing integration, see [get-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-integration.html)

### Payload format differences
<a name="http-api-develop-integrations-lambda.proxy-format-differences"></a>

The following list shows differences between the `1.0` and `2.0` payload format versions:
+ Format `2.0` doesn't have `multiValueHeaders` or `multiValueQueryStringParameters` fields. Duplicate headers are combined with commas and included in the `headers` field. Duplicate query strings are combined with commas and included in the `queryStringParameters` field.
+ Format `2.0` has `rawPath`. If you use an API mapping to connect your stage to a custom domain name, `rawPath` won't provide the API mapping value. Use format `1.0` and `path` to access the API mapping for your custom domain name.
+ Format `2.0` includes a new `cookies` field. All cookie headers in the request are combined with commas and added to the `cookies` field. In the response to the client, each cookie becomes a `set-cookie` header.

### Payload format structure
<a name="http-api-develop-integrations-lambda.proxy-format-structure"></a>

The following examples show the structure of each payload format version. All headernames are lowercased.

------
#### [ 2.0 ]

```
{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "headers": {
    "header1": "value1",
    "header2": "value1,value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "authentication": {
      "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"
        }
      }
    },
    "authorizer": {
      "jwt": {
        "claims": {
          "claim1": "value1",
          "claim2": "value2"
        },
        "scopes": [
          "scope1",
          "scope2"
        ]
      }
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "192.0.2.1",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "Hello from Lambda",
  "pathParameters": {
    "parameter1": "value1"
  },
  "isBase64Encoded": false,
  "stageVariables": {
    "stageVariable1": "value1",
    "stageVariable2": "value2"
  }
}
```

------
#### [ 1.0 ]

```
{
  "version": "1.0",
  "resource": "/my/path",
  "path": "/my/path",
  "httpMethod": "GET",
  "headers": {
    "header1": "value1",
    "header2": "value2"
  },
  "multiValueHeaders": {
    "header1": [
      "value1"
    ],
    "header2": [
      "value1",
      "value2"
    ]
  },
  "queryStringParameters": {
    "parameter1": "value1",
    "parameter2": "value"
  },
  "multiValueQueryStringParameters": {
    "parameter1": [
      "value1",
      "value2"
    ],
    "parameter2": [
      "value"
    ]
  },
  "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": "192.0.2.1",
      "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
}
```

------

## Lambda function response format
<a name="http-api-develop-integrations-lambda.response"></a>

The payload format version determines the structure of the response that your Lambda function must return.

### Lambda function response for format 1.0
<a name="http-api-develop-integrations-lambda.v1"></a>

With the `1.0` format version, Lambda integrations must return a response in the following JSON format:

**Example**  

```
{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headername": "headervalue", ... },
    "multiValueHeaders": { "headername": ["headervalue", "headervalue2", ...], ... },
    "body": "..."
}
```

### Lambda function response for format 2.0
<a name="http-api-develop-integrations-lambda.v2"></a>

With the `2.0` format version, API Gateway can infer the response format for you. API Gateway makes the following assumptions if your Lambda function returns valid JSON and doesn't return a `statusCode`:
+ `isBase64Encoded` is `false`.
+ `statusCode` is `200`.
+ `content-type` is `application/json`.
+ `body` is the function's response.

The following examples show the output of a Lambda function and API Gateway's interpretation.


| Lambda function output | API Gateway interpretation | 
| --- | --- | 
|  <pre>"Hello from Lambda!"</pre>  |  <pre>{<br />  "isBase64Encoded": false,<br />  "statusCode": 200,<br />  "body": "Hello from Lambda!",<br />  "headers": {<br />    "content-type": "application/json"<br />  }<br />}</pre>  | 
|  <pre>{ "message": "Hello from Lambda!" }</pre>  |  <pre>{<br />  "isBase64Encoded": false,<br />  "statusCode": 200,<br />  "body": "{ \"message\": \"Hello from Lambda!\" }",<br />  "headers": {<br />    "content-type": "application/json"<br />  }<br />}</pre>  | 

To customize the response, your Lambda function should return a response with the following format.

```
{
    "cookies" : ["cookie1", "cookie2"],
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headername": "headervalue", ... },
    "body": "Hello from Lambda!"
}
```

# Create HTTP proxy integrations for HTTP APIs
<a name="http-api-develop-integrations-http"></a>

An HTTP proxy integration enables you to connect an API route to a publicly routable HTTP endpoint. With this integration type, API Gateway passes the entire request and response between the frontend and the backend. 

To create an HTTP proxy integration, provide the URL of a publicly routable HTTP endpoint.

## HTTP proxy integration with path variables
<a name="http-api-develop-integrations-http-proxy"></a>

You can use path variables in HTTP API routes.

For example, the route `/pets/{petID}` catches requests to `/pets/6`. You can reference path variables in the integration URI to send the variable's contents to an integration. An example is `/pets/extendedpath/{petID}`.

You can use greedy path variables to catch all child resources of a route. To create a greedy path variable, add `+` to the variable name—for example, `{proxy+}`. 

To set up a route with an HTTP proxy integration that catches all requests, create an API route with a greedy path variable (for example, `/parent/{proxy+}`). Integrate the route with an HTTP endpoint (for example, `https://petstore-demo-endpoint.execute-api.com/petstore/{proxy}`) on the `ANY` method. The greedy path variable must be at the end of the resource path.

# Create AWS service integrations for HTTP APIs in API Gateway
<a name="http-api-develop-integrations-aws-services"></a>

You can integrate your HTTP API with AWS services by using *first-class integrations*. A first-class integration connects an HTTP API route to an AWS service API. When a client invokes a route that's backed by a first-class integration, API Gateway invokes an AWS service API for you. For example, you can use first-class integrations to send a message to an Amazon Simple Queue Service queue, or to start an AWS Step Functions state machine. For supported service actions, see [Integration subtype reference](http-api-develop-integrations-aws-services-reference.md).

## Mapping request parameters
<a name="http-api-develop-integrations-aws-services-parameter-mapping"></a>

First-class integrations have required and optional parameters. You must configure all required parameters to create an integration. You can use static values or map parameters that are dynamically evaluated at runtime. For a full list of supported integrations and parameters, see [Integration subtype reference](http-api-develop-integrations-aws-services-reference.md).

The following table describes the supported mapping request parameters.


| Type | Example | Notes | 
| --- | --- | --- | 
| Header value | \$1request.header.name | Header names are case-insensitive. API Gateway combines multiple header values with commas, for example "header1": "value1,value2". | 
| Query string value | \$1request.querystring.name | Query string names are case-sensitive. API Gateway combines multiple values with commas, for example "querystring1": "Value1,Value2". | 
| Path parameter | \$1request.path.name | The value of a path parameter in the request. For example if the route is /pets/\$1petId\$1, you can map the petId parameter from the request with \$1request.path.petId. | 
| Request body passthrough | \$1request.body | API Gateway passes the entire request body through. | 
| Request body | \$1request.body.name | A [JSON path expression](https://goessner.net/articles/JsonPath/index.html#e2). Recursive descent (\$1request.body..name) and filter expressions (?(expression)) aren't supported.  When you specify a JSON path, API Gateway truncates the request body at 100 KB and then applies the selection expression. To send payloads larger than 100 KB, specify `$request.body`.   | 
| Context variable | \$1context.variableName | The value of a supported [context variable](http-api-logging-variables.md). | 
| Stage variable | \$1stageVariables.variableName | The value of a [stage variable](http-api-stages.stage-variables.md). | 
| Static value | string | A constant value. | 

## Create a first-class integration
<a name="http-api-develop-integrations-aws-services-example"></a>

Before you create a first-class integration, you must create an IAM role that grants API Gateway permissions to invoke the AWS service action that you're integrating with. To learn more, see [Creating a role for an AWS service](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-service.html).

To create a first-class integration, choose a supported AWS service action, such as `SQS-SendMessage`, configure the request parameters, and provide a role that grants API Gateway permissions to invoke the integrated AWS service API. Depending on the integration subtype, different request parameters are required. To learn more, see [Integration subtype reference](http-api-develop-integrations-aws-services-reference.md).

The following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command creates an integration that sends an Amazon SQS message:

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-subtype SQS-SendMessage \
    --integration-type AWS_PROXY \
    --payload-format-version 1.0 \
    --credentials-arn arn:aws:iam::123456789012:role/apigateway-sqs \
    --request-parameters '{"QueueUrl": "$request.header.queueUrl", "MessageBody": "$request.body.message"}'
```

## Create a first-class integration using CloudFormation
<a name="http-api-develop-integrations-aws-services-example-cfn"></a>

The following example shows an CloudFormation snippet that creates a `/{source}/{detailType}` route with a first-class integration with Amazon EventBridge.

The `Source` parameter is mapped to the `{source}` path parameter, the `DetailType` is mapped to the `{DetailType}` path parameter, and the `Detail` parameter is mapped to the request body.

The snippet does not show the event bus or the IAM role that grants API Gateway permissions to invoke the `PutEvents` action.

```
Route:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref HttpApi
      AuthorizationType: None
      RouteKey: 'POST /{source}/{detailType}'
      Target: !Join 
        - /
        - - integrations
          - !Ref Integration
  Integration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref HttpApi
      IntegrationType: AWS_PROXY
      IntegrationSubtype: EventBridge-PutEvents
      CredentialsArn: !GetAtt EventBridgeRole.Arn
      RequestParameters:
        Source: $request.path.source
        DetailType: $request.path.detailType
        Detail: $request.body
        EventBusName: !GetAtt EventBus.Arn
      PayloadFormatVersion: "1.0"
```

# Integration subtype reference
<a name="http-api-develop-integrations-aws-services-reference"></a>

The following [integration subtypes](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationsubtype) are supported for HTTP APIs.

**Topics**
+ [

## EventBridge-PutEvents 1.0
](#EventBridge-PutEvents)
+ [

## SQS-SendMessage 1.0
](#SQS-SendMessage)
+ [

## SQS-ReceiveMessage 1.0
](#SQS-ReceiveMessage)
+ [

## SQS-DeleteMessage 1.0
](#SQS-DeleteMessage)
+ [

## SQS-PurgeQueue 1.0
](#SQS-PurgeQueue)
+ [

## AppConfig-GetConfiguration 1.0
](#AppConfig-GetConfiguration)
+ [

## Kinesis-PutRecord 1.0
](#Kinesis-PutRecord)
+ [

## StepFunctions-StartExecution 1.0
](#StepFunctions-StartExecution)
+ [

## StepFunctions-StartSyncExecution 1.0
](#StepFunctions-StartSyncExecution)
+ [

## StepFunctions-StopExecution 1.0
](#StepFunctions-StopExecution)

## EventBridge-PutEvents 1.0
<a name="EventBridge-PutEvents"></a>

Sends custom events to Amazon EventBridge so that they can be matched to rules.


| Parameter | Required | 
| --- | --- | 
| Detail | True | 
| DetailType | True | 
| Source | True | 
| Time | False | 
| EventBusName | False | 
| Resources | False | 
| Region | False | 
| TraceHeader | False | 

To learn more, see [PutEvents](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html) in the *Amazon EventBridge API Reference*.

## SQS-SendMessage 1.0
<a name="SQS-SendMessage"></a>

Delivers a message to the specified queue.


| Parameter | Required | 
| --- | --- | 
| QueueUrl | True | 
| MessageBody | True | 
| DelaySeconds | False | 
| MessageAttributes | False | 
| MessageDeduplicationId | False | 
| MessageGroupId | False | 
| MessageSystemAttributes | False | 
| Region | False | 

To learn more, see [SendMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html) in the *Amazon Simple Queue Service API Reference*.

## SQS-ReceiveMessage 1.0
<a name="SQS-ReceiveMessage"></a>

Retrieves one or more messages (up to 10), from the specified queue.


| Parameter | Required | 
| --- | --- | 
| QueueUrl | True | 
| AttributeNames | False | 
| MaxNumberOfMessages | False | 
| MessageAttributeNames | False | 
| ReceiveRequestAttemptId | False | 
| VisibilityTimeout | False | 
| WaitTimeSeconds | False | 
| Region | False | 

To learn more, see [ReceiveMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html) in the *Amazon Simple Queue Service API Reference*.

## SQS-DeleteMessage 1.0
<a name="SQS-DeleteMessage"></a>

Deletes the specified message from the specified queue.


| Parameter | Required | 
| --- | --- | 
| ReceiptHandle | True | 
| QueueUrl | True | 
| Region | False | 

To learn more, see [DeleteMessage](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteMessage.html) in the *Amazon Simple Queue Service API Reference*.

## SQS-PurgeQueue 1.0
<a name="SQS-PurgeQueue"></a>

Deletes all messages in the specified queue.


| Parameter | Required | 
| --- | --- | 
| QueueUrl | True | 
| Region | False | 

To learn more, see [PurgeQueue](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_PurgeQueue.html) in the *Amazon Simple Queue Service API Reference*.

## AppConfig-GetConfiguration 1.0
<a name="AppConfig-GetConfiguration"></a>

Receive information about a configuration.


| Parameter | Required | 
| --- | --- | 
| Application | True | 
| Environment | True | 
| Configuration | True | 
| ClientId | True | 
| ClientConfigurationVersion | False | 
| Region | False | 

To learn more, see [GetConfiguration](https://docs.aws.amazon.com/appconfig/2019-10-09/APIReference/API_GetConfiguration.html) in the *AWS AppConfig API Reference*.

## Kinesis-PutRecord 1.0
<a name="Kinesis-PutRecord"></a>

Writes a single data record into an Amazon Kinesis data stream.


| Parameter | Required | 
| --- | --- | 
| StreamName | True | 
| Data | True | 
| PartitionKey | True | 
| SequenceNumberForOrdering | False | 
| ExplicitHashKey | False | 
| Region | False | 

To learn more, see [PutRecord](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_PutRecord.html) in the *Amazon Kinesis Data Streams API Reference*.

## StepFunctions-StartExecution 1.0
<a name="StepFunctions-StartExecution"></a>

Starts a state machine execution.


| Parameter | Required | 
| --- | --- | 
| StateMachineArn | True | 
| Name | False | 
| Input | False | 
| Region | False | 

To learn more, see [StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) in the *AWS Step Functions API Reference*.

## StepFunctions-StartSyncExecution 1.0
<a name="StepFunctions-StartSyncExecution"></a>

Starts a synchronous state machine execution.


| Parameter | Required | 
| --- | --- | 
| StateMachineArn | True | 
| Name | False | 
| Input | False | 
| Region | False | 
| TraceHeader | False | 

To learn more, see [StartSyncExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartSyncExecution.html) in the *AWS Step Functions API Reference*.

## StepFunctions-StopExecution 1.0
<a name="StepFunctions-StopExecution"></a>

Stops an execution.


| Parameter | Required | 
| --- | --- | 
| ExecutionArn | True | 
| Cause | False | 
| Error | False | 
| Region | False | 

To learn more, see [StopExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StopExecution.html) in the *AWS Step Functions API Reference*.

# Create private integrations for HTTP APIs in API Gateway
<a name="http-api-develop-integrations-private"></a>

Private integrations enable you to create API integrations with private resources in a VPC, such as Application Load Balancers or Amazon ECS container-based applications. 

You can expose your resources in a VPC for access by clients outside of the VPC by using private integrations. You can control access to your API by using any of the [ authorization methods](http-api-access-control.md) that API Gateway supports.

**Note**  
To create a private integration, you must first create a VPC link. VPC links V2 are now supported for both HTTP and REST APIs. To learn more about VPC links V2, see [Set up VPC links V2 in API Gateway](apigateway-vpc-links-v2.md). 

After you’ve created a VPC link V2, you can set up private integrations that connect to an Application Load Balancer, Network Load Balancer, or resources registered with an AWS Cloud Map service.

## Considerations
<a name="http-api-develop-integrations-private-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 or AWS Cloud Map service, VPC link and HTTP API.
+ By default, private integration traffic uses the HTTP protocol. To use HTTPS, specify a [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html). To do this using the AWS Management Console, when you create your private integration, choose **Advanced settings** and then enter a secure server name.
+ For private integrations, API Gateway includes the [stage](http-api-stages.md) portion of the API endpoint in the request to your backend resources. For example, a request to the `test` stage of an API includes `test/route-path` in the request to your private integration. To remove the stage name from the request to your backend resources, use [parameter mapping](http-api-parameter-mapping.md) to overwrite the request path to `$request.path`.

## Create a private integration using an Application Load Balancer or Network Load Balancer
<a name="http-api-develop-integrations-private-ELB"></a>

Before you create a private integration, you must create a VPC link V2. To learn more about VPC links V2, see [Set up VPC links V2 in API Gateway](apigateway-vpc-links-v2.md).

To create a private integration with an Application Load Balancer or Network Load Balancer, create an HTTP proxy integration, specify the VPC link to use, and provide the listener ARN of the load balancer.

The following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command creates a private integration that connects to a load balancer by using a VPC link:

```
aws apigatewayv2 create-integration --api-id api-id --integration-type HTTP_PROXY \
    --integration-method GET --connection-type VPC_LINK \
    --connection-id VPC-link-ID \
    --integration-uri arn:aws:elasticloadbalancing:us-east-2:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/0467ef3c8400ae65
    --payload-format-version 1.0
```

## Create a private integration using AWS Cloud Map service discovery
<a name="http-api-develop-integrations-private-Cloud-Map"></a>

Before you create a private integration, you must create a VPC link V2. To learn more about VPC links, see [Set up VPC links V2 in API Gateway](apigateway-vpc-links-v2.md).

For integrations with AWS Cloud Map, API Gateway uses `DiscoverInstances` to identify resources. You can use query parameters to target specific resources. The registered resources' attributes must include IP addresses and ports. API Gateway distributes requests across healthy resources that are returned from `DiscoverInstances`. To learn more, see [DiscoverInstances](https://docs.aws.amazon.com/cloud-map/latest/api/API_DiscoverInstances.html) in the AWS Cloud Map API Reference.

**Note**  
If you use Amazon ECS to populate entries in AWS Cloud Map, you must configure your Amazon ECS task to use SRV records with Amazon ECS Service Discovery or turn on Amazon ECS Service Connect. For more information, see [Interconnecting services](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/interconnecting-services.html) in the Amazon Elastic Container Service Developer Guide.

To create a private integration with AWS Cloud Map, create an HTTP proxy integration, specify the VPC link to use, and provide the ARN of the AWS Cloud Map service.

The following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command creates a private integration that uses AWS Cloud Map service discovery to identify resources:

```
aws apigatewayv2 create-integration --api-id api-id --integration-type HTTP_PROXY  \
    --integration-method GET --connection-type VPC_LINK \
    --connection-id VPC-link-ID \
    --integration-uri arn:aws:servicediscovery:us-east-2:123456789012:service/srv-id?stage=prod&deployment=green_deployment
    --payload-format-version 1.0
```

# Configure CORS for HTTP APIs in API Gateway
<a name="http-api-cors"></a>

[Cross-origin resource sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) is a browser security feature that restricts HTTP requests that are initiated from scripts running in the browser. If you cannot access your API and receive an error message that contains `Cross-Origin Request Blocked`, you might need to enable CORS. For more information, see [What is CORS?](https://aws.amazon.com/what-is/cross-origin-resource-sharing/).

CORS is typically required to build web applications that access APIs hosted on a different domain or origin. You can enable CORS to allow requests to your API from a web application hosted on a different domain. For example, if your API is hosted on `https://{api_id}.execute-api.{region}.amazonaws.com/` and you want to call your API from a web application hosted on `example.com`, your API must support CORS.

If you configure CORS for an API, API Gateway automatically sends a response to preflight OPTIONS requests, even if there isn't an OPTIONS route configured for your API. For a CORS request, API Gateway adds the configured CORS headers to the response from an integration.

**Note**  
If you configure CORS for an API, API Gateway ignores CORS headers returned from your backend integration.

You can specify the following parameters in a CORS configuration. To add these parameters using the API Gateway HTTP API console, choose **Add** after you enter your value.


| CORS headers | CORS configuration property | Example values | 
| --- | --- | --- | 
|  Access-Control-Allow-Origin  |  allowOrigins  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-cors.html)  | 
|  Access-Control-Allow-Credentials  |  allowCredentials  |  true  | 
|  Access-Control-Expose-Headers  |  exposeHeaders  |  date, x-api-id, \$1  | 
|  Access-Control-Max-Age  |  maxAge  |  300  | 
|  Access-Control-Allow-Methods  |  allowMethods  |  GET, POST, DELETE, \$1  | 
|  Access-Control-Allow-Headers  |  allowHeaders  |  authorization, \$1  | 

To return CORS headers, your request must contain an `origin` header. For the `OPTIONS` method, your request must contain an `origin` header and an `Access-Control-Request-Method` header.

Your CORS configuration might look similar to the following:

![\[CORS configuration for HTTP APIs\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/http-cors-console.png)


## Configuring CORS for an HTTP API with a `$default` route and an authorizer
<a name="http-api-cors-default-route"></a>

You can enable CORS and configure authorization for any route of an HTTP API. When you enable CORS and authorization for the [`$default` route](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-routes.html#http-api-develop-routes.default), there are some special considerations. The `$default` route catches requests for all methods and routes that you haven't explicitly defined, including `OPTIONS` requests. To support unauthorized `OPTIONS` requests, add an `OPTIONS /{proxy+}` route to your API that doesn't require authorization and attach an integration to the route. The `OPTIONS /{proxy+}` route has higher priority than the `$default` route. As a result, it enables clients to submit `OPTIONS` requests to your API without authorization. For more information about routing priorities, see [Routing API requests](http-api-develop-routes.md#http-api-develop-routes.evaluation).

## Configure CORS for an HTTP API by using the AWS CLI
<a name="http-api-cors.example"></a>

The following [update-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-api.html) command enables CORS requests from `https://www.example.com`:

**Example**  

```
aws apigatewayv2 update-api --api-id api-id --cors-configuration AllowOrigins="https://www.example.com"
```

For more information, see [CORS](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid.html#apis-apiid-model-cors) in the Amazon API Gateway Version 2 API Reference.

# Transform API requests and responses for HTTP APIs in API Gateway
<a name="http-api-parameter-mapping"></a>

You can modify API requests from clients before they reach your backend integrations. You can also change the response from integrations before API Gateway returns the response to clients. You use *parameter mapping* to modify API requests and responses for HTTP APIs. To use parameter mapping, you specify API request or response parameters to modify, and specify how to modify those parameters.



## Transforming API requests
<a name="http-api-mapping-request-parameters"></a>

You use request parameters to change requests before they reach your backend integrations. You can modify headers, query strings, or the request path.

Request parameters are a key-value map. The key identifies the location of the request parameter to change, and how to change it. The value specifies the new data for the parameter.

The following table shows supported keys.


| Type | Syntax | 
| --- | --- | 
| Header | append\$1overwrite\$1remove:header.headername | 
| Query string | append\$1overwrite\$1remove:querystring.querystring-name | 
| Path | overwrite:path | 

The following table shows supported values that you can map to parameters.


| Type | Syntax | Notes | 
| --- | --- | --- | 
| Header value | \$1request.header.name or \$1\$1request.header.name\$1 | Header names are case-insensitive. API Gateway combines multiple header values with commas, for example "header1": "value1,value2". Some headers are reserved. To learn more, see [Reserved headers](#http-api-mapping-reserved-headers). | 
| Query string value | \$1request.querystring.name or \$1\$1request.querystring.name\$1 | Query string names are case-sensitive. API Gateway combines multiple values with commas, for example "querystring1" "Value1,Value2". | 
| Request body | \$1request.body.name or \$1\$1request.body.name\$1 | A JSON path expression. Recursive descent (\$1request.body..name) and filter expressions (?(expression)) aren't supported.  When you specify a JSON path, API Gateway truncates the request body at 100 KB and then applies the selection expression. To send payloads larger than 100 KB, specify `$request.body`.   | 
| Request path | \$1request.path or \$1\$1request.path\$1 | The request path, without the stage name. | 
| Path parameter | \$1request.path.name or \$1\$1request.path.name\$1 | The value of a path parameter in the request. For example if the route is /pets/\$1petId\$1, you can map the petId parameter from the request with \$1request.path.petId. | 
| Context variable | \$1context.variableName or \$1\$1context.variableName\$1 | The value of a [context variable](http-api-logging-variables.md). Only the special characters `.` and `_` are supported. | 
| Stage variable | \$1stageVariables.variableName or \$1\$1stageVariables.variableName\$1 | The value of a [stage variable](http-api-stages.stage-variables.md). | 
| Static value | string | A constant value. | 

**Note**  
To use multiple variables in a selection expression, enclose the variable in brackets. For example, `${request.path.name} ${request.path.id}`.

## Transforming API responses
<a name="http-api-mapping-response-parameters"></a>

You use response parameters to transform the HTTP response from a backend integration before returning the response to clients. You can modify headers or the status code of a response before API Gateway returns the response to clients.

You configure response parameters for each status code that your integration returns. Response parameters are a key-value map. The key identifies the location of the request parameter to change, and how to change it. The value specifies the new data for the parameter.

The following table shows supported keys.


| Type | Syntax | 
| --- | --- | 
| Header | append\$1overwrite\$1remove:header.headername | 
| Status code | overwrite:statuscode | 

The following table shows supported values that you can map to parameters.


| Type | Syntax | Notes | 
| --- | --- | --- | 
| Header value | \$1response.header.name or \$1\$1response.header.name\$1 | Header names are case-insensitive. API Gateway combines multiple header values with commas, for example "header1": "value1,value2". Some headers are reserved. To learn more, see [Reserved headers](#http-api-mapping-reserved-headers). | 
| Response body | \$1response.body.name or \$1\$1response.body.name\$1 | A JSON path expression. Recursive descent (\$1response.body..name) and filter expressions (?(expression)) aren't supported.  When you specify a JSON path, API Gateway truncates the response body at 100 KB and then applies the selection expression. To send payloads larger than 100 KB, specify `$response.body`.   | 
| Context variable | \$1context.variableName or \$1\$1context.variableName\$1 | The value of a supported [context variable](http-api-logging-variables.md). | 
| Stage variable | \$1stageVariables.variableName or \$1\$1stageVariables.variableName\$1 | The value of a [stage variable](http-api-stages.stage-variables.md). | 
| Static value | string | A constant value. | 

**Note**  
To use multiple variables in a selection expression, enclose the variable in brackets. For example, `${request.path.name} ${request.path.id}`.

## Reserved headers
<a name="http-api-mapping-reserved-headers"></a>

The following headers are reserved. You can't configure request or response mappings for these headers.
+ access-control-\$1
+ apigw-\$1
+ Authorization
+ Connection
+ Content-Encoding
+ Content-Length
+ Content-Location
+ Forwarded
+ Keep-Alive
+ Origin
+ Proxy-Authenticate
+ Proxy-Authorization
+ TE
+ Trailers 
+ Transfer-Encoding
+ Upgrade
+ x-amz-\$1
+ x-amzn-\$1
+ X-Forwarded-For
+ X-Forwarded-Host
+ X-Forwarded-Proto
+ Via

## Examples
<a name="http-api-parameter-mapping-examples"></a>

The following AWS CLI examples configure parameter mappings. For example CloudFormation templates, see [GitHub](https://github.com/awsdocs/amazon-api-gateway-developer-guide/tree/main/cloudformation-templates).

### Add a header to an API request
<a name="http-api-parameter-mapping-examples-request-header"></a>

The following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command creates a header named `header1` to an API request before it reaches your backend integration. API Gateway populates the header with the request ID.

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-type HTTP_PROXY \
    --payload-format-version 1.0 \
    --integration-uri 'https://api.example.com' \
    --integration-method ANY \
    --request-parameters '{ "append:header.header1": "$context.requestId" }'
```

### Rename a request header
<a name="http-api-parameter-mapping-examples-response"></a>

The following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command renames a request header from `header1` to `header2`:

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-type HTTP_PROXY \
    --payload-format-version 1.0 \
    --integration-uri 'https://api.example.com' \
    --integration-method ANY \
    --request-parameters '{ "append:header.header2": "$request.header.header1",  "remove:header.header1": "''"}'
```

### Change the response from an integration
<a name="http-api-parameter-mapping-examples-response"></a>

The following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command configures response parameters for an integration. When the integrations returns a 500 status code, API Gateway changes the status code to 403, and adds `header1`1 to the response. When the integration returns a 404 status code, API Gateway adds an `error` header to the response.

```
aws apigatewayv2 create-integration \
    --api-id abcdef123 \
    --integration-type HTTP_PROXY \
    --payload-format-version 1.0 \
    --integration-uri 'https://api.example.com' \
    --integration-method ANY \
    --response-parameters '{"500" : {"append:header.header1": "$context.requestId", "overwrite:statuscode" : "403"}, "404" : {"append:header.error" : "$stageVariables.environmentId"}  }'
```

### Remove configured parameter mappings
<a name="http-api-parameter-mapping-examples-remove"></a>

The following [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command removes previously configured request parameters for `append:header.header1`. It also removes previously configured response parameters for a 200 status code.

```
aws apigatewayv2 update-integration \
    --api-id abcdef123 \
    --integration-id hijk456 \
    --request-parameters '{"append:header.header1" : ""}' \
    --response-parameters '{"200" : {}}'
```

# Use OpenAPI definitions for HTTP APIs in API Gateway
<a name="http-api-open-api"></a>

You can define your HTTP API by using an OpenAPI 3.0 definition file. Then you can import the definition into API Gateway to create an API. To learn more about API Gateway extensions to OpenAPI, see [OpenAPI extensions for API Gateway](api-gateway-swagger-extensions.md).

## Importing an HTTP API
<a name="http-api-import"></a>

You can create an HTTP API by importing an OpenAPI 3.0 definition file.

To migrate from a REST API to an HTTP API, you can export your REST API as an OpenAPI 3.0 definition file. Then import the API definition as an HTTP API. To learn more about exporting a REST API, see [Export a REST API from API Gateway](api-gateway-export-api.md). 

**Note**  
HTTP APIs support the same AWS variables as REST APIs. To learn more, see [AWS variables for OpenAPI import](import-api-aws-variables.md).

### Import validation information
<a name="http-api-import.validation"></a>

As you import an API, API Gateway provides three categories of validation information.

**Info**  
A property is valid according to the OpenAPI specification, but that property isn’t supported for HTTP APIs.  
For example, the following OpenAPI 3.0 snippet produces info on import because HTTP APIs don't support request validation. API Gateway ignores the `requestBody` and `schema` fields.  

```
"paths": {
  "/": {
    "get": {
      "x-amazon-apigateway-integration": {
        "type": "AWS_PROXY",
        "httpMethod": "POST",
        "uri": "arn:aws:lambda:us-east-2:123456789012:function:HelloWorld",
        "payloadFormatVersion": "1.0"
      },
      "requestBody": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Body"
            }
          }
        }
      }
    }
  }
  ...
},
"components": {
  "schemas": {
    "Body": {
      "type": "object",
      "properties": {
        "key": {
          "type": "string"
        }
      }
    }
    ...
  }
  ...
}
```

**Warning**  
A property or structure is invalid according to the OpenAPI specification, but it doesn’t block API creation. You can specify whether API Gateway should ignore these warnings and continue creating the API, or stop creating the API on warnings.  
The following OpenAPI 3.0 document produces warnings on import because HTTP APIs support only Lambda proxy and HTTP proxy integrations.  

```
"x-amazon-apigateway-integration": {
  "type": "AWS",
  "httpMethod": "POST",
  "uri": "arn:aws:lambda:us-east-2:123456789012:function:HelloWorld",
  "payloadFormatVersion": "1.0"
}
```

**Error**  
The OpenAPI specification is invalid or malformed. API Gateway can’t create any resources from the malformed document. You must fix the errors, and then try again.  
The following API definition produces errors on import because HTTP APIs support only the OpenAPI 3.0 specification.  

```
{
  "swagger": "2.0.0",
  "info": {
    "title": "My API",
    "description": "An Example OpenAPI definition for Errors/Warnings/ImportInfo",
    "version": "1.0"
  }
  ...
}
```
As another example, while OpenAPI allows users to define an API with multiple security requirements attached to a particular operation, API Gateway does not support this. Each operation can have only one of IAM authorization, a Lambda authorizer, or a JWT authorizer. Attempting to model multiple security requirements results in an error.

### Import an API by using the AWS CLI
<a name="http-api-import.example"></a>

The following [import-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/import-api.html) command imports the OpenAPI 3.0 definition file `api-definition.json` as an HTTP API:

**Example**  

```
aws apigatewayv2 import-api --body file://api-definition.json
```

**Example**  
You can import the following example OpenAPI 3.0 definition to create an HTTP API.  

```
{
  "openapi": "3.0.1",
  "info": {
    "title": "Example Pet Store",
    "description": "A Pet Store API.",
    "version": "1.0"
  },
  "paths": {
    "/pets": {
      "get": {
        "operationId": "GET HTTP",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pets"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP_PROXY",
          "httpMethod": "GET",
          "uri": "http://petstore.execute-api.us-west-1.amazonaws.com/petstore/pets",
          "payloadFormatVersion": 1.0
        }
      },
      "post": {
        "operationId": "Create Pet",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewPet"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "200 response",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NewPetResponse"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration": {
          "type": "HTTP_PROXY",
          "httpMethod": "POST",
          "uri": "http://petstore.execute-api.us-west-1.amazonaws.com/petstore/pets",
          "payloadFormatVersion": 1.0
        }
      }
    },
    "/pets/{petId}": {
      "get": {
        "operationId": "Get Pet",
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "200 response",
            "headers": {
              "Access-Control-Allow-Origin": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Pet"
                }
              }
            }
          }
        },        
        "x-amazon-apigateway-integration": {
          "type": "HTTP_PROXY",
          "httpMethod": "GET",
          "uri": "http://petstore.execute-api.us-west-1.amazonaws.com/petstore/pets/{petId}",
          "payloadFormatVersion": 1.0
        }
      }
    }
  },
  "x-amazon-apigateway-cors": {
    "allowOrigins": [
      "*"
    ],
    "allowMethods": [
      "GET",
      "OPTIONS",
      "POST"
    ],
    "allowHeaders": [
      "x-amzm-header",
      "x-apigateway-header",
      "x-api-key",
      "authorization",
      "x-amz-date",
      "content-type"
    ]
  },
  "components": {
    "schemas": {
      "Pets": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/Pet"
        }
      },
      "Empty": {
        "type": "object"
      },
      "NewPetResponse": {
        "type": "object",
        "properties": {
          "pet": {
            "$ref": "#/components/schemas/Pet"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Pet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "price": {
            "type": "number"
          }
        }
      },
      "NewPet": {
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/PetType"
          },
          "price": {
            "type": "number"
          }
        }
      },
      "PetType": {
        "type": "string",
        "enum": [
          "dog",
          "cat",
          "fish",
          "bird",
          "gecko"
        ]
      }
    }
  }
}
```

# Export HTTP APIs from API Gateway
<a name="http-api-export"></a>

After you've created an HTTP API, you can export an OpenAPI 3.0 definition of your API from API Gateway. You can either choose a stage to export, or export the latest configuration of your API. You can also import an exported API definition into API Gateway to create another, identical API. To learn more about importing API definitions, see [Importing an HTTP API](http-api-open-api.md#http-api-import).

## Export an OpenAPI 3.0 definition of a stage by using the AWS CLI
<a name="http-api-export.stage.example"></a>

The following [export-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/export-api.html) command exports an OpenAPI definition of an API stage named `prod` to a YAML file named `stage-definition.yaml`. The exported definition file includes [API Gateway extensions](api-gateway-swagger-extensions.md) by default.

```
aws apigatewayv2 export-api \
    --api-id api-id  \
    --output-type YAML  \
    --specification OAS30 \
    --stage-name prod \
    stage-definition.yaml
```

## Export an OpenAPI 3.0 definition of your API's latest changes by using the AWS CLI
<a name="http-api-export.latest.example"></a>

The following [export-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/export-api.html) command exports an OpenAPI definition of an HTTP API to a JSON file named `latest-api-definition.json`. Because the command doesn't specify a stage, API Gateway exports the latest configuration of your API, whether it has been deployed to a stage or not. The exported definition file doesn't include [API Gateway extensions](api-gateway-swagger-extensions.md).

```
aws apigatewayv2 export-api \
    --api-id api-id  \
    --output-type JSON  \
    --specification OAS30 \
    --no-include-extensions \
    latest-api-definition.json
```

For more information, see [ExportAPI](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-exports-specification.html#apis-apiid-exports-specification-http-methods) in the *Amazon API Gateway Version 2 API Reference*.

## Export an OpenAPI 3.0 definition by using the API Gateway console
<a name="http-api-export.console"></a>

The following procedure shows how to export an OpenAPI definition of an HTTP API.

**To export an OpenAPI 3.0 definition 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 HTTP API.

1. On the main navigation pane, under **Develop**, choose **Export**.

1. Select from the following options to export your API:  
![\[Export options for HTTP APIs.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/export-http-api.png)

   1. For **Source**, select a source for the OpenAPI 3.0 definition. You can choose a stage to export, or export the latest configuration of your API.

   1. Turn on **Include API Gateway extensions** to include [API Gateway extensions](api-gateway-swagger-extensions.md).

   1. For **Output format**, select an output format.

1. Choose **Download**.

# Publish HTTP APIs for customers to invoke
<a name="http-api-publish"></a>

You can use stages and custom domain names to publish your API for clients to invoke.

An API stage is a logical reference to a lifecycle state of your API (for example, `dev`, `prod`, `beta`, or `v2`). Each stage is a named reference to a deployment of the API and is made available for client applications to call. You can configure different integrations and settings for each stage of an API.

You can use custom domain names to provide a simpler, more intuitive URL for clients to invoke your API than the default URL, `https://api-id.execute-api.region.amazonaws.com/stage`.

**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**
+ [

# Stages for HTTP APIs in API Gateway
](http-api-stages.md)
+ [

# Security policy for HTTP APIs in API Gateway
](http-api-ciphers.md)
+ [

# Custom domain names for HTTP APIs in API Gateway
](http-api-custom-domain-names.md)

# Stages for HTTP APIs in API Gateway
<a name="http-api-stages"></a>

An API stage is a logical reference to a lifecycle state of your API (for example, `dev`, `prod`, `beta`, or `v2`). API stages are identified by their API ID and stage name, and they're included in the URL 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.

You can create a `$default` stage that is served from the base of your API's URL—for example, `https://{api_id}.execute-api.{region}.amazonaws.com/`. You use this URL to invoke an API stage.

A deployment is a snapshot of your API configuration. After you deploy an API to a stage, it’s available for clients to invoke. You must deploy an API for changes to take effect. If you enable automatic deployments, changes to an API are automatically released for you.

# Use stage variables for HTTP APIs in API Gateway
<a name="http-api-stages.stage-variables"></a>

Stage variables are key-value pairs that you can define for a stage of an HTTP API. They act like environment variables and can be used in your API setup.

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 [Lambda authorizer response format](http-api-lambda-authorizer.md#http-api-lambda-authorizer.payload-format-response).

## Example – Use a stage variable to customize the HTTP integration endpoint
<a name="http-api-stages.stage-variables-examples"></a>

For example, you can define a stage variable, and then set its value as an HTTP endpoint for an HTTP proxy integration. Later, you can reference the endpoint by using the associated stage variable name. By doing this, you can use the same API setup with a different endpoint at each stage. Similarly, you can use stage variables to specify a different AWS Lambda function integration for each stage of your API.

To use a stage variable to customize the HTTP integration endpoint, you must first set the name and value of the stage variable (for example, `url`) with a value of `example.com`. Next, set up an HTTP proxy integration. Instead of entering the endpoint's URL, you can tell API Gateway to use the stage variable value, **http://\$1\$1stageVariables.url\$1**. This value tells API Gateway to substitute your stage variable `${}` at runtime, depending on the stage of your API. 

You can reference stage variables in a similar way to specify a Lambda function name or an AWS role ARN.

When specifying a Lambda function name as a stage variable value, you must configure the permissions on the Lambda function manually. The following [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command configures the permission for the Lambda function:

```
aws lambda add-permission --function-name arn:aws:lambda:XXXXXX:your-lambda-function-name --source-arn arn:aws:execute-api:us-east-1:YOUR_ACCOUNT_ID:api_id/*/HTTP_METHOD/resource --principal apigateway.amazonaws.com --statement-id apigateway-access --action lambda:InvokeFunction
```

# API Gateway stage variables reference for HTTP APIs in API Gateway
<a name="http-api-stages.stage-variables-reference"></a>

You can use API Gateway stage variables for HTTP APIs in the following cases.

## HTTP integration URIs
<a name="http-api-stages.stage-variables-in-integration-HTTP-uris"></a>

You can use a stage variable as part of an HTTP integration URI, 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>}` 

## Lambda functions
<a name="http-api-stages.stage-variables-in-integration-lambda-functions"></a>

 You can use a stage variable in place of a Lambda function integration name or 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.

## AWS integration credentials
<a name="http-api-stages.stage-variables-in-integration-aws-credentials"></a>

 You can use a stage variable as part of an AWS user or role credential ARN, as shown in the following example. 
+  `arn:aws:iam::<account_id>:${stageVariables.<variable_name>}` 

# Security policy for HTTP APIs in API Gateway
<a name="http-api-ciphers"></a>

API Gateway enforces a security policy of `TLS_1_2` for all HTTP API endpoints.

A *security policy* is a predefined combination of minimum TLS version and cipher suites offered by Amazon API Gateway. The TLS protocol addresses network security problems such as tampering and eavesdropping between a client and server. When your clients establish a TLS handshake to your API through the custom domain, the security policy enforces the TLS version and cipher suite options your clients can choose to use. This security policy accepts TLS 1.2 and TLS 1.3 traffic and rejects TLS 1.0 traffic.

## Supported TLS protocols and ciphers for HTTP APIs
<a name="http-api-ciphers-list"></a>

The following table describes the supported TLS protocols for HTTP APIs.


| **TLS protocols** | **TLS\$11\$12 security policy** | 
| --- | --- | 
| TLSv1.3 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| TLSv1.2 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 

The following table describes the TLS ciphers that are available for the TLS 1\$12 security policy for HTTP APIs.


| **TLS ciphers** | **TLS\$11\$12 security policy** | 
| --- | --- | 
| TLS-AES-128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| TLS-AES-256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| TLS-CHACHA20-POLY1305-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-ECDSA-AES128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-RSA-AES128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-ECDSA-AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-RSA-AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-ECDSA-AES256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-RSA-AES256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-ECDSA-AES256-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| ECDHE-RSA-AES256-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| AES128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| AES256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 
| AES256-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/success_icon.png) Yes | 

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

OpenSSL and IETF RFC 5246 use different names for the same ciphers. For a list of the cipher names, see [OpenSSL and RFC cipher names](apigateway-security-policies-list.md#apigateway-secure-connections-openssl-rfc-cipher-names).

## Information about REST APIs and WebSocket APIs
<a name="apigateway-http-additional-apis"></a>

For more information about REST APIs and WebSocket APIs, see [Choose a security policy for your custom domain in API Gateway](apigateway-custom-domain-tls-version.md) and [Security policy for WebSocket APIs in API Gateway](websocket-api-ciphers.md).

# Custom domain names for HTTP APIs in API Gateway
<a name="http-api-custom-domain-names"></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
```

## Considerations
<a name="http-api-custom-domain-name-considerations"></a>

The following considerations might impact your use of a custom domain name.
+ A Regional custom domain name can be associated with REST APIs and HTTP APIs. You can use the API Gateway Version 2 APIs to create and manage Regional custom domain names for REST APIs. 
+ For the minimum TLS version, only TLS 1.2 is supported.
+ 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](#http-wildcard-custom-domain-names).

## Prerequisites
<a name="http-api-custom-domain-names-prerequisites"></a>

The following are prerequisites for creating a custom domain name.

### Register a domain name
<a name="http-api-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.

### Certificates for custom domain names
<a name="http-api-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="http-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.api.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`, which all route to the same domain.

Wildcard custom domain names support distinct configurations from API Gateway's standard custom domain names. For example, in a single AWS account, you can configure `*.example.com` and `a.example.com` to behave differently.

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="http-api-custom-domain-names-next-steps"></a>

To set up a custom domain name for an HTTP API, you use documentation from the REST API section of the API Gateway Developer Guide. 

First, specify a certificate for your custom domain name. For more information, see [Get certificates ready in AWS Certificate Manager](how-to-specify-certificate-for-custom-domain-name.md). Next, you create a Regional custom domain name. For more information, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md).

# Map API stages to a custom domain name for HTTP APIs
<a name="http-api-mappings"></a>

You use API mappings to connect API stages to a custom domain name. After you create a domain name and configure DNS records, you use API mappings to send 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 the `production` stage of an API to `https://api.example.com/orders`.

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).

## Routing API requests
<a name="http-api-mappings-evalutation"></a>

You can configure API mappings with multiple levels, for example `orders/v1/items` and `orders/v2/items`.

For API mappings with multiple levels, API Gateway routes requests to the API mapping that has the longest matching path. API Gateway considers only the paths configured for API mappings, and not API routes, to select the API to invoke. If no path matches the request, API Gateway sends the request to the API that you've mapped to the empty path `(none)`.

For custom domain names that use API mappings with multiple levels, API Gateway routes requests to the API mapping that has the longest matching prefix.

For example, consider a custom domain name `https://api.example.com` with the following API mappings:

1. `(none)` mapped to API 1.

1. `orders` mapped to API 2.

1. `orders/v1/items` mapped to API 3.

1. `orders/v2/items` mapped to API 4.

1. `orders/v2/items/categories` mapped to API 5.


| 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.  | 
|  `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="http-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.
+ If you create an API mappings with multiple levels, API Gateway converts all header names to lowercase.

## Create an API mapping
<a name="http-api-mappings-examples"></a>

To create an API mapping, you must first create a custom domain name, API, and stage. For information about creating a custom domain name, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.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 ]

**To create an API mapping**

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**.

1. Select a custom domain name that you've already created.

1. Choose **API mappings**.

1. Choose **Configure API mappings**.

1. Choose **Add new mapping**.

1. Enter an **API**, a **Stage**, and optionally a **Path**.

1. Choose **Save**.

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

The following [create-api-mapping](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.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.

```
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.

```
MyApiMapping:
  Type: 'AWS::ApiGatewayV2::ApiMapping'
  Properties:
    DomainName: api.example.com
    ApiMappingKey: 'orders/v2/items'
    ApiId: !Ref MyApi
    Stage: !Ref MyStage
```

------

# Disable the default endpoint for HTTP APIs
<a name="http-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. When you disable the default endpoint, it affects all stages of an API.

The following procedure shows how to disable the default endpoint for an HTTP 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 an HTTP API.

1. Choose your API's ID to open the **API details** page.

1. On **API details**, choose **Edit**.

1. For **Default endpoint**, select **Disable**.

1. Choose **Save**.

   If you turn on automatic deployments for your stage, you do not need to redeploy your API for the change to take effect. Otherwise, you must redeploy your API.

1. (Optional) Choose **Deploy**, and then redeploy your API or create a new stage for the change to take effect.

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

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) command disables the default endpoint for an HTTP API:

```
aws apigatewayv2 update-api \
    --api-id abcdef123 \
    --disable-execute-api-endpoint
```

After you disable the default endpoint, you must deploy your API for the change to take effect, unless automatic deployments are enabled.

The following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-deployment.html) command creates a deployment:

```
aws apigatewayv2 create-deployment \
    --api-id abcdef123 \
    --stage-name dev
```

------

# IP address types for custom domain names for HTTP APIs
<a name="http-api-custom-domain-names-ip-address-type"></a>

When you create an API, 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).

## Considerations for IP address types
<a name="http-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 is IPv4.
+ 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 API.

## Change the IP address type of a custom domain name
<a name="http-api-custom-domain-names-ip-address-type-change"></a>

You can change the IP address type by updating the domain’s endpoint configuration. You can update the domain's 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/apigatewayv2/update-domain-name.html) command updates an API to have an IP address type of dualstack:

```
aws apigatewayv2 update-domain-name \
   --domain-name dualstack.example.com \
   --domain-name-configurations CertificateArn=arn:aws:acm:us-east-1:111122223333:certificate/abcd1234-5678-abc,IpAddressType=dualstack
```

The output will look like the following:

```
{
    "ApiMappingSelectionExpression": "$request.basepath",
    "DomainName": "dualstack.example.com",
    "DomainNameConfigurations": [
        {
            "ApiGatewayDomainName": "d-abcd1234.execute-api.us-east-1.amazonaws.com",
            "CertificateArn": "arn:aws:acm:us-east-1:111122223333:certificate/abcd1234-5678-abc",
            "DomainNameStatus": "AVAILABLE",
            "EndpointType": "REGIONAL",
            "HostedZoneId": "Z3LQWSYCGH4ADY",
            "SecurityPolicy": "TLS_1_2",
            "IpAddressType": "dualstack"
        }
    ],
    "Tags": {}
}
```

------

# Protect your HTTP APIs in API Gateway
<a name="http-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 setting throttling targets, and enabling mutual TLS. In this section you can learn how to enable these capabilities using API Gateway.

**Topics**
+ [

# Throttle requests to your HTTP APIs for better throughput in API Gateway
](http-api-throttling.md)
+ [

# How to turn on mutual TLS authentication for your HTTP APIs in API Gateway
](http-api-mutual-tls.md)

# Throttle requests to your HTTP APIs for better throughput in API Gateway
<a name="http-api-throttling"></a>

You can configure throttling for your APIs to help protect them from being overwhelmed by too many requests. Throttles 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 routes to improve overall performance across all APIs in your account.

## Account-level throttling per Region
<a name="http-api-protect-throttling-account"></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).

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.

## Route-level throttling
<a name="http-api-protect-throttling-route"></a>

You can set route-level throttling to override the account-level request throttling limits for a specific stage or for individual routes in your API. The default route throttling limits can't exceed account-level rate limits.

You can configure route-level throttling by using the AWS CLI. The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) command configures custom throttling for the specified stage and route of an API:

```
aws apigatewayv2 update-stage \
    --api-id a1b2c3d4 \
    --stage-name dev \
    --route-settings '{"GET /pets":{"ThrottlingBurstLimit":100,"ThrottlingRateLimit":2000}}'
```

# How to turn on mutual TLS authentication for your HTTP APIs in API Gateway
<a name="http-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 HTTP APIs](http-api-disable-default-endpoint.md). 

## Prerequisites for mutual TLS
<a name="http-api-mutual-tls-prerequisites"></a>

To configure mutual TLS you need:
+ A 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="http-api-mutual-tls-custom-domain-name"></a>

 To enable mutual TLS for a HTTP 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 names for HTTP APIs in API Gateway](http-api-custom-domain-names.md).

### Using AWS Certificate Manager issued certificates
<a name="http-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="http-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="http-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 hashing algorithms are supported in the truststore:
+ SHA-256 or stronger
+ RSA-2048 or stronger
+ ECDSA-256 or stronger

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="w2aac19c17b9b9c13"></a>

**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="http-api-mutual-tls-configure"></a>

To configure mutual TLS for a HTTP API, you must use a Regional custom domain name for your API, with a minimum TLS version of 1.2. To learn more about creating and configuring a custom domain name, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.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/apigatewayv2/create-domain-name.html) creates a custom domain name with mutual TLS:

```
aws apigatewayv2 create-domain-name \
    --domain-name api.example.com \
    --domain-name-configurations CertificateArn=arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --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="http-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="http-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/apigatewayv2/update-domain-name.html) command updates a custom domain name to use a new truststore version:

```
aws apigatewayv2 update-domain-name \
    --domain-name api.example.com \
    --domain-name-configurations CertificateArn=arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --mutual-tls-authentication TruststoreVersion='abcdef123'
```

## Disable mutual TLS
<a name="http-api-mutual-tls-disable"></a>

To disable mutual TLS for a custom domain name, remove the truststore from your custom domain name, as shown in the following command.

The following [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) command updates a custom domain name to remove the truststore from your custom domain name:

```
aws apigatewayv2 update-domain-name \
    --domain-name api.example.com \
    --domain-name-configurations CertificateArn=arn:aws:acm:us-west-2:123456789012:certificate/123456789012-1234-1234-1234-12345678 \
    --mutual-tls-authentication TruststoreUri=''
```

## Troubleshoot mutual TLS for your HTTP API
<a name="http-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="http-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="w2aac19c17b9c19b7"></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="w2aac19c17b9c19b9"></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.

# Monitor HTTP APIs in API Gateway
<a name="http-api-monitor"></a>

You can use CloudWatch metrics and CloudWatch Logs to monitor HTTP APIs. By combining logs and metrics, you can log errors and monitor your API's performance.

**Note**  
API Gateway might not generate logs and metrics in the following cases:  
413 Request Entity 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

**Topics**
+ [

# Monitor CloudWatch metrics for HTTP APIs in API Gateway
](http-api-metrics.md)
+ [

# Configure logging for HTTP APIs in API Gateway
](http-api-logging.md)

# Monitor CloudWatch metrics for HTTP APIs in API Gateway
<a name="http-api-metrics"></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. To monitor your metrics, create a CloudWatch dashboard for your API. For more information about how to create a CloudWatch dashboard, see [ Creating a CloudWatch dashboard ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/create_dashboard.html) in the *Amazon CloudWatch User Guide*. 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 following metrics are supported for HTTP APIs. You can also enable detailed metrics to write route-level metrics to Amazon CloudWatch.


| Metric | Description | 
| --- | --- | 
| 4xx | The number of client-side errors captured in a given period. | 
| 5xx | The number of server-side errors captured in a given period. | 
| Count | The total number API requests in a given period. | 
| IntegrationLatency | The time between when API Gateway relays a request to the backend and when it receives a response from the backend. | 
| 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. | 
| DataProcessed | The amount of data processed in bytes. | 

You can use the dimensions in the following table to filter API Gateway metrics.


| Dimension | Description | 
| --- | --- | 
| ApiId | Filters API Gateway metrics for an API with the specified API ID. | 
| ApiId, Stage | Filters API Gateway metrics for an API stage with the specified API ID and stage ID. | 
| ApiId, Method, Resource, Stage |  Filters API Gateway metrics for an API method with the specified API ID, stage ID, resource path, and route ID. API Gateway will not send these metrics unless you have explicitly enabled detailed CloudWatch metrics. You can do this by calling the [UpdateStage](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-stages-stagename.html) action of the API Gateway V2 REST API to update the `detailedMetricsEnabled` property to `true`. Alternatively, you can call the [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) AWS CLI command to update the `DetailedMetricsEnabled` property to `true`. Enabling such metrics will incur additional charges to your account. For pricing information, see [Amazon CloudWatch Pricing](https://aws.amazon.com/cloudwatch/pricing/).  | 

# Configure logging for HTTP APIs in API Gateway
<a name="http-api-logging"></a>

You can turn on logging to write logs to CloudWatch Logs. You can use [logging variables](http-api-logging-variables.md) to customize the content of your logs.

To improve your security posture, we recommend that you write logs to CloudWatch Logs for all stages of your HTTP API. 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*.

To turn on logging for an HTTP API, you must do the following.

1. Ensure that your user has the required permissions to activate logging.

1. Create a CloudWatch Logs log group.

1. Provide the ARN of the CloudWatch Logs log group for a stage of your API.

## Permissions to activate logging
<a name="http-api-logging.permissions"></a>

To turn on logging for an API, your user must have the following permissions.

**Example**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams",
                "logs:GetLogEvents",
                "logs:FilterLogEvents"
            ],
            "Resource": "arn:aws:logs:us-east-2:123456789012:log-group:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogDelivery",
                "logs:PutResourcePolicy",
                "logs:UpdateLogDelivery",
                "logs:DeleteLogDelivery",
                "logs:CreateLogGroup",
                "logs:DescribeResourcePolicies",
                "logs:GetLogDelivery",
                "logs:ListLogDeliveries"
            ],
            "Resource": "*"
        }
    ]
}
```

## Create a log group and activate logging for HTTP APIs
<a name="http-api-enable-logging"></a>

You can create a log group and activate access logging using the AWS Management Console or the AWS CLI.

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

1.  Create a log group. 

   To learn how to create a log group using the console, see [Create a Log Group in Amazon CloudWatch Logs User Guide](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html).

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

1. Choose an HTTP API.

1. Under the **Monitor** tab in the primary navigation panel, choose **Logging**.

1. Select a stage to activate logging and choose **Select**. 

1. Choose **Edit** to activate access logging. 

1. Turn on **Access logging**, enter a CloudWatch Logs, and select a log format.

1. Choose **Save**.

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

The following [create-log-group](https://docs.aws.amazon.com/cli/latest/reference/logs/create-log-group.html) command creates a log group:

```
aws logs create-log-group --log-group-name my-log-group
```

You need the Amazon Resource Name (ARN) for your log group to turn on logging. The ARN format is arn:aws:logs:*region*:*account-id*:log-group:*log-group-name*.

The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) command turns on logging for the `$default` stage of an HTTP API:

```
aws apigatewayv2 update-stage --api-id abcdef \
    --stage-name '$default' \
    --access-log-settings '{"DestinationArn": "arn:aws:logs:region:account-id:log-group:log-group-name", "Format": "$context.identity.sourceIp - - [$context.requestTime] \"$context.httpMethod $context.routeKey $context.protocol\" $context.status $context.responseLength $context.requestId"}'
```

------

## Example log formats
<a name="http-api-enable-logging.examples"></a>

Examples of some common access log formats are available 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.requestTime] "$context.httpMethod $context.routeKey $context.protocol" $context.status $context.responseLength $context.requestId $context.extendedRequestId
  ```
+  `JSON`: 

  ```
  { "requestId":"$context.requestId", "ip": "$context.identity.sourceIp", "requestTime":"$context.requestTime", "httpMethod":"$context.httpMethod","routeKey":"$context.routeKey", "status":"$context.status","protocol":"$context.protocol", "responseLength":"$context.responseLength", "extendedRequestId": "$context.extendedRequestId" }
  ```
+ `XML`: 

  ```
  <request id="$context.requestId"> <ip>$context.identity.sourceIp</ip> <requestTime>$context.requestTime</requestTime> <httpMethod>$context.httpMethod</httpMethod> <routeKey>$context.routeKey</routeKey> <status>$context.status</status> <protocol>$context.protocol</protocol> <responseLength>$context.responseLength</responseLength> <extendedRequestId>$context.extendedRequestId</extendedRequestId> </request>
  ```
+ `CSV` (comma-separated values):

  ```
  $context.identity.sourceIp,$context.requestTime,$context.httpMethod,$context.routeKey,$context.protocol,$context.status,$context.responseLength,$context.requestId,$context.extendedRequestId
  ```

# Customize HTTP API access logs
<a name="http-api-logging-variables"></a>

You can use the following variables to customize HTTP API access logs. To learn more about access logs for HTTP APIs, see [Configure logging for HTTP APIs in API Gateway](http-api-logging.md).


| 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 JSON Web Token (JWT) after the method caller is successfully authenticated, such as `$context.authorizer.claims.username`. For more information, see [Control access to HTTP APIs with JWT authorizers in API Gateway](http-api-jwt-authorizer.md).  Calling `$context.authorizer.claims` returns null.   | 
| \$1context.authorizer.error | The error message returned from an authorizer. | 
| \$1context.authorizer.property |  The 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`, and calling `$context.authorizer.boolKey` returns `true`.  | 
| \$1context.awsEndpointRequestId |  The AWS endpoint's request ID from the `x-amz-request-id` or `x-amzn-requestId` header.  | 
| \$1context.awsEndpointRequestId2 |  The AWS endpoint's request ID from the `x-amz-id-2` header.  | 
| \$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 [Map API stages to a custom domain name for HTTP APIs](http-api-mappings.md).  | 
| \$1context.dataProcessed | The amount of data processed in bytes. | 
| \$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 that contains an API Gateway error message.  | 
| \$1context.error.messageString | The quoted value of \$1context.error.message, namely "\$1context.error.message". | 
| \$1context.error.responseType |  A type of `GatewayResponse`. 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.extendedRequestId | Equivalent to \$1context.requestId. | 
| \$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. Supported for routes that use IAM authorization.  | 
| \$1context.identity.caller |  The principal identifier of the caller that signed the request. Supported for routes 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). Supported for routes that use IAM authorization.  | 
| \$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.  | 
| \$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.  | 
| \$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.  | 
| \$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.  | 
| \$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.  | 
| \$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.  | 
| \$1context.identity.sourceIp |  The source IP address of the immediate TCP connection making the request to API Gateway endpoint.  | 
| \$1context.identity.user |  The principal identifier of the user that will be authorized against resource access. Supported for routes 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. Supported for routes that use IAM authorization. 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. Equivalent to \$1context.integrationErrorMessage. | 
| \$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.status | The status code returned from an integration. For Lambda proxy integrations, this is the status code that your Lambda function code returns. | 
| \$1context.integrationErrorMessage |  A string that contains an integration error message.  | 
| \$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. | 
| \$1context.path | The request path. For example, /\$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 |  The ID that API Gateway assigns to the API request.  | 
| \$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. | 
| \$1context.responseLatency | The response latency in ms. | 
| \$1context.responseLength | The response payload length in bytes. | 
| \$1context.routeKey |  The route key of the API request, for example `/pets`.  | 
| \$1context.stage |  The deployment stage of the API request (for example, `beta` or `prod`).  | 
| \$1context.status | The method response status. | 

# Troubleshooting issues with HTTP APIs in API Gateway
<a name="http-api-troubleshooting"></a>

The following topics provide troubleshooting advice for errors and issues that you might encounter when using HTTP APIs.

**Topics**
+ [

# Troubleshooting issues with HTTP API Lambda integrations
](http-api-troubleshooting-lambda.md)
+ [

# Troubleshooting issues with HTTP API JWT authorizers
](http-api-troubleshooting-jwt.md)

# Troubleshooting issues with HTTP API Lambda integrations
<a name="http-api-troubleshooting-lambda"></a>

The following provides troubleshooting advice for errors and issues that you might encounter when using [AWS Lambda integrations](http-api-develop-integrations-lambda.md) with HTTP APIs.

## Issue: My API with a Lambda integration returns `{"message":"Internal Server Error"}`
<a name="http-api-troubleshooting-lambda-internal-server-error"></a>

To troubleshoot the internal server error, add the `$context.integrationErrorMessage` [logging variable](http-api-logging-variables.md) to your log format, and view your HTTP API's logs. To achieve this, do the following:

**To create a log group by using the AWS Management Console**

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. Choose **Log groups**.

1. Choose **Create log group**.

1. Enter a log group name, and then choose **Create**.

1. Note the Amazon Resource Name (ARN) for your log group. The ARN format is arn:aws:logs:*region*: *account-id*:log-group:*log-group-name*. You need the log group ARN to enable access logging for your HTTP API.

**To add the `$context.integrationErrorMessage` logging variable**

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

1. Choose your HTTP API.

1. Under **Monitor**, choose **Logging**.

1. Select a stage of your API.

1. Choose **Edit**, and then enable access logging.

1. For **Log destination**, enter the ARN of the log group that you created in the previous step.

1. For **Log format**, choose **CLF**. API Gateway creates an example log format. 

1. Add `$context.integrationErrorMessage` to the end of the log format.

1. Choose **Save**.

**To view your API's logs**

1. Generate logs. Use a browser or `curl` to invoke your API.

   ```
   $curl https://api-id.execute-api.us-west-2.amazonaws.com/route
   ```

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

1. Choose your HTTP API.

1. Under **Monitor**, choose **Logging**.

1. Select the stage of your API for which you enabled logging.

1. Choose **View logs in CloudWatch**.

1. Choose the latest log stream to view your HTTP API's logs.

1. Your log entry should look similar to the following:  
![\[CloudWatch Logs log entry showing the integration error message from Lambda.\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/troubleshoot-http-api-logs.png)

Because we added `$context.integrationErrorMessage` to the log format, we see an error message in our logs that summarizes the problem. 

Your logs might include a different error message that indicates that there's a problem with your Lambda function code. In that case, check your Lambda function code, and verify that your Lambda function returns a response in the [required format](http-api-develop-integrations-lambda.md#http-api-develop-integrations-lambda.response). If your logs don't include an error message, add `$context.error.message` and `$context.error.responseType` to your log format for more information to help troubleshoot.

In this case, the logs show that API Gateway didn't have the required permissions to invoke the Lambda function.

When you create a Lambda integration in the API Gateway console, API Gateway automatically configures permissions to invoke the Lambda function. When you create a Lambda integration by using the AWS CLI, CloudFormation, or an SDK, you must grant permissions for API Gateway to invoke the function. The following [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) commands grant permission for different HTTP API routes to invoke a Lambda function.

**Example – For the `$default` stage and `$default` route of an HTTP API**  

```
aws lambda add-permission \
    --function-name my-function \
    --statement-id apigateway-invoke-permissions \
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/\$default/\$default"
```

**Example – For the `prod` stage and `test` route of an HTTP API**  

```
aws lambda add-permission \
    --function-name my-function \
    --statement-id apigateway-invoke-permissions \
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/prod/*/test"
```

[Confirm the function policy](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html) in the **Permissions** tab of the Lambda console.

Try invoking your API again. You should see your Lambda function's response.

# Troubleshooting issues with HTTP API JWT authorizers
<a name="http-api-troubleshooting-jwt"></a>

The following provides troubleshooting advice for errors and issues that you might encounter when using JSON Web Token (JWT) authorizers with HTTP APIs.

## Issue: My API returns `401 {"message":"Unauthorized"}`
<a name="http-api-troubleshooting-jwt.unauthorized"></a>

Check the `www-authenticate` header in the response from the API.

The following command uses `curl` to send a request to an API with a JWT authorizer that uses `$request.header.Authorization` as its identity source.

```
$curl -v -H "Authorization: token" https://api-id.execute-api.us-west-2.amazonaws.com/route
```

The response from the API includes a `www-authenticate` header.

```
...
< HTTP/1.1 401 Unauthorized
< Date: Wed, 13 May 2020 04:07:30 GMT
< Content-Length: 26
< Connection: keep-alive
< www-authenticate: Bearer scope="" error="invalid_token" error_description="the token does not have a valid audience"
< apigw-requestid: Mc7UVioPPHcEKPA=
<
* Connection #0 to host api-id.execute-api.us-west-2.amazonaws.com left intact
{"message":"Unauthorized"}}
```

In this case, the `www-authenticate` header shows that the token wasn't issued for a valid audience. For API Gateway to authorize a request, the JWT's `aud` or `client_id` claim must match one of the audience entries that's configured for the authorizer. API Gateway validates `client_id` only if `aud` is not present. When both `aud` and `client_id` are present, API Gateway evaluates `aud`. 

You can also decode a JWT and verify that it matches the issuer, audience, and scopes that your API requires. The website [jwt.io](https://jwt.io/) can debug JWTs in the browser. The OpenID Foundation maintains a [list of libraries for working with JWTs](https://openid.net/developers/jwt-jws-jwe-jwk-and-jwa-implementations/). 

To learn more about JWT authorizers, see [Control access to HTTP APIs with JWT authorizers in API Gateway](http-api-jwt-authorizer.md).