

# Lambda integrations for REST APIs in API Gateway
<a name="set-up-lambda-integrations"></a>

 You can integrate an API method with a Lambda function using Lambda proxy integration or Lambda non-proxy (custom) integration. 

In Lambda proxy integration, the required setup is simple. Set the integration's HTTP method to POST, the integration endpoint URI to the ARN of the Lambda function invocation action of a specific Lambda function, and grant API Gateway permission to call the Lambda function on your behalf.

In Lambda non-proxy integration, in addition to the proxy integration setup steps, you also specify how the incoming request data is mapped to the integration request and how the resulting integration response data is mapped to the method response. 

**Topics**
+ [

# Lambda proxy integrations in API Gateway
](set-up-lambda-proxy-integrations.md)
+ [

# Set up Lambda custom integrations in API Gateway
](set-up-lambda-custom-integrations.md)
+ [

# Set up asynchronous invocation of the backend Lambda function
](set-up-lambda-integration-async.md)
+ [

# Handle Lambda errors in API Gateway
](handle-errors-in-lambda-integration.md)

# Lambda proxy integrations in API Gateway
<a name="set-up-lambda-proxy-integrations"></a>

The following section shows how to use a Lambda proxy integration.

**Topics**
+ [

## Understand API Gateway Lambda proxy integration
](#api-gateway-create-api-as-simple-proxy)
+ [

## Support for multi-value headers and query string parameters
](#apigateway-multivalue-headers-and-parameters)
+ [

## Input format of a Lambda function for proxy integration
](#api-gateway-simple-proxy-for-lambda-input-format)
+ [

## Output format of a Lambda function for proxy integration
](#api-gateway-simple-proxy-for-lambda-output-format)
+ [

# Set up Lambda proxy integration for API Gateway using the AWS CLI
](set-up-lambda-proxy-integration-using-cli.md)
+ [

# Set up a proxy resource with Lambda proxy integration with an OpenAPI definition
](api-gateway-set-up-lambda-proxy-integration-on-proxy-resource.md)

## Understand API Gateway Lambda proxy integration
<a name="api-gateway-create-api-as-simple-proxy"></a>

Amazon API Gateway Lambda proxy integration is a simple, powerful, and nimble mechanism to build an API with a setup of a single API method. The Lambda proxy integration allows the client to call a single Lambda function in the backend. The function accesses many resources or features of other AWS services, including calling other Lambda functions. 

 In Lambda proxy integration, when a client submits an API request, API Gateway passes to the integrated Lambda function an [event object](#api-gateway-simple-proxy-for-lambda-input-format), except that the order of the request parameters is not preserved. This [request data](#api-gateway-simple-proxy-for-lambda-input-format) includes the request headers, query string parameters, URL path variables, payload, and API configuration data. The configuration data can include current deployment stage name, stage variables, user identity, or authorization context (if any). The backend Lambda function parses the incoming request data to determine the response that it returns. For API Gateway to pass the Lambda output as the API response to the client, the Lambda function must return the result in [this format](#api-gateway-simple-proxy-for-lambda-output-format). 

 Because API Gateway doesn't intervene very much between the client and the backend Lambda function for the Lambda proxy integration, the client and the integrated Lambda function can adapt to changes in each other without breaking the existing integration setup of the API. To enable this, the client must follow application protocols enacted by the backend Lambda function. 

 You can set up a Lambda proxy integration for any API method. But a Lambda proxy integration is more potent when it is configured for an API method involving a generic proxy resource. The generic proxy resource can be denoted by a special templated path variable of `{proxy+}`, the catch-all `ANY` method placeholder, or both. The client can pass the input to the backend Lambda function in the incoming request as request parameters or applicable payload. The request parameters include headers, URL path variables, query string parameters, and the applicable payload. The integrated Lambda function verifies all of the input sources before processing the request and responding to the client with meaningful error messages if any of the required input is missing.

 When calling an API method integrated with the generic HTTP method of `ANY` and the generic resource of `{proxy+}`, the client submits a request with a particular HTTP method in place of `ANY`. The client also specifies a particular URL path instead of `{proxy+}`, and includes any required headers, query string parameters, or an applicable payload. 

 The following list summarizes runtime behaviors of different API methods with the Lambda proxy integration: 
+ `ANY /{proxy+}`: The client must choose a particular HTTP method, must set a particular resource path hierarchy, and can set any headers, query string parameters, and applicable payload to pass the data as input to the integrated Lambda function. 
+ `ANY /res`: The client must choose a particular HTTP method and can set any headers, query string parameters, and applicable payload to pass the data as input to the integrated Lambda function. 
+ `GET|POST|PUT|... /{proxy+}`: The client can set a particular resource path hierarchy, any headers, query string parameters, and applicable payload to pass the data as input to the integrated Lambda function. 
+  `GET|POST|PUT|... /res/{path}/...`: The client must choose a particular path segment (for the `{path}` variable) and can set any request headers, query string parameters, and applicable payload to pass input data to the integrated Lambda function.
+  `GET|POST|PUT|... /res`: The client can choose any request headers, query string parameters, and applicable payload to pass input data to the integrated Lambda function.

 Both the proxy resource of `{proxy+}` and the custom resource of `{custom}` are expressed as templated path variables. However `{proxy+}` can refer to any resource along a path hierarchy, while `{custom}` refers to a particular path segment only. For example, a grocery store might organize its online product inventory by department names, produce categories, and product types. The grocery store's website can then represent available products by the following templated path variables of custom resources: `/{department}/{produce-category}/{product-type}`. For example, apples are represented by `/produce/fruit/apple` and carrots by `/produce/vegetables/carrot`. It can also use `/{proxy+}` to represent any department, any produce category, or any product type that a customer can search for while shopping in the online store. For example, `/{proxy+}` can refer to any of the following items: 
+ `/produce`
+ `/produce/fruit`
+ `/produce/vegetables/carrot`

 To let customers search for any available product, its produce category, and the associated store department, you can expose a single method of `GET /{proxy+}` with read-only permissions. Similarly, to allow a supervisor to update the `produce` department's inventory, you can set up another single method of `PUT /produce/{proxy+}` with read/write permissions. To allow a cashier to update the running total of a vegetable, you can set up a `POST /produce/vegetables/{proxy+}` method with read/write permissions. To let a store manager perform any possible action on any available product, the online store developer can expose the `ANY /{proxy+}` method with read/write permissions. In any case, at run time, the customer or the employee must select a particular product of a given type in a chosen department, a specific produce category in a chosen department, or a specific department. 



For more information about setting up API Gateway proxy integrations, see [Set up a proxy integration with a proxy resource](api-gateway-set-up-simple-proxy.md). 

 Proxy integration requires that the client have more detailed knowledge of the backend requirements. Therefore, to ensure optimal app performance and user experience, the backend developer must communicate clearly to the client developer the requirements of the backend, and provide a robust error feedback mechanism when the requirements are not met. 

## Support for multi-value headers and query string parameters
<a name="apigateway-multivalue-headers-and-parameters"></a>

API Gateway supports multiple headers and query string parameters that have the same name. Multi-value headers as well as single-value headers and parameters can be combined in the same requests and responses. For more information, see [Input format of a Lambda function for proxy integration](#api-gateway-simple-proxy-for-lambda-input-format) and [Output format of a Lambda function for proxy integration](#api-gateway-simple-proxy-for-lambda-output-format).

## Input format of a Lambda function for proxy integration
<a name="api-gateway-simple-proxy-for-lambda-input-format"></a>

In Lambda proxy integration, API Gateway maps the entire client request to the input `event` parameter of the backend Lambda function. The following example shows the structure of an event that API Gateway sends to a Lambda proxy integration.

In this example, we assume that the invocation to API Gateway was the following:

```
curl 'https://a1b2c3.execute-api.us-east-1.amazonaws.com/my/path?parameter1=value1&parameter2=value1&parameter2=value2&parameter3=value1,value2' -H 'header1: value1' -H 'header2: value1' -H 'header2: value2' -H 'header3: value1,value2'
```

The output looks like the following:

```
{
  "resource": "/my/path",
  "path": "/my/path",
  "httpMethod": "GET",
  "headers": {
      "header1": "value1",
      "header2": "value2",
      "header3": "value1,value2"
  },
  "multiValueHeaders": {
    "header1": ["value1"],
    "header2": ["value1","value2"],
    "header3": ["value1,value2"]
  },
  "queryStringParameters": {
      "parameter1": "value1",
      "parameter2": "value2",
      "parameter3": "value1,value2"
  },
  "multiValueQueryStringParameters": {
    "parameter1": ["value1"],
    "parameter2": ["value1","value2"],
    "parameter3": ["value1,value2"]
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "id",
    "authorizer": {
      "claims": null,
      "scopes": null
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "extendedRequestId": "request-id",
    "httpMethod": "GET",
    "identity": {
      "accessKey": null,
      "accountId": null,
      "caller": null,
      "cognitoAuthenticationProvider": null,
      "cognitoAuthenticationType": null,
      "cognitoIdentityId": null,
      "cognitoIdentityPoolId": null,
      "principalOrgId": null,
      "sourceIp": "IP",
      "user": null,
      "userAgent": "user-agent",
      "userArn": null,
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "path": "/my/path",
    "protocol": "HTTP/1.1",
    "requestId": "id=",
    "requestTime": "04/Mar/2020:19:15:17 +0000",
    "requestTimeEpoch": 1583349317135,
    "resourceId": null,
    "resourcePath": "/my/path",
    "stage": "$default"
  },
  "pathParameters": null,
  "stageVariables": null,
  "body": "Hello from Lambda!",
  "isBase64Encoded": false
}
```

**Note**  
In the input:  
The `headers` key can only contain single-value headers.
The `multiValueHeaders` key can contain multi-value headers as well as single-value headers.
If you specify values for both `headers` and `multiValueHeaders`, API Gateway merges them into a single list. If the same key-value pair is specified in both, only the values from `multiValueHeaders` will appear in the merged list.

In the input to the backend Lambda function, the `requestContext` object is a map of key-value pairs. In each pair, the key is the name of a [\$1context](api-gateway-mapping-template-reference.md#context-variable-reference) variable property, and the value is the value of that property. API Gateway might add new keys to the map.

Depending on the features that are enabled, the `requestContext` map may vary from API to API. For example, in the preceding example, no authorization type is specified, so no `$context.authorizer.*` or `$context.identity.*` properties are present. When an authorization type is specified, this causes API Gateway to pass authorized user information to the integration endpoint in a `requestContext.identity` object as follows:
+ When the authorization type is `AWS_IAM`, the authorized user information includes `$context.identity.*` properties.
+ When the authorization type is `COGNITO_USER_POOLS` (Amazon Cognito authorizer), the authorized user information includes `$context.identity.cognito*` and `$context.authorizer.claims.*` properties.
+ When the authorization type is `CUSTOM` (Lambda authorizer), the authorized user information includes `$context.authorizer.principalId` and other applicable `$context.authorizer.*` properties.

## Output format of a Lambda function for proxy integration
<a name="api-gateway-simple-proxy-for-lambda-output-format"></a>

In Lambda proxy integration, API Gateway requires the backend Lambda function to return output according to the following JSON format:

```
{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}
```

In the output:
+ The `headers` and `multiValueHeaders` keys can be unspecified if no extra response headers are to be returned.
+ The `headers` key can only contain single-value headers.
+ The `multiValueHeaders` key can contain multi-value headers as well as single-value headers. You can use the `multiValueHeaders` key to specify all of your extra headers, including any single-value ones.
+ If you specify values for both `headers` and `multiValueHeaders`, API Gateway merges them into a single list. If the same key-value pair is specified in both, only the values from `multiValueHeaders` will appear in the merged list.

To enable CORS for the Lambda proxy integration, you must add `Access-Control-Allow-Origin:domain-name` to the output `headers`. `domain-name` can be `*` for any domain name. The output `body` is marshalled to the frontend as the method response payload. If `body` is a binary blob, you can encode it as a Base64-encoded string by setting `isBase64Encoded` to `true` and configuring `*/*` as a **Binary Media Type**. Otherwise, you can set it to `false` or leave it unspecified.

**Note**  
For more information about enabling binary support, see [Enabling binary support using the API Gateway console](api-gateway-payload-encodings-configure-with-console.md). For an example Lambda function, see [Return binary media from a Lambda proxy integration in API Gateway](lambda-proxy-binary-media.md).

If the function output is of a different format, API Gateway returns a `502 Bad Gateway` error response. 

To return a response in a Lambda function in Node.js, you can use commands such as the following:
+ To return a successful result, call `callback(null, {"statusCode": 200, "body": "results"})`.
+ To throw an exception, call `callback(new Error('internal server error'))`.
+ For a client-side error (if, for example, a required parameter is missing), you can call `callback(null, {"statusCode": 400, "body": "Missing parameters of ..."})` to return the error without throwing an exception.

In a Lambda `async` function in Node.js, the equivalent syntax would be:
+ To return a successful result, call `return {"statusCode": 200, "body": "results"}`.
+ To throw an exception, call `throw new Error("internal server error")`.
+ For a client-side error (if, for example, a required parameter is missing), you can call `return {"statusCode": 400, "body": "Missing parameters of ..."}` to return the error without throwing an exception.

# Set up Lambda proxy integration for API Gateway using the AWS CLI
<a name="set-up-lambda-proxy-integration-using-cli"></a>

In this section, we show how to set up an API with the Lambda proxy integration using the AWS CLI. For detailed instructions for using the API Gateway console to configure a proxy resource with the Lambda proxy integration, see [Tutorial: Create a REST API with a Lambda proxy integration](api-gateway-create-api-as-simple-proxy-for-lambda.md).

As an example, we use the following sample Lambda function as the backend of the API:

```
export const handler = async(event, context) => {
    console.log('Received event:', JSON.stringify(event, null, 2));
    var res ={
        "statusCode": 200,
        "headers": {
            "Content-Type": "*/*"
        }
    };
    var greeter = 'World';
    if (event.greeter && event.greeter!=="") {
        greeter =  event.greeter;
    } else if (event.body && event.body !== "") {
        var body = JSON.parse(event.body);
        if (body.greeter && body.greeter !== "") {
            greeter = body.greeter;
        }
    } else if (event.queryStringParameters && event.queryStringParameters.greeter && event.queryStringParameters.greeter !== "") {
        greeter = event.queryStringParameters.greeter;
    } else if (event.multiValueHeaders && event.multiValueHeaders.greeter && event.multiValueHeaders.greeter != "") {
        greeter = event.multiValueHeaders.greeter.join(" and ");
    } else if (event.headers && event.headers.greeter && event.headers.greeter != "") {
        greeter = event.headers.greeter;
    } 
    res.body = "Hello, " + greeter + "!";
    return res
};
```

Comparing this to the Lambda custom integration setup in [Set up Lambda custom integrations in API Gateway](set-up-lambda-custom-integrations.md), the input to this Lambda function can be expressed in the request parameters and body. You have more latitude to allow the client to pass the same input data. Here, the client can pass the greeter's name in as a query string parameter, a header, or a body property. The function can also support the Lambda custom integration. The API setup is simpler. You do not configure the method response or integration response at all.

**To set up a Lambda proxy integration using the AWS CLI**

1. Use the following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command to create an API:

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   The output will look like the following:

   ```
   {
       "name": "HelloWorldProxy (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   You use the API `id` (`te6si5ach7`) and the `rootResourceId` ( `krznpq9xpg`) throughout this example.

1. Use the following [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) command to create an API Gateway [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) of `/greeting`:

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

   The output will look like the following:

   ```
   {
       "path": "/{proxy+}", 
       "pathPart": "{proxy+}", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   You use the `{proxy+}` resource's `id` value (`2jf6xt`) to create a method on the `/{proxy+}` resource in the next step.

1. Use the following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) to create an `ANY` method request of `ANY /{proxy+}`:

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method ANY \
          --authorization-type "NONE"
   ```

   The output will look like the following:

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "ANY", 
       "authorizationType": "NONE"
   }
   ```

   This API method allows the client to receive or send greetings from the Lambda function at the backend. 

1. Use the following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) command to set up the integration of the `ANY /{proxy+}` method with a Lambda function, named `HelloWorld`. This function responds to the request with a message of `"Hello, {name}!"`, if the `greeter` parameter is provided, or `"Hello, World!"`, if the query string parameter is not set.

   ```
   aws apigateway put-integration \
         --rest-api-id te6si5ach7 \
         --resource-id 2jf6xt \
         --http-method ANY \
         --type AWS_PROXY \
         --integration-http-method POST \
         --uri arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:HelloWorld/invocations \
         --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```
**Important**  
For Lambda integrations, you must use the HTTP method of `POST` for the integration request, according to the [specification of the Lambda service action for function invocations](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html). The IAM role of `apigAwsProxyRole` must have policies allowing the `apigateway` service to invoke Lambda functions. For more information about IAM permissions, see [API Gateway permissions model for invoking an API](permissions.md#api-gateway-control-access-iam-permissions-model-for-calling-api).

   The output will look like the following:

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:1234567890:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "cacheNamespace": "vvom7n", 
       "credentials": "arn:aws:iam::1234567890:role/apigAwsProxyRole", 
       "type": "AWS_PROXY"
   }
   ```

   Instead of supplying an IAM role for `credentials`, you can use the [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command to add resource-based permissions. This is what the API Gateway console does. 

1. Use the following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to deploy the API to a `test` stage:

   ```
   aws apigateway create-deployment  \
         --rest-api-id te6si5ach7 \
         --stage-name test
   ```

1. Test the API using the following cURL commands in a terminal.

   Calling the API with the query string parameter of `?greeter=jane`:

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=jane'
   ```

   Calling the API with a header parameter of `greeter:jane`:

   ```
   curl -X GET https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -H 'greeter: jane'
   ```

   Calling the API with a body of `{"greeter":"jane"}`:

   ```
   curl -X POST https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/hi \
     -H 'content-type: application/json' \
     -d '{ "greeter": "jane" }'
   ```

   In all the cases, the output is a 200 response with the following response body:

   ```
   Hello, jane!
   ```

# Set up a proxy resource with Lambda proxy integration with an OpenAPI definition
<a name="api-gateway-set-up-lambda-proxy-integration-on-proxy-resource"></a>

To set up a proxy resource with the Lambda proxy integration type, create an API resource with a greedy path parameter (for example, `/parent/{proxy+}`) and integrate this resource with a Lambda function backend (for example, `arn:aws:lambda:us-west-2:123456789012:function:SimpleLambda4ProxyResource`) on the `ANY` method. The greedy path parameter must be at the end of the API resource path. As with a non-proxy resource, you can set up the proxy resource by using the API Gateway console, importing an OpenAPI definition file, or calling the API Gateway REST API directly.

The following OpenAPI API definition file shows an example of an API with a proxy resource that is integrated with a Lambda function named `SimpleLambda4ProxyResource`.

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

```
{
   "openapi": "3.0.0",
   "info": {
      "version": "2016-09-12T17:50:37Z",
      "title": "ProxyIntegrationWithLambda"
   },
   "paths": {
      "/{proxy+}": {
         "x-amazon-apigateway-any-method": {
            "parameters": [
               {
                  "name": "proxy",
                  "in": "path",
                  "required": true,
                  "schema": {
                     "type": "string"
                  }
               }
            ],
            "responses": {},
            "x-amazon-apigateway-integration": {
               "responses": {
                  "default": {
                     "statusCode": "200"
                  }
               },
               "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
               "passthroughBehavior": "when_no_match",
               "httpMethod": "POST",
               "cacheNamespace": "roq9wj",
               "cacheKeyParameters": [
                  "method.request.path.proxy"
               ],
               "type": "aws_proxy"
            }
         }
      }
   },
   "servers": [
      {
         "url": "https://gy415nuibc.execute-api.us-east-1.amazonaws.com/{basePath}",
         "variables": {
            "basePath": {
              "default": "/testStage"
            }
         }
      }
   ]
}
```

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

```
{
  "swagger": "2.0",
  "info": {
    "version": "2016-09-12T17:50:37Z",
    "title": "ProxyIntegrationWithLambda"
  },
  "host": "gy415nuibc.execute-api.us-east-1.amazonaws.com",
  "basePath": "/testStage",
  "schemes": [
    "https"
  ],
  "paths": {
    "/{proxy+}": {
      "x-amazon-apigateway-any-method": {
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "name": "proxy",
            "in": "path",
            "required": true,
            "type": "string"
          }
        ],
        "responses": {},
        "x-amazon-apigateway-integration": {
          "responses": {
            "default": {
              "statusCode": "200"
            }
          },
          "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:SimpleLambda4ProxyResource/invocations",
          "passthroughBehavior": "when_no_match",
          "httpMethod": "POST",
          "cacheNamespace": "roq9wj",
          "cacheKeyParameters": [
            "method.request.path.proxy"
          ],
          "type": "aws_proxy"
        }
      }
    }
  }
}
```

------

In Lambda proxy integration, at run time, API Gateway maps an incoming request into the input `event` parameter of the Lambda function. The input includes the request method, path, headers, any query string parameters, any payload, associated context, and any defined stage variables. The input format is explained in [Input format of a Lambda function for proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-input-format). For API Gateway to map the Lambda output to HTTP responses successfully, the Lambda function must output the result in the format described in [Output format of a Lambda function for proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-simple-proxy-for-lambda-output-format). 

In Lambda proxy integration of a proxy resource through the `ANY` method, the single backend Lambda function serves as the event handler for all requests through the proxy resource. For example, to log traffic patterns, you can have a mobile device send its location information of state, city, street, and building by submitting a request with `/state/city/street/house` in the URL path for the proxy resource. The backend Lambda function can then parse the URL path and insert the location tuples into a DynamoDB table.

# Set up Lambda custom integrations in API Gateway
<a name="set-up-lambda-custom-integrations"></a>

 To show how to set up the Lambda custom, or non-proxy,integration, we create an API Gateway API to expose the `GET /greeting?greeter={name}` method to invoke a Lambda function. Use one of the following example Lambda functions for you API.

Use one of the following example Lambda functions:

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

```
'use strict';
var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];            
var times = ['morning', 'afternoon', 'evening', 'night', 'day'];

export const handler = async(event) => {
  console.log(event);
  // Parse the input for the name, city, time and day property values
  let name = event.name === null || event.name === undefined || event.name === "" ? 'you' : event.name;
  let city = event.city === undefined ? 'World' : event.city;
  let time = times.indexOf(event.time)<0 ? 'day' : event.time;
  let day = days.indexOf(event.day)<0 ? null : event.day;

  // Generate a greeting
  let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. ';
  if (day) greeting += 'Happy ' + day + '!';
  
  // Log the greeting to CloudWatch
  console.log('Hello: ', greeting);
  
  // Return a greeting to the caller
  return greeting;
};
```

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

```
import json


def lambda_handler(event, context):
    print(event)
    res = {
        "statusCode": 200,
        "headers": {
            "Content-Type": "*/*"
        }
    }

    if event['greeter'] == "":
        res['body'] = "Hello, World"
    elif (event['greeter']):
        res['body'] = "Hello, " + event['greeter'] + "!"
    else:
        raise Exception('Missing the required greeter parameter.')

    return res
```

------

The function responds with a message of `"Hello, {name}!"` if the `greeter` parameter value is a non-empty string. It returns a message of `"Hello, World!"` if the `greeter` value is an empty string. The function returns an error message of `"Missing the required greeter parameter."` if the greeter parameter is not set in the incoming request. We name the function `HelloWorld`.

You can create it in the Lambda console or by using the AWS CLI. In this section, we reference this function using the following ARN:

```
arn:aws:lambda:us-east-1:123456789012:function:HelloWorld
```

With the Lambda function set in the backend, proceed to set up the API.<a name="set-up-lambda-custom-integration-using-cli"></a>

**To set up the Lambda custom integration using the AWS CLI**

1. Use the following [create-rest-api](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-rest-api.html) command to create an API:

   ```
   aws apigateway create-rest-api --name 'HelloWorld (AWS CLI)'
   ```

   The output will look like the following:

   ```
   {
       "name": "HelloWorld (AWS CLI)", 
       "id": "te6si5ach7",
       "rootResourceId" : "krznpq9xpg",
       "createdDate": 1508461860
   }
   ```

   You use the API `id` ( `te6si5ach7`) and the `rootResourceId` (`krznpq9xpg`) throughout this example.

1. Use the following [create-resource](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-resource.html) command to create an API Gateway [Resource](https://docs.aws.amazon.com/apigateway/latest/api/API_Resource.html) of `/greeting`:

   ```
   aws apigateway create-resource \
         --rest-api-id te6si5ach7 \
         --parent-id krznpq9xpg \
         --path-part greeting
   ```

   The output will look like the following:

   ```
   {
       "path": "/greeting", 
       "pathPart": "greeting", 
       "id": "2jf6xt", 
       "parentId": "krznpq9xpg"
   }
   ```

   You use the `greeting` resource's `id` value (`2jf6xt`) to create a method on the `/greeting` resource in the next step.

1. Use the following [put-method](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method.html) command to create an API method request of `GET /greeting?greeter={name}`:

   ```
   aws apigateway put-method --rest-api-id te6si5ach7 \
          --resource-id 2jf6xt \
          --http-method GET \
          --authorization-type "NONE" \
          --request-parameters method.request.querystring.greeter=false
   ```

   The output will look like the following:

   ```
   {
       "apiKeyRequired": false, 
       "httpMethod": "GET", 
       "authorizationType": "NONE", 
       "requestParameters": {
           "method.request.querystring.greeter": false
       }
   }
   ```

   This API method allows the client to receive a greeting from the Lambda function at the backend. The `greeter` parameter is optional because the backend should handle either an anonymous caller or a self-identified caller.

1. Use the following [put-method-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-method-response.html) command to set up the `200 OK` response to the method request of `GET /greeting?greeter={name}`:

   ```
   aws apigateway put-method-response \
           --rest-api-id te6si5ach7 \ 
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200
   ```

   

1. Use the following [put-integration](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration.html) command to set up the integration of the `GET /greeting?greeter={name}` method with a Lambda function, named `HelloWorld`. The function responds to the request with a message of `"Hello, {name}!"`, if the `greeter` parameter is provided, or `"Hello, World!"`, if the query string parameter is not set.

   ```
   aws apigateway put-integration \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --type AWS \
           --integration-http-method POST \
           --uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations \
           --request-templates '{"application/json":"{\"greeter\":\"$input.params('greeter')\"}"}' \
           --credentials arn:aws:iam::123456789012:role/apigAwsProxyRole
   ```

   The mapping template supplied here translates the `greeter` query string parameter to the `greeter` property of the JSON payload. This is necessary because the input to a Lambda function must be expressed in the body.
**Important**  
For Lambda integrations, you must use the HTTP method of `POST` for the integration request, according to the [specification of the Lambda service action for function invocations](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html). The `uri` parameter is the ARN of the function-invoking action.  
The output will look like the following:

   ```
   {
       "passthroughBehavior": "WHEN_NO_MATCH", 
       "cacheKeyParameters": [], 
       "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:HelloWorld/invocations", 
       "httpMethod": "POST", 
       "requestTemplates": {
           "application/json": "{\"greeter\":\"$input.params('greeter')\"}"
       }, 
       "cacheNamespace": "krznpq9xpg", 
       "credentials": "arn:aws:iam::123456789012:role/apigAwsProxyRole", 
       "type": "AWS"
   }
   ```

   The IAM role of `apigAwsProxyRole` must have policies that allow the `apigateway` service to invoke Lambda functions. Instead of supplying an IAM role for `credentials`, you can call the [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) command to add resource-based permissions. This is how the API Gateway console adds these permissions. 

1. Use the following [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) command to set up the integration response to pass the Lambda function output to the client as the `200 OK` method response:

   ```
    aws apigateway put-integration-response \
           --rest-api-id te6si5ach7 \
           --resource-id 2jf6xt \
           --http-method GET \
           --status-code 200 \
           --selection-pattern ""
   ```

   By setting the selection-pattern to an empty string, the `200 OK` response is the default. 

   The output will look like the following:

   ```
    {
       "selectionPattern": "", 
       "statusCode": "200"
   }
   ```

1. Use the following [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigateway/create-deployment.html) command to deploy the API to a `test` stage:

   ```
   aws apigateway create-deployment \
           --rest-api-id te6si5ach7 \
           --stage-name test
   ```

1.  Test the API using the following cURL command in a terminal:

   ```
   curl -X GET 'https://te6si5ach7.execute-api.us-west-2.amazonaws.com/test/greeting?greeter=me' \
     -H 'authorization: AWS4-HMAC-SHA256 Credential={access_key}/20171020/us-west-2/execute-api/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=f327...5751'
   ```

# Set up asynchronous invocation of the backend Lambda function
<a name="set-up-lambda-integration-async"></a>

In Lambda non-proxy (custom) integration, the backend Lambda function is invoked synchronously by default. This is the desired behavior for most REST API operations. Some applications, however, require work to be performed asynchronously (as a batch operation or a long-latency operation), typically by a separate backend component. In this case, the backend Lambda function is invoked asynchronously, and the front-end REST API method doesn't return the result.

You can configure the Lambda function for a Lambda non-proxy integration to be invoked asynchronously by specifying `'Event'` as the [Lambda invocation type](https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html). This is done as follows:

## Configure Lambda asynchronous invocation in the API Gateway console
<a name="asynchronous-invocation-console-examples"></a>

For all invocations to be asynchronous:
+ In **Integration request**, add an `X-Amz-Invocation-Type` header with a static value of `'Event'`.

For clients to decide if invocations are asynchronous or synchronous:

1. In **Method request**, add an `InvocationType` header.

1. In **Integration request** add an `X-Amz-Invocation-Type` header with a mapping expression of `method.request.header.InvocationType`.

1. Clients can include the `InvocationType: Event` header in API requests for asynchronous invocations or `InvocationType: RequestResponse` for synchronous invocations.

## Configure Lambda asynchronous invocation using OpenAPI
<a name="asynchronous-invocation-OpenAPI-examples"></a>

For all invocations to be asynchronous:
+  Add the `X-Amz-Invocation-Type` header to the **x-amazon-apigateway-integration** section.

  ```
  "x-amazon-apigateway-integration" : {
            "type" : "aws",
            "httpMethod" : "POST",
            "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
            "responses" : {
              "default" : {
                "statusCode" : "200"
              }
            },
            "requestParameters" : {
              "integration.request.header.X-Amz-Invocation-Type" : "'Event'"
            },
            "passthroughBehavior" : "when_no_match",
            "contentHandling" : "CONVERT_TO_TEXT"
          }
  ```

For clients to decide if invocations are asynchronous or synchronous:

1.  Add the following header on any [OpenAPI Path Item Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#pathItemObject). 

   ```
   "parameters" : [ {
   "name" : "InvocationType",
   "in" : "header",
   "schema" : {
     "type" : "string"
   }
   } ]
   ```

1.  Add the `X-Amz-Invocation-Type` header to **x-amazon-apigateway-integration** section.

   ```
   "x-amazon-apigateway-integration" : {
             "type" : "aws",
             "httpMethod" : "POST",
             "uri" : "arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-2:123456789012:function:my-function/invocations",
             "responses" : {
               "default" : {
                 "statusCode" : "200"
               }
             },
             "requestParameters" : {
               "integration.request.header.X-Amz-Invocation-Type" : "method.request.header.InvocationType"
             },
             "passthroughBehavior" : "when_no_match",
             "contentHandling" : "CONVERT_TO_TEXT"
           }
   ```

1.  Clients can include the `InvocationType: Event` header in API requests for asynchronous invocations or `InvocationType: RequestResponse` for synchronous invocations. 

## Configure Lambda asynchronous invocation using CloudFormation
<a name="asynchronous-invocation-cfn-examples"></a>

The following CloudFormation templates show how to configure the `AWS::ApiGateway::Method` for asynchronous invocations.

For all invocations to be asynchronous:

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: "'Event'"
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

For clients to decide if invocations are asynchronous or synchronous:

```
AsyncMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref AsyncResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      RequestParameters:
        method.request.header.InvocationType: false
      Integration:
        Type: AWS
        RequestParameters:
          integration.request.header.X-Amz-Invocation-Type: method.request.header.InvocationType
        IntegrationResponses:
            - StatusCode: '200'
        IntegrationHttpMethod: POST
        Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${myfunction.Arn}$/invocations
      MethodResponses:
        - StatusCode: '200'
```

 Clients can include the `InvocationType: Event` header in API requests for asynchronous invocations or `InvocationType: RequestResponse` for synchronous invocations. 

# Handle Lambda errors in API Gateway
<a name="handle-errors-in-lambda-integration"></a>

 For Lambda custom integrations, you must map errors returned by Lambda in the integration response to standard HTTP error responses for your clients. Otherwise, Lambda errors are returned as `200 OK` responses by default and the result is not intuitive for your API users. 

 There are two types of errors that Lambda can return: standard errors and custom errors. In your API, you must handle these differently. 

 With the Lambda proxy integration, Lambda is required to return an output of the following format: 

```
{
  "isBase64Encoded" : "boolean",
  "statusCode": "number",
  "headers": { ... },
  "body": "JSON string"
}
```

In this output, `statusCode` is typically `4XX` for a client error and `5XX` for a server error. API Gateway handles these errors by mapping the Lambda error to an HTTP error response, according to the specified `statusCode`. For API Gateway to pass the error type (for example, `InvalidParameterException`), as part of the response to the client, the Lambda function must include a header (for example, `"X-Amzn-ErrorType":"InvalidParameterException"`) in the `headers` property. 

**Topics**
+ [

## Handle standard Lambda errors in API Gateway
](#handle-standard-errors-in-lambda-integration)
+ [

## Handle custom Lambda errors in API Gateway
](#handle-custom-errors-in-lambda-integration)

## Handle standard Lambda errors in API Gateway
<a name="handle-standard-errors-in-lambda-integration"></a>

A standard AWS Lambda error has the following format:

```
{
  "errorMessage": "<replaceable>string</replaceable>",
  "errorType": "<replaceable>string</replaceable>",
  "stackTrace": [
    "<replaceable>string</replaceable>",
    ...
  ]
}
```

 Here, `errorMessage` is a string expression of the error. The `errorType` is a language-dependent error or exception type. The `stackTrace` is a list of string expressions showing the stack trace leading to the occurrence of the error. 

 For example, consider the following JavaScript (Node.js) Lambda function. 

```
export const handler = function(event, context, callback) {
    callback(new Error("Malformed input ..."));
};
```

This function returns the following standard Lambda error, containing `Malformed input ...` as the error message:

```
{
  "errorMessage": "Malformed input ...",
  "errorType": "Error",
  "stackTrace": [
    "export const handler (/var/task/index.js:3:14)"
  ]
}
```

 Similarly, consider the following Python Lambda function, which raises an `Exception` with the same `Malformed input ...` error message. 

```
def lambda_handler(event, context):
    raise Exception('Malformed input ...')
```

 This function returns the following standard Lambda error: 

```
{
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      3,
      "lambda_handler",
      "raise Exception('Malformed input ...')"
    ]
  ],
  "errorType": "Exception",
  "errorMessage": "Malformed input ..."
}
```

 Note that the `errorType` and `stackTrace` property values are language-dependent. The standard error also applies to any error object that is an extension of the `Error` object or a subclass of the `Exception` class. 

 To map the standard Lambda error to a method response, you must first decide on an HTTP status code for a given Lambda error. You then set a regular expression pattern on the `[selectionPattern](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html#selectionPattern)` property of the [IntegrationResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_IntegrationResponse.html) associated with the given HTTP status code. In the API Gateway console, this `selectionPattern` is denoted as **Lambda error regex** in the **Integration response** section, under each integration response.

**Note**  
API Gateway uses Java pattern-style regexes for response mapping. For more information, see [Pattern](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) in the Oracle documentation.

 For example, use the following [put-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/put-integration-response.html) to set up a new `selectionPattern` expression: 

```
aws apigateway put-integration-response --rest-api-id z0vprf0mdh --resource-id x3o5ih --http-method GET --status-code 400 --selection-pattern "Malformed.*" --region us-west-2
```

 Make sure that you also set up the corresponding error code (`400`) on the [method response](api-gateway-method-settings-method-response.md#setup-method-response-status-code). Otherwise, API Gateway throws an invalid configuration error response at runtime. 

**Note**  
 At runtime, API Gateway matches the Lambda error's `errorMessage` against the pattern of the regular expression on the `selectionPattern` property. If there is a match, API Gateway returns the Lambda error as an HTTP response of the corresponding HTTP status code. If there is no match, API Gateway returns the error as a default response or throws an invalid configuration exception if no default response is configured.   
 Setting the `selectionPattern` value to `.*` for a given response amounts to resetting this response as the default response. This is because such a selection pattern will match all error messages, including null, i.e., any unspecified error message. The resulting mapping overrides the default mapping. If you use `.+` as the selection pattern to filter responses, it might not match a response containing be aware that it may not match a response containing a newline ('`\n`) character.

 To update an existing `selectionPattern` value using the AWS CLI, call the [update-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigateway/update-integration-response.html) operation to replace the `/selectionPattern` path value with the specified regex expression of the `Malformed*` pattern. 



To set the `selectionPattern` expression using the API Gateway console, enter the expression in the **Lambda error regex** text box when setting up or updating an integration response of a specified HTTP status code. 

## Handle custom Lambda errors in API Gateway
<a name="handle-custom-errors-in-lambda-integration"></a>

 Instead of the standard error described in the preceding section, AWS Lambda allows you to return a custom error object as JSON string. The error can be any valid JSON object. For example, the following JavaScript (Node.js) Lambda function returns a custom error: 

```
export const handler = (event, context, callback) => {
    ...
    // Error caught here:
    var myErrorObj = {
        errorType : "InternalServerError",
        httpStatus : 500,
        requestId : context.awsRequestId,
        trace : {
            "function": "abc()",
            "line": 123,
            "file": "abc.js"
        }
    }
    callback(JSON.stringify(myErrorObj));
};
```

 You must turn the `myErrorObj` object into a JSON string before calling `callback` to exit the function. Otherwise, the `myErrorObj` is returned as a string of `"[object Object]"`. When a method of your API is integrated with the preceding Lambda function, API Gateway receives an integration response with the following payload: 

```
{
    "errorMessage": "{\"errorType\":\"InternalServerError\",\"httpStatus\":500,\"requestId\":\"e5849002-39a0-11e7-a419-5bb5807c9fb2\",\"trace\":{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}}"
}
```

 As with any integration response, you can pass through this error response as-is to the method response. Or you can have a mapping template to transform the payload into a different format. For example, consider the following body-mapping template for a method response of `500` status code: 

```
{
    errorMessage: $input.path('$.errorMessage');
}
```

This template translates the integration response body that contains the custom error JSON string to the following method response body. This method response body contains the custom error JSON object: 

```
{
    "errorMessage" : {
        errorType : "InternalServerError",
        httpStatus : 500,
        requestId : context.awsRequestId,
        trace : {
            "function": "abc()",
            "line": 123,
            "file": "abc.js"
        }
    }
};
```

 Depending on your API requirements, you may need to pass some or all of the custom error properties as method response header parameters. You can achieve this by applying the custom error mappings from the integration response body to the method response headers. 

For example, the following OpenAPI extension defines a mapping from the `errorMessage.errorType`, `errorMessage.httpStatus`, `errorMessage.trace.function`, and `errorMessage.trace` properties to the `error_type`, `error_status`, `error_trace_function`, and `error_trace` headers, respectively. 

```
"x-amazon-apigateway-integration": {
    "responses": {
        "default": {
          "statusCode": "200",
          "responseParameters": {
            "method.response.header.error_trace_function": "integration.response.body.errorMessage.trace.function",
            "method.response.header.error_status": "integration.response.body.errorMessage.httpStatus",
            "method.response.header.error_type": "integration.response.body.errorMessage.errorType",
            "method.response.header.error_trace": "integration.response.body.errorMessage.trace"
          },
          ...
        }
    }
}
```

 At runtime, API Gateway deserializes the `integration.response.body` parameter when performing header mappings. However, this deserialization applies only to body-to-header mappings for Lambda custom error responses and does not apply to body-to-body mappings using `$input.body`. With these custom-error-body-to-header mappings, the client receives the following headers as part of the method response, provided that the `error_status`, `error_trace`, `error_trace_function`, and `error_type` headers are declared in the method request. 

```
"error_status":"500",
"error_trace":"{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}",
"error_trace_function":"abc()",
"error_type":"InternalServerError"
```

The `errorMessage.trace` property of the integration response body is a complex property. It is mapped to the `error_trace` header as a JSON string. 