

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