

# Data transformations for REST APIs in API Gateway
<a name="rest-api-data-transformations"></a>

**Note**  
This section explains features that you use with a non-proxy integration. However, we recommend that when possible, you use a proxy integration for your REST API. A proxy integration has a streamlined integration setup and can evolve with the backend without having to tear down the existing setup. For more information, see [Choose an API Gateway API integration type](api-gateway-api-integration-types.md).

If you use a non-proxy integration, you can use two features of API Gateway to transform your method request and your integration response. You might transform your method request if it takes a different payload format than the integration request payload. You might transform your integration response if it returns a different payload format than the format you need to return in the method response. For more information about the request lifecycle, see [Example resource for a REST API](rest-api-develop.md#rest-api-develop-example).

The following example shows a data transformation where for the header `"x-version:beta"`, the `x-version` header parameter is transformed into the `app-version` header parameter. The data transformation from `x-version` to `app-version` occurs in the integration request. That way, the integration endpoint receives the transformed header parameter value. When the integration endpoint returns a status code, the status code is transformed from `200` to `204` before the method response.

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


To create a data transformation, you can use the following features:

**Parameter mapping**  
In parameter mapping, you can modify integration request URL path parameters, URL query string parameters, or HTTP header values, but you can't modify the integration request payload. You can also modify HTTP response header values. Use parameter mapping to create static header values for cross origin resource sharing (CORS).   
You can use parameter mapping in your integration request for proxy and non-proxy integrations, but to use parameter mapping for an integration response, you need a non-proxy integration. Parameter mapping doesn't require any scripting in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html). For more information, see [Parameter mapping for REST APIs in API Gateway](rest-api-parameter-mapping.md).

**Mapping template transformations**  
In mapping template transformations, you use a mapping template to map URL path parameters, URL query string parameters, HTTP headers, and the integration request or integration response body. A *mapping template* is a script expressed in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) using [JSONPath expressions](https://goessner.net/articles/JsonPath/) and applied to the payload based on the `Content-type` header.  
With a mapping template, you can do the following:  
+ Select which data to send using integration with AWS services, such as Amazon DynamoDB or Lambda functions, or HTTP endpoints. For more information, see [Tutorial: Modify the integration request and response for integrations to AWS services](set-up-data-transformations-in-api-gateway.md).
+ Conditionally override an API's integration request and integration response parameters, create new header values, and override status codes. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).
You can also specify the behavior of your API when an integration request body has `Content-type` header with no matching mapping templates. This is called integration passthrough behavior. For more information, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md). 

## Choose between parameter mapping and mapping template transformations
<a name="rest-api-data-transformations-choose"></a>

We recommend that you use parameter mapping to transform your data when possible. If your API requires you to change the body, or requires you to perform conditional overrides and modifications based on the incoming integration request or integration response, and you can't use a proxy integration, use mapping template transformations.

# Parameter mapping for REST APIs in API Gateway
<a name="rest-api-parameter-mapping"></a>

**Note**  
If you are using an HTTP API, see [Transform API requests and responses for HTTP APIs in API Gateway](http-api-parameter-mapping.md).

In parameter mapping, you map request or response parameters. You can map parameters using parameter mapping expressions or static values. For a list of mapping expressions, see [Parameter mapping source reference for REST APIs in API Gateway](rest-api-parameter-mapping-sources.md). You can use parameter mapping in your integration request for proxy and non-proxy integrations, but to use parameter mapping for an integration response, you need a non-proxy integration.

For example, you can map the method request header parameter `puppies` to the integration request header parameter `DogsAge0`. Then, if a client sends the header `puppies:true` to your API, the integration request sends the request header `DogsAge0:true` to the integration endpoint. The following diagram shows the request lifecycle of this example.

![\[Diagram of API Gateway parameter mapping example for a request\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/parameter-mapping-example1.png)


To create this example using API Gateway, see [Example 1: Map a method request parameter to an integration request parameter](request-response-data-mappings.md#request-response-data-mappings-example-1).

 As another example, you can also map the integration response header parameter `kittens` to the method response header parameter `CatsAge0`. Then, if the integration endpoint returns `kittens:false`, the client receives the header `CatsAge0:false`. The following diagram shows the request lifecycle of this example.

![\[Diagram of API Gateway parameter mapping example for a response\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/parameter-mapping-example2.png)


**Topics**
+ [

# Parameter mapping examples for REST APIs in API Gateway
](request-response-data-mappings.md)
+ [

# Parameter mapping source reference for REST APIs in API Gateway
](rest-api-parameter-mapping-sources.md)

# Parameter mapping examples for REST APIs in API Gateway
<a name="request-response-data-mappings"></a>

The following examples show how to create parameter mapping expressions using the API Gateway console, OpenAPI, and CloudFormation templates. For an example of how to use parameter mapping to create the required CORS headers, see [CORS for REST APIs in API Gateway](how-to-cors.md). 

## Example 1: Map a method request parameter to an integration request parameter
<a name="request-response-data-mappings-example-1"></a>

The following example maps the method request header parameter `puppies` to the integration request header parameter `DogsAge0`. 

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

**To map the method request parameter**

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

1. Choose a REST API.

1. Choose a method.

   Your method must have a non-proxy integration.

1. For **Method request settings**, choose **Edit**.

1. Choose **HTTP request headers**.

1. Choose **Add header**.

1. For **Name**, enter **puppies**.

1. Choose **Save**.

1. Choose the **Integration request** tab, and then for **Integration request settings**, choose **Edit**.

   The AWS Management Console automatically adds a parameter mapping from `method.request.header.puppies ` to `puppies` for you, but you need to change the **Name** to match the request header parameter that is expected by your integration endpoint.

1. For **Name**, enter **DogsAge0**.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

The following steps show you how to verify that your parameter mapping was successful.

**(Optional) Test your parameter mapping**

1. Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. For headers, enter **puppies:true**.

1. Choose **Test**.

1. In the **Logs**, the result should look like the following:

   ```
   Tue Feb 04 00:28:36 UTC 2025 : Method request headers: {puppies=true}
   Tue Feb 04 00:28:36 UTC 2025 : Method request body before transformations: 
   Tue Feb 04 00:28:36 UTC 2025 : Endpoint request URI: http://petstore-demo-endpoint.execute-api.com/petstore/pets
   Tue Feb 04 00:28:36 UTC 2025 : Endpoint request headers: {DogsAge0=true, x-amzn-apigateway-api-id=abcd1234, Accept=application/json, User-Agent=AmazonAPIGateway_aaaaaaa, X-Amzn-Trace-Id=Root=1-abcd-12344}
   ```

   The request header parameter has changed from `puppies` to `DogsAge0`.

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

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body:
        openapi: 3.0.1
        info:
          title: ParameterMappingExample
          version: "2025-02-04T00:30:41Z"
        paths:
          /pets:
            get:
              parameters:
                - name: puppies
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.DogsAge0: method.request.header.puppies
                passthroughBehavior: when_no_match
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "ParameterMappingExample",
    "version" : "2025-02-04T00:30:41Z"
  },
  "paths" : {
    "/pets" : {
      "get" : {
        "parameters" : [ {
          "name" : "puppies",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.DogsAge0" : "method.request.header.puppies"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  }
}
```

------

## Example 2: Map multiple method request parameters to different integration request parameters
<a name="request-response-data-mappings-example-2"></a>

The following example maps the multi-value method request query string parameter `methodRequestQueryParam` to the integration request query string parameter `integrationQueryParam` and maps the method request header parameter `methodRequestHeaderParam` to the integration request path parameter `integrationPathParam`.

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

**To map the method request parameters**

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

1. Choose a REST API.

1. Choose a method.

   Your method must have a non-proxy integration.

1. For **Method request settings**, choose **Edit**.

1. Choose **URL query string parameters**.

1. Choose **Add query string**.

1. For **Name**, enter **methodRequestQueryParam**.

1. Choose **HTTP request headers**.

1. Choose **Add header**.

1. For **Name**, enter **methodRequestHeaderParam**.

1. Choose **Save**.

1. Choose the **Integration request** tab, and then for **Integration request settings**, choose **Edit**.

1. Choose **URL path parameters**.

1. Choose **Add path parameter**.

1. For **Name**, enter **integrationPathParam**.

1. For **Mapped from**, enter **method.request.header.methodRequestHeaderParam**.

   This maps the method request header you specified in the method request to a new integration request path parameter.

1. Choose **URL query string parameters**.

1. Choose **Add query string**.

1. For **Name**, enter **integrationQueryParam**.

1. For **Mapped from**, enter **method.request.multivaluequerystring.methodRequestQueryParam**.

   This maps the multivalue query string parameter to a new single valued integration request query string parameter.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

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

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

The following OpenAPI definition creates the following parameter mappings for an HTTP integration:
+ The method request's header, named `methodRequestHeaderParam`, into the integration request path parameter, named `integrationPathParam`
+ The multi-value method request query string, named `methodRequestQueryParam`, into the integration request query string, named `integrationQueryParam`

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: Parameter mapping example 2
          version: "2025-01-15T19:12:31Z"
        paths:
          /:
            post:
              parameters:
                - name: methodRequestQueryParam
                  in: query
                  schema:
                    type: string
                - name: methodRequestHeaderParam
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.querystring.integrationQueryParam: method.request.multivaluequerystring.methodRequestQueryParam
                  integration.request.path.integrationPathParam: method.request.header.methodRequestHeaderParam
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

The following OpenAPI definition creates the following parameter mappings for an HTTP integration:
+ The method request's header, named `methodRequestHeaderParam`, into the integration request path parameter, named `integrationPathParam`
+ The multi-value method request query string, named `methodRequestQueryParam`, into the integration request query string, named `integrationQueryParam`

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example 2",
    "version" : "2025-01-15T19:12:31Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "parameters" : [ {
          "name" : "methodRequestQueryParam",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "methodRequestHeaderParam",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.querystring.integrationQueryParam" : "method.request.multivaluequerystring.methodRequestQueryParam",
            "integration.request.path.integrationPathParam" : "method.request.header.methodRequestHeaderParam"
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000,
          "type" : "http"
        }
      }
    }
  }
}
```

------

## Example 3: Map fields from the JSON request body to integration request parameters
<a name="request-response-data-mappings-example-3"></a>

You can also map integration request parameters from fields in the JSON request body using a [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2). The following example maps the method request body to an integration request header named `body-header` and maps part of the request body, as expressed by a JSON expression to an integration request header named `pet-price`.

To test this example, provide an input that contains a price category, such as the following:

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

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

**To map the method request parameters**

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

1. Choose a REST API.

1. Choose a `POST`, `PUT`, `PATCH`, or `ANY` method.

   Your method must have a non-proxy integration.

1. For **Integration request settings**, choose **Edit**.

1. Choose **URL request headers parameters**.

1. Choose **Add request header parameter**.

1. For **Name**, enter **body-header**.

1. For **Mapped from**, enter **method.request.body**.

   This maps the method request body to a new integration request header parameter.

1. Choose **Add request header parameter**.

1. For **Name**, enter **pet-price**.

1. For **Mapped from**, enter ** method.request.body[0].price**.

   This maps a part of the method request body to a new integration request header parameter.

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

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

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: Parameter mapping example 3
          version: "2025-01-15T19:19:14Z"
        paths:
          /:
            post:
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.pet-price: method.request.body[0].price
                  integration.request.header.body-header: method.request.body
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
                type: http
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

The following OpenAPI definition map integration request parameters from fields in the JSON request body.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example 3",
    "version" : "2025-01-15T19:19:14Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.pet-price" : "method.request.body[0].price",
            "integration.request.header.body-header" : "method.request.body"
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000,
          "type" : "http"
        }
      }
    }
  }
}
```

------

## Example 4: Map the integration response to the method response
<a name="request-response-data-mappings-example-4"></a>

You can also map the integration response to the method response. The following example maps the integration response body to a method response header named `location`, maps the integration response header `x-app-id` to the method response header `id`, and maps the multi-valued integration response header `item` to the method response header `items`.

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

**To map the integration response**

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

1. Choose a REST API.

1. Choose a method.

   Your method must have a non-proxy integration.

1. Choose the **Method response** tab, and then for **Response 200**, choose **Edit**.

1. For **Header name**, choose **Add header**.

1. Create three headers named **id**, **item**, and **location**.

1. Choose **Save**.

1. Choose the **Integration response** tab, and then for **Default - Response**, choose **Edit**.

1. Under **Header mappings**, enter the following.

   1. For **id**, enter **integration.response.header.x-app-id**

   1. For **item**, enter **integration.response.multivalueheader.item**

   1. For **location**, enter **integration.response.body.redirect.url**

1. Choose **Save**.

1. Redeploy your API for the changes to take effect.

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

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body:
        openapi: 3.0.1
        info:
          title: Parameter mapping example
          version: "2025-01-15T19:21:35Z"
        paths:
          /:
            post:
              responses:
                "200":
                  description: 200 response
                  headers:
                    item:
                      schema:
                        type: string
                    location:
                      schema:
                        type: string
                    id:
                      schema:
                        type: string
              x-amazon-apigateway-integration:
                type: http
                httpMethod: GET
                uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                    responseParameters:
                      method.response.header.id: integration.response.header.x-app-id
                      method.response.header.location: integration.response.body.redirect.url
                      method.response.header.item: integration.response.multivalueheader.item
                requestTemplates:
                  application/json: '{"statusCode": 200}'
                passthroughBehavior: when_no_templates
                timeoutInMillis: 29000
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

The following OpenAPI definition maps the integration response to the method response.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "Parameter mapping example",
    "version" : "2025-01-15T19:21:35Z"
  },
  "paths" : {
    "/" : {
      "post" : {
        "responses" : {
          "200" : {
            "description" : "200 response",
            "headers" : {
              "item" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "location" : {
                "schema" : {
                  "type" : "string"
                }
              },
              "id" : {
                "schema" : {
                  "type" : "string"
                }
              }
            }
          }
        },
        "x-amazon-apigateway-integration" : {
          "type" : "http",
          "httpMethod" : "GET",
          "uri" : "http://petstore-demo-endpoint.execute-api.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseParameters" : {
                "method.response.header.id" : "integration.response.header.x-app-id",
                "method.response.header.location" : "integration.response.body.redirect.url",
                "method.response.header.item" : "integration.response.multivalueheader.item"
              }
            }
          },
          "requestTemplates" : {
            "application/json" : "{\"statusCode\": 200}"
          },
          "passthroughBehavior" : "when_no_templates",
          "timeoutInMillis" : 29000
        }
      }
    }
  }
}
```

------

# Parameter mapping source reference for REST APIs in API Gateway
<a name="rest-api-parameter-mapping-sources"></a>

When you create a parameter mapping, you specify the method request or integration response parameters to modify and you specify how to modify those parameters.

The following table shows the method request parameters that you can map, and the expression to create the mapping. In these expressions, *name* is the name of a method request parameter. For example, to map the request header parameter `puppies`, use the expression `method.request.header.puppies`. Your expression must match the regular expression `'^[a-zA-Z0-9._$-]+$]'`. You can use parameter mapping in your integration request for proxy and non-proxy integrations. 


| **Mapped data source** | **Mapping expression** | 
| --- | --- | 
| Method request path | method.request.path.name | 
| Method request query string | method.request.querystring.name | 
| Multi-value method request query string | method.request.multivaluequerystring.name | 
| Method request header | method.request.header.name | 
| Multi-value method request header | method.request.multivalueheader.name | 
| Method request body | method.request.body | 
| Method request body (JsonPath) | `method.request.body.JSONPath_EXPRESSION`. *JSONPath\$1EXPRESSION* is a JSONPath expression for a JSON field of the body of a request. For more information, see [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2).  | 
| Stage variables | stageVariables.name | 
| Context variables |  `context.name` The name must be one of the [supported context variables](api-gateway-mapping-template-reference.md#context-variable-reference). | 
| Static value | `'static_value'`. The *static\$1value* is a string literal and must be enclosed within a pair of single quotes. For example, `'https://www.example.com'`. | 

The following table shows the integration response parameters that you can map and the expression to create the mapping. In these expressions, *name* is the name of an integration response parameter. You can map method response headers from any integration response header or integration response body, \$1context variables, or static values. To use parameter mapping for an integration response, you need a non-proxy integration.


| Mapped data source | Mapping expression | 
| --- | --- | 
| Integration response header | integration.response.header.name | 
| Integration response header | integration.response.multivalueheader.name | 
| Integration response body | integration.response.body | 
| Integration response body (JsonPath) | `integration.response.body.JSONPath_EXPRESSION` *JSONPath\$1EXPRESSION* is a JSONPath expression for a JSON field of the body of a response. For more information, see [JSONPath expression](http://goessner.net/articles/JsonPath/index.html#e2). | 
| Stage variable | stageVariables.name | 
| Context variable |  `context.name` The name must be one of the [supported context variables](api-gateway-mapping-template-reference.md#context-variable-reference). | 
| Static value | ` 'static_value'` The *static\$1value* is a string literal and must be enclosed within a pair of single quotes. For example, `'https://www.example.com'`. | 

# Mapping template transformations for REST APIs in API Gateway
<a name="models-mappings"></a>

A mapping template transformation uses a mapping template to modify your integration request or integration response. A *mapping template* is a script expressed in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) and applied to a payload using [JSONPath ](https://goessner.net/articles/JsonPath/) based on the `Content-type` header. You use mapping templates when you use mapping template transformations. This section describes conceptual information related to mapping templates.

The following diagram shows the request lifecycle for a `POST /pets` resource that has an integration with a PetStore integration endpoint. In this API, a user sends data about a pet and the integration endpoint returns the adoption fee associated with a pet. In this request lifecycle, mapping template transformations filter the request body to the integration endpoint and filter the response body from the integration endpoint.

![\[Example request lifecycle\]](http://docs.aws.amazon.com/apigateway/latest/developerguide/images/mapping-template-transforms.png)


The following sections explain the request and response lifecycle.

## Method request and integration request
<a name="models-mappings-request"></a>

In the previous example, if this is the request body sent to the method request:

```
POST /pets
    HTTP/1.1
    Host:abcd1234.us-west-2.amazonaws.com
    Content-type: application/json
    
  {
    "id": 1,
    "type": "dog",
    "Age": 11,
  }
```

This request body is not in the correct format to be used by the integration endpoint, so API Gateway performs a mapping template transformation. API Gateway only performs a mapping template transformation because there is a mapping template defined for the Content-Type `application/json`. If you don't define a mapping template for the Content-Type, by default, API Gateway passes the body through the integration request to the integration endpoint. To modify this behavior, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md).

The following mapping template transforms the method request data in the integration request before it's sent to the integration endpoint:

```
#set($inputRoot = $input.path('$'))
  {
    "dogId" : "dog_"$elem.id,
    "Age": $inputRoot.Age
  }
```

1. The `$inputRoot` variable represents the root object in the original JSON data from the previous section. Directives begin with the `#` symbol.

1. The `dog` is a concatenation of the user's `id` and a string value.

1. `Age` is from the method request body.

Then, the following output is forwarded to the integration endpoint:

```
{
    "dogId" : "dog_1",
    "Age": 11
  }
```

## Integration response and method response
<a name="models-mappings-response"></a>

After the successful request to the integration endpoint, the endpoint sends a response to API Gateway's integration response. The following is the example output data from the integration endpoint:

```
{
    "dogId" : "dog_1",
    "adoptionFee": 19.95,
}
```

The method response expects a different payload than what is returned by the integration response. API Gateway performs a mapping template transformation. API Gateway only performs a mapping template transformation because there is a mapping template defined for the Content-Type `application/json`. If you don't define a mapping template for the Content-Type, by default, API Gateway passes the body through the integration response to the method response. To modify this behavior, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md).

```
#set($inputRoot = $input.path('$'))
  {
    "adoptionFee" : $inputRoot.adoptionFee,
  }
```

The following output is sent to the method response:

```
{"adoptionFee": 19.95}
```

This completes the example mapping template transformation. We recommend that when possible, instead of using mapping template transformations, you use a proxy integration to transform your data. For more information, see [Choose an API Gateway API integration type](api-gateway-api-integration-types.md).

# Method request behavior for payloads without mapping templates for REST APIs in API Gateway
<a name="integration-passthrough-behaviors"></a>

If your method request has a payload and you don't have a mapping template defined for the `Content-Type` header, you can choose to pass the client-supplied request payload through the integration request to the backend without transformation. The process is known as integration passthrough. 

 The actual passthrough behavior of an incoming request is determined by this setting. There are three options: 

**When no template matches the request Content-Type header**  
Choose this option if you want the method request body to pass through the integration request to the backend without transformation when the method request content type does not match any content types associated with the mapping templates.  
When calling the API Gateway API, you choose this option by setting `WHEN_NO_MATCH` as the `passthroughBehavior` property value on the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html).

**When there are no templates defined (recommended)**  
Choose this option if you want the method request body to pass through the integration request to the backend without transformation when no mapping template is defined in the integration request. If a template is defined when this option is selected, the method request with a payload and content type that doesn't match any defined mapping template will be rejected with an HTTP 415 Unsupported Media Type response.  
When calling the API Gateway API, you choose this option by setting `WHEN_NO_TEMPLATES` as the `passthroughBehavior` property value on the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html).

**Never**  
Choose this option if you do not want the method request body to pass through the integration request to the backend without transformation when no mapping template is defined in the integration request. If a template is defined when this option is selected, the method request of an unmapped content type will be rejected with an HTTP 415 Unsupported Media Type response.   
When calling the API Gateway API, you choose this option by setting `NEVER` as the `passthroughBehavior` property value on the [Integration](https://docs.aws.amazon.com/apigateway/latest/api/API_Integration.html).

 The following examples show the possible passthrough behaviors. 

Example 1: One mapping template is defined in the integration request for the `application/json` content type.


| Content-type | Passthrough option | Behavior | 
| --- | --- | --- | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1MATCH | The request payload is transformed using the template. | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1TEMPLATES | The request payload is transformed using the template. | 
| None API Gateway defaults to `application/json` | NEVER | The request payload is transformed using the template. | 
| application/json | WHEN\$1NO\$1MATCH | The request payload is transformed using the template. | 
| application/json | WHEN\$1NO\$1TEMPLATES | The request payload is transformed using the template. | 
| application/json | NEVER | The request payload is transformed using the template. | 
| application/xml | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/xml | WHEN\$1NO\$1TEMPLATES | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/xml | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 

Example 2: One mapping template is defined in the integration request for the `application/xml` content type.


| Content-type | Passthrough option | Behavior | 
| --- | --- | --- | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1TEMPLATES | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| None API Gateway defaults to `application/json` | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/json | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/json | WHEN\$1NO\$1TEMPLATES | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/json | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/xml | WHEN\$1NO\$1MATCH | The request payload is transformed using the template. | 
| application/xml | WHEN\$1NO\$1TEMPLATES | The request payload is transformed using the template. | 
| application/xml | NEVER | The request payload is transformed using the template. | 

Example 3: No mapping templates are defined in the integration request.


| Content-type | Passthrough option | Behavior | 
| --- | --- | --- | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| None API Gateway defaults to `application/json` | WHEN\$1NO\$1TEMPLATES | The request payload is not transformed and is sent to the backend as-is. | 
| None API Gateway defaults to `application/json` | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/json | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/json | WHEN\$1NO\$1TEMPLATES | The request payload is not transformed and is sent to the backend as-is. | 
| application/json | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 
| application/xml | WHEN\$1NO\$1MATCH | The request payload is not transformed and is sent to the backend as-is. | 
| application/xml | WHEN\$1NO\$1TEMPLATES | The request payload is not transformed and is sent to the backend as-is. | 
| application/xml | NEVER | The request is rejected with an HTTP 415 Unsupported Media Type response. | 

# Additional mapping template example for REST APIs in API Gateway
<a name="example-photos"></a>

The following example shows a photo album API in API Gateway that uses mapping templates to transform integration request and integration response data. It also uses data models to define method request and integration response payloads. For more information about data models, see [Data models for REST APIs](models-mappings-models.md).

## Method request and integration request
<a name="example-photos-request"></a>

The following is a model that defines the method request body. This input model requires that the caller upload one photo page, and requires a minimum of 10 photos for each page. You can use this input model to generate an SDK or to use request validation for your API. While using request validation, if the method request body doesn't adhere to the data structure of the model, API Gateway fails the request. 

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosInputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "object",
      "required" : [
      "photo"
      ],
      "properties": {
        "page": { "type": "integer" },
        "pages": { "type": "string" },
        "perpage": { "type": "integer", "minimum" : 10 },
        "total": { "type": "string" },
        "photo": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "owner": { "type": "string" },
              "photographer_first_name" : {"type" : "string"},
              "photographer_last_name" : {"type" : "string"},
              "secret": { "type": "string" },
              "server": { "type": "string" },
              "farm": { "type": "integer" },
              "title": { "type": "string" },
              "ispublic": { "type": "boolean" },
              "isfriend": { "type": "boolean" },
              "isfamily": { "type": "boolean" }
            }
          }
        }
      }
    }
  }
}
```

The following is an example method request body that adheres to the data structure of the previous data model.

```
{
  "photos": {
    "page": 1,
    "pages": "1234",
    "perpage": 100,
    "total": "123398",
    "photo": [
      {
        "id": "12345678901",
        "owner": "23456789@A12",
        "photographer_first_name" : "Saanvi",
        "photographer_last_name" : "Sarkar",
        "secret": "abc123d456",
        "server": "1234",
        "farm": 1,
        "title": "Sample photo 1",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      },
      {
        "id": "23456789012",
        "owner": "34567890@B23",
        "photographer_first_name" : "Richard",
        "photographer_last_name" : "Roe",
        "secret": "bcd234e567",
        "server": "2345",
        "farm": 2,
        "title": "Sample photo 2",
        "ispublic": true,
        "isfriend": false,
        "isfamily": false
      }
    ]
  }
}
```

In this example, if the previous method request body was submitted by the client, then this mapping template transforms the payload to match the format required by the integration endpoint.

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.ispublic,
      "isfriend": $elem.isfriend,
      "isfamily": $elem.isfamily
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

The following example is output data from the transformation:

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

This data is sent to the integration request, and then to the integration endpoint.

## Integration response and method response
<a name="photos-example-response"></a>

The following is an example output model for the photo data from the integration endpoint. You can use this model for a method response model, which is necessary when you generate a strongly typed SDK for the API. This causes the output to be cast into an appropriate class in Java or Objective-C.

```
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "PhotosOutputModel",
  "type": "object",
  "properties": {
    "photos": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "photographedBy": { "type": "string" },
          "title": { "type": "string" },
          "ispublic": { "type": "boolean" },
          "isfriend": { "type": "boolean" },
          "isfamily": { "type": "boolean" }
        }
      }
    }
  }
}
```

The integration endpoint might not respond with a response that adheres to the data structure of this model. For instance, the integration response might look like the following:

```
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "description": "My sample photo 1",
      "public": true,
      "friend": false,
      "family": false
    }		
  ]
}
```

The following example mapping template transforms the integration response data into the format expected by the method response:

```
#set($inputRoot = $input.path('$'))
{
  "photos": [
#foreach($elem in $inputRoot.photos.photo)
    {
      "id": "$elem.id",
      "photographedBy": "$elem.photographer_first_name $elem.photographer_last_name",
      "title": "$elem.title",
      "ispublic": $elem.public,
      "isfriend": $elem.friend,
      "isfamily": $elem.family
    }#if($foreach.hasNext),#end
		
#end
  ]
}
```

The following example is output data from the transformation:

```
{
  "photos": [
    {
      "id": "12345678901",
      "photographedBy": "Saanvi Sarkar",
      "title": "Sample photo 1",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    },		
    {
      "id": "23456789012",
      "photographedBy": "Richard Roe",
      "title": "Sample photo 2",
      "ispublic": true,
      "isfriend": false,
      "isfamily": false
    }		
  ]
}
```

This data is sent to the method response and then back to the client.

# Override your API's request and response parameters and status codes for REST APIs in API Gateway
<a name="apigateway-override-request-response-parameters"></a>

You can use mapping template transformations to override any type of request parameter, response header, or response status code. You use a mapping template to do the following:
+ Perform many-to-one parameter mappings
+ Override parameters after standard API Gateway mappings have been applied
+ Conditionally map parameters based on body content or other parameter values
+ Programmatically create new parameters
+ Override status codes returned by your integration endpoint

Overrides are final. An override may only be applied to each parameter once. If you try to override the same parameter multiple times, API Gateway returns a `5XX` response. If you must override the same parameter multiple times throughout the template, we recommend creating a variable and applying the override at the end of the template. The template is applied only after the entire template is parsed.

## Example 1: Override the status code based on the integration body
<a name="apigateway-override-request-response-examples"></a>

The following example use the [example API](api-gateway-create-api-from-example.md) to override the status code based on the integration response body.

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

**To override a status code based on the integration response body**

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

1. Choose **Create API**.

1. For **REST API**, choose **Build**.

1. For **API details**, choose **Example API**.

1. Choose **Create API**.

   API Gateway creates an example pet store API. To retrieve information about a pet, you use the API method request of `GET /pets/{petId}`, where `{petId}` is a path parameter corresponding to an ID number for a pet.

   In this example, you override the `GET` method's response code to `400` when an error condition is detected.

1. In the **Resources** tree, choose the `GET` method under `/{petId}`.

1. First, you test the current implementation of the API. 

   Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. For **petId**, enter **-1**, and then choose **Test**.

   The **Response body** indicates an out-of-range error:

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   In addition, the last line under **Logs** ends with: `Method completed with status: 200`.

   The integration was completed successfully, but there was an error. Now you'll override the status code based on the integration response.

1. On the **Integration response** tab, for the **Default - Response**, choose **Edit**.

1. Choose **Mapping templates**.

1. Choose **Add mapping template**.

1. For **Content type**, enter **application/json**.

1. For **Template body**, enter the following:

   ```
   #set($inputRoot = $input.path('$'))
   $input.json("$")
   #if($inputRoot.toString().contains("error"))
   #set($context.responseOverride.status = 400)
   #end
   ```

   This mapping template uses the `$context.responseOverride.status` variable to override the status code to `400` if the integration response contains the string `error`.

1. Choose **Save**.

1. Choose the **Test** tab.

1. For **petId**, enter **-1**.

1. In the results, the **Response Body** indicates an out-of-range error:

   ```
   {
     "errors": [
       {
         "key": "GetPetRequest.petId",
         "message": "The value is out of range."
       }
     ]
   }
   ```

   However, the last line under **Logs** now ends with: `Method completed with status: 400`.

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

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 1
          description: Example pet store API.
          version: "2025-01-14T00:13:18Z"
        paths:
          /pets/{petId}:
            get:
              parameters:
                - name: petId
                  in: path
                  required: true
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}
                responses:
                  default:
                    statusCode: "200"
                    responseTemplates:
                      application/json: |-
                        #set($inputRoot = $input.path('$'))
                        $input.json("$")
                        #if($inputRoot.toString().contains("error"))
                        #set($context.responseOverride.status = 400)
                        #end
                requestParameters:
                  integration.request.path.petId: method.request.path.petId
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

The following OpenAPI definition creates the `GET pets/{petId}` resource and overrides the status code based on the integration body.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 1",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:13:18Z"
  },
  "paths" : {
    "/pets/{petId}" : {
      "get" : {
        "parameters" : [ {
          "name" : "petId",
          "in" : "path",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets/{petId}",
          "responses" : {
            "default" : {
              "statusCode" : "200",
              "responseTemplates" : {
                "application/json" : "#set($inputRoot = $input.path('$'))\n$input.json(\"$\")\n#if($inputRoot.toString().contains(\"error\"))\n#set($context.responseOverride.status = 400)\n#end"
              }
            }
          },
          "requestParameters" : {
            "integration.request.path.petId" : "method.request.path.petId"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  },
  "components" : {
    "schemas" : {
      "Pet" : {
        "type" : "object",
        "properties" : {
          "id" : {
            "type" : "integer"
          },
          "type" : {
            "type" : "string"
          },
          "price" : {
            "type" : "number"
          }
        }
      }
    }
  }
}
```

------

## Example 2: Override the request header and create new headers
<a name="apigateway-override-request-response-examples-2"></a>

The following example uses the [example API](api-gateway-create-api-from-example.md) to override the request header and create new headers.

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

**To override a method's request header by creating a new header**

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

1. Choose the example API you created in the previous tutorial. The name of the API should be **PetStore**.

1. In the **Resources** tree, choose the `GET` method under `/pet`.

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

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

1. For **Name**, enter **header1**.

1. Choose **Add header**, and then create a second header called **header2**.

1. Choose **Save**.

   Now, you combine these headers into one header value using a mapping template.

1. On the **Integration request** tab, for **Integration request settings**, choose **Edit**.

1. For **Request body passthrough**, select **When there are no templates defined (recommended)**.

1. Choose **Mapping templates**, and then do the following:

   1. Choose **Add mapping template**.

   1. For **Content type**, enter **application/json**. 

   1. For **Template body**, enter the following:

      ```
      #set($header1Override = "pets")
      #set($header3Value = "$input.params('header1')$input.params('header2')")
      $input.json("$")
      #set($context.requestOverride.header.header3 = $header3Value)
      #set($context.requestOverride.header.header1 = $header1Override)
      #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
      ```

      This mapping template overrides `header1` with the string `pets` and creates a multi-value header called `$header3Value` that combines `header1` and `header2`.

1. Choose **Save**.

1. Choose the **Test** tab.

1. Under **Headers**, copy the following code:

   ```
   header1:header1Val
   header2:header2Val
   ```

1. Choose **Test**.

   In the **Logs**, you should see an entry that includes this text:

   ```
   Endpoint request headers: {header3=header1Valheader2Val, 
   header2=header2Val, header1=pets, x-amzn-apigateway-api-id=api-id,
   Accept=application/json, multivalueheader=pets,header1Valheader2Val}
   ```

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

 In this example, you use the [body](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html#cfn-apigateway-restapi-body) property to import an OpenAPI definition file into API Gateway. 

```
AWSTemplateFormatVersion: 2010-09-09
Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Body: 
        openapi: 3.0.1
        info:
          title: PetStore Example 2
          description: Example pet store API.
          version: "2025-01-14T00:36:18Z"
        paths:
          /pets:
            get:
              parameters:
                - name: header2
                  in: header
                  schema:
                    type: string
                - name: page
                  in: query
                  schema:
                    type: string
                - name: type
                  in: query
                  schema:
                    type: string
                - name: header1
                  in: header
                  schema:
                    type: string
              responses:
                "200":
                  description: 200 response
              x-amazon-apigateway-integration:
                httpMethod: GET
                uri: http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets
                responses:
                  default:
                    statusCode: "200"
                requestParameters:
                  integration.request.header.header1: method.request.header.header1
                  integration.request.header.header2: method.request.header.header2
                  integration.request.querystring.page: method.request.querystring.page
                  integration.request.querystring.type: method.request.querystring.type
                requestTemplates:
                  application/json: |-
                    #set($header1Override = "pets")
                    #set($header3Value = "$input.params('header1')$input.params('header2')")
                    $input.json("$")
                    #set($context.requestOverride.header.header3 = $header3Value)
                    #set($context.requestOverride.header.header1 = $header1Override)
                    #set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])
                passthroughBehavior: when_no_match
                type: http
        components:
          schemas:
            Pet:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                price:
                  type: number
  ApiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  ApiGatewayDeployment20250219:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn: Api 
    Properties: 
      RestApiId: !Ref Api
  Stage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
       DeploymentId: !Ref ApiGatewayDeployment20250219
       RestApiId: !Ref Api
       StageName: prod
```

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

 The following OpenAPI definition creates the `GET pets` resource and overrides the request header and create new headers.

```
{
  "openapi" : "3.0.1",
  "info" : {
    "title" : "PetStore Example 2",
    "description" : "Example pet store API.",
    "version" : "2025-01-14T00:36:18Z"
  },
  "paths" : {
    "/pets" : {
      "get" : {
        "parameters" : [ {
          "name" : "header2",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "page",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "type",
          "in" : "query",
          "schema" : {
            "type" : "string"
          }
        }, {
          "name" : "header1",
          "in" : "header",
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "description" : "200 response"
          }
        },
        "x-amazon-apigateway-integration" : {
          "httpMethod" : "GET",
          "uri" : "http://petstore.execute-api.us-east-1.amazonaws.com/petstore/pets",
          "responses" : {
            "default" : {
              "statusCode" : "200"
            }
          },
          "requestParameters" : {
            "integration.request.header.header1" : "method.request.header.header1",
            "integration.request.header.header2" : "method.request.header.header2",
            "integration.request.querystring.page" : "method.request.querystring.page",
            "integration.request.querystring.type" : "method.request.querystring.type"
          },
          "requestTemplates" : {
            "application/json" : "#set($header1Override = \"pets\")\n#set($header3Value = \"$input.params('header1')$input.params('header2')\")\n$input.json(\"$\")\n#set($context.requestOverride.header.header3 = $header3Value)\n#set($context.requestOverride.header.header1 = $header1Override)\n#set($context.requestOverride.header.multivalueheader=[$header1Override, $header3Value])"
          },
          "passthroughBehavior" : "when_no_match",
          "type" : "http"
        }
      }
    }
  }
}
```

------

To use a mapping template override, add one or more of the following `$context` variables. For a list of `$context` variables, see [Context variables for data transformations](api-gateway-mapping-template-reference.md#context-variable-reference).

# Tutorial: Modify the integration request and response for integrations to AWS services
<a name="set-up-data-transformations-in-api-gateway"></a>

The following tutorial shows how to use mapping template transformations to set up mapping templates to transform integration requests and responses using the console and AWS CLI.

**Topics**
+ [

## Set up data transformation using the API Gateway console
](#mapping-example-console)
+ [

## Set up data transformation using the AWS CLI
](#mapping-example-cli)
+ [

## Completed data transformation CloudFormation template
](#api-gateway-data-transformations-full-cfn-stack)

## Set up data transformation using the API Gateway console
<a name="mapping-example-console"></a>

In this tutorial, you will create an incomplete API and DynamoDB table using the following .zip file [data-transformation-tutorial-console.zip](samples/data-transformation-tutorial-console.zip). This incomplete API has a `/pets` resource with `GET` and `POST` methods. 
+ The `GET` method will get data from the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. The output data will be transformed according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).
+ The `POST` method will allow the user to `POST` pet information to a Amazon DynamoDB table using a mapping template.

Download and unzip [the app creation template for CloudFormation](samples/data-transformation-tutorial-console.zip). You'll use this template to create a DynamoDB table to post pet information and an incomplete API. You will finish the rest of the steps in the API Gateway console. 

**To create an CloudFormation stack**

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

1. Choose **Create stack** and then choose **With new resources (standard)**.

1. For **Specify template**, choose **Upload a template file**.

1. Select the template that you downloaded.

1. Choose **Next**. 

1. For **Stack name**, enter **data-transformation-tutorial-console** and then choose **Next**.

1. For **Configure stack options**, choose **Next**.

1. For **Capabilities**, acknowledge that CloudFormation can create IAM resources in your account.

1. Choose **Next**, and then choose **Submit**.

CloudFormation provisions the resources specified in the template. It can take a few minutes to finish provisioning your resources. When the status of your CloudFormation stack is **CREATE\$1COMPLETE**, you're ready to move on to the next step.

**To test the `GET` integration response**

1. On the **Resources** tab of the CloudFormation stack for **data-transformation-tutorial-console**, select the physical ID of your API.

1. In the main navigation pane, choose **Resources**, and then select the **GET** method. 

1. Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

   The output of the test will show the following: 

   ```
   [
     {
       "id": 1,
       "type": "dog",
       "price": 249.99
     },
     {
       "id": 2,
       "type": "cat",
       "price": 124.99
     },
     {
       "id": 3,
       "type": "fish",
       "price": 0.99
     }
   ]
   ```

   You will transform this output according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).

**To transform the `GET` integration response**

1. Choose the **Integration response** tab.

   Currently, there are no mapping templates defined, so the integration response will not be transformed. 

1. For **Default - Response**, choose **Edit**.

1. Choose **Mapping templates**, and then do the following:

   1. Choose **Add mapping template**.

   1. For **Content type**, enter **application/json**. 

   1. For **Template body**, enter the following:

      ```
      #set($inputRoot = $input.path('$'))
      [
      #foreach($elem in $inputRoot)
        {
          "description" : "Item $elem.id is a $elem.type.",
          "askingPrice" : $elem.price
        }#if($foreach.hasNext),#end
      
      #end
      ]
      ```

   Choose **Save**.

**To test the `GET` integration response**
+ Choose the **Test** tab, and then choose **Test**.

  The output of the test will show the transformed response. 

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**To transform input data from the `POST` method**

1. Choose the **POST** method.

1. Choose the **Integration request** tab, and then for **Integration request settings**, choose **Edit**.

   The CloudFormation template has populated some of the integration request fields. 
   +  The integration type is AWS service. 
   +  The AWS service is DynamoDB. 
   +  The HTTP method is `POST`. 
   +  The Action is `PutItem`. 
   +  The Execution role allowing API Gateway to put an item into the DynamoDB table is `data-transformation-tutorial-console-APIGatewayRole`. CloudFormation created this role to allow API Gateway to have the minimal permissions for interacting with DynamoDB. 

    The name of the DynamoDB table has not been specified. You will specify the name in the following steps. 

1. For **Request body passthrough**, select **Never**.

   This means that the API will reject data with Content-Types that do not have a mapping template.

1. Choose **Mapping templates**.

1. The **Content type** is set to `application/json`. This means a content types that are not application/json will be rejected by the API. For more information about the integration passthrough behaviors, see [Method request behavior for payloads without mapping templates for REST APIs in API Gateway](integration-passthrough-behaviors.md)

1. Enter the following code into the text editor.

   ```
   {
       "TableName":"data-transformation-tutorial-console-ddb",
       "Item": {
           "id": {
               "N": $input.json("$.id")
           },
           "type": {
               "S": $input.json("$.type")
           },
           "price": {
               "N": $input.json("$.price")
           }
       }
   }
   ```

    This template specifies the table as `data-transformation-tutorial-console-ddb` and sets the items as `id`, `type`, and `price`. The items will come from the body of the `POST` method. You also can use a data model to help create a mapping template. For more information, see [Request validation for REST APIs in API Gateway](api-gateway-method-request-validation.md). 

1. Choose **Save** to save your mapping template. 

**To add a method and integration response from the `POST` method**

The CloudFormation created a blank method and integration response. You will edit this response to provide more information. For more information about how to edit responses, see [Parameter mapping examples for REST APIs in API Gateway](request-response-data-mappings.md).

1. On the **Integration response** tab, for **Default - Response**, choose **Edit**.

1. Choose **Mapping templates**, and then choose **Add mapping template**.

1. For **Content-type**, enter **application/json**.

1. In the code editor, enter the following output mapping template to send an output message:

   ```
   { "message" : "Your response was recorded at $context.requestTime" }
   ```

   For more information about context variables, see [Context variables for data transformations](api-gateway-mapping-template-reference.md#context-variable-reference).

1. Choose **Save** to save your mapping template. 

**Test the `POST` method**

Choose the **Test** tab. You might need to choose the right arrow button to show the tab.

1. In the request body, enter the following example.

   ```
   {
             "id": "4",
             "type" : "dog",
             "price": "321"
   }
   ```

1. Choose **Test**.

   The output should show your success message.

    You can open the DynamoDB console at [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/) to verify that the example item is in your table. 

**To delete an CloudFormation stack**

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

1. Select your CloudFormation stack.

1. Choose **Delete** and then confirm your choice.

## Set up data transformation using the AWS CLI
<a name="mapping-example-cli"></a>

In this tutorial, you will create an incomplete API and DynamoDB table using the following .zip file [data-transformation-tutorial-cli.zip](samples/data-transformation-tutorial-cli.zip). This incomplete API has a `/pets` resource with a `GET` method integrated with the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. You will create a `POST` method to connect to a DynamoDB table and use mapping templates to input data into a DynamoDB table. 
+ You will transform the output data according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).
+ You will create a `POST` method to allow the user to `POST` pet information to a Amazon DynamoDB table using a mapping template.

**To create an CloudFormation stack**

Download and unzip [the app creation template for CloudFormation](samples/data-transformation-tutorial-cli.zip). 

To complete the following tutorial, you need the [AWS Command Line Interface (AWS CLI) version 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html). 

For long commands, an escape character (`\`) is used to split a command over multiple lines.
**Note**  
In Windows, some Bash CLI commands that you commonly use (such as `zip`) are not supported by the operating system's built-in terminals. To get a Windows-integrated version of Ubuntu and Bash, [install the Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install). Example CLI commands in this guide use Linux formatting. Commands which include inline JSON documents must be reformatted if you are using the Windows CLI. 

1.  Use the following command to create the CloudFormation stack.

   ```
   aws cloudformation create-stack --stack-name data-transformation-tutorial-cli --template-body file://data-transformation-tutorial-cli.zip --capabilities CAPABILITY_NAMED_IAM 
   ```

1. CloudFormation provisions the resources specified in the template. It can take a few minutes to finish provisioning your resources. Use the following command to see the status of your CloudFormation stack.

   ```
   aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli
   ```

1. When the status of your CloudFormation stack is `StackStatus: "CREATE_COMPLETE"`, use the following command to retrieve relevant output values for future steps.

   ```
    aws cloudformation describe-stacks --stack-name data-transformation-tutorial-cli --query "Stacks[*].Outputs[*].{OutputKey: OutputKey, OutputValue: OutputValue, Description: Description}"
   ```

   The output values are the following:
   + ApiRole, which is the role name that allows API Gateway to put items in the DynamoDB table. For this tutorial, the role name is `data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG`.
   + DDBTableName, which is the name of the DynamoDB table. For this tutorial, the table name is `data-transformation-tutorial-cli-ddb`
   + ResourceId, which is the ID for the pets resource where the `GET` and `POST` methods are exposed. For this tutorial, the Resource ID is `efg456`
   + ApiId, which is the ID for the API. For this tutorial, the API ID is `abc123`.

**To test the `GET` method before data transformation**
+ Use the following command to test the `GET` method. 

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
            --resource-id efg456 \
            --http-method GET
  ```

  The output of the test will show the following.

  ```
  [
    {
      "id": 1,
      "type": "dog",
      "price": 249.99
    },
    {
      "id": 2,
      "type": "cat",
      "price": 124.99
    },
    {
      "id": 3,
      "type": "fish",
      "price": 0.99
    }
  ]
  ```

  You will transform this output according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).

**To transform the `GET` integration response**
+ Use the following command to update the integration response for the `GET` method. Replace the *rest-api-id* and *resource-id* with your values.

  Use the following command to create the integration response.

  ```
  aws apigateway put-integration-response --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
    --status-code 200 \
    --selection-pattern "" \
    --response-templates '{"application/json": "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"}'
  ```

**To test the `GET` method**
+ Use the following command to test the `GET` method.

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method GET \
  ```

  The output of the test will show the transformed response. 

  ```
  [
    {
      "description" : "Item 1 is a dog.",
      "askingPrice" : 249.99
    },
    {
      "description" : "Item 2 is a cat.",
      "askingPrice" : 124.99
    },
    {
      "description" : "Item 3 is a fish.",
      "askingPrice" : 0.99
    }
  ]
  ```

**To create a `POST` method**

1. Use the following command to create a new method on the `/pets` resource.

   ```
   aws apigateway put-method --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --authorization-type "NONE" \
   ```

   This method will allow you to send pet information to the DynamoDB table that your created in the CloudFormation stack.

1.  Use the following command to create an AWS service integration on the `POST` method.

   ```
   aws apigateway put-integration --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --type AWS \
     --integration-http-method POST \
     --uri "arn:aws:apigateway:us-east-2:dynamodb:action/PutItem" \
     --credentials arn:aws:iam::111122223333:role/data-transformation-tutorial-cli-APIGatewayRole-ABCDEFG \
     --request-templates '{"application/json":"{\"TableName\":\"data-transformation-tutorial-cli-ddb\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"}'
   ```

1.  Use the following command to create a method response for a successful call of the `POST` method. 

   ```
   aws apigateway put-method-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200
   ```

1. Use the following command to create an integration response for the successful call of the `POST` method.

   ```
   aws apigateway put-integration-response --rest-api-id abc123 \
     --resource-id efg456 \
     --http-method POST \
     --status-code 200 \
     --selection-pattern "" \
     --response-templates '{"application/json": "{\"message\": \"Your response was recorded at $context.requestTime\"}"}'
   ```

**To test the `POST` method**
+ Use the following command to test the `POST` method.

  ```
  aws apigateway test-invoke-method --rest-api-id abc123 \
    --resource-id efg456 \
    --http-method POST \
    --body '{\"id\": \"4\", \"type\": \"dog\", \"price\": \"321\"}'
  ```

  The output will show the successful message.

**To delete an CloudFormation stack**
+ Use the following command to delete your CloudFormation resources.

  ```
  aws cloudformation delete-stack  --stack-name data-transformation-tutorial-cli
  ```

## Completed data transformation CloudFormation template
<a name="api-gateway-data-transformations-full-cfn-stack"></a>

The following example is a completed CloudFormation template, which creates an API and a DynamoDB table with a `/pets` resource with `GET` and `POST` methods. 
+ The `GET` method will get data from the `http://petstore-demo-endpoint.execute-api.com/petstore/pets` HTTP endpoint. The output data will be transformed according to the mapping template in [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).
+ The `POST` method will allow the user to `POST` pet information to a DynamoDB table using a mapping template.

### Example CloudFormation template
<a name="mapping-template-cfn-example"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Description: A completed Amazon API Gateway REST API that uses non-proxy integration to POST to an Amazon DynamoDB table and non-proxy integration to GET transformed pets data.
Parameters:
  StageName:
    Type: String
    Default: v1
    Description: Name of API stage.
Resources:
  DynamoDBTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: !Sub data-transformation-tutorial-complete
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: N
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  APIGatewayRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17		 	 	 
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - apigateway.amazonaws.com
      Policies:
        - PolicyName: APIGatewayDynamoDBPolicy
          PolicyDocument:
            Version: 2012-10-17		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - 'dynamodb:PutItem'
                Resource: !GetAtt DynamoDBTable.Arn
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: data-transformation-complete-api
      ApiKeySourceType: HEADER
  PetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref Api
      ParentId: !GetAtt Api.RootResourceId
      PathPart: 'pets'
  PetsMethodGet:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: GET
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: HTTP
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: GET
        Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets/
        PassthroughBehavior: WHEN_NO_TEMPLATES
        IntegrationResponses:
          - StatusCode: '200'
            ResponseTemplates:
              application/json: "#set($inputRoot = $input.path(\"$\"))\n[\n#foreach($elem in $inputRoot)\n {\n  \"description\": \"Item $elem.id is a $elem.type\",\n  \"askingPrice\": \"$elem.price\"\n }#if($foreach.hasNext),#end\n\n#end\n]"
      MethodResponses:
        - StatusCode: '200'
  PetsMethodPost:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      RestApiId: !Ref Api
      ResourceId: !Ref PetsResource
      HttpMethod: POST
      ApiKeyRequired: false
      AuthorizationType: NONE
      Integration:
        Type: AWS
        Credentials: !GetAtt APIGatewayRole.Arn
        IntegrationHttpMethod: POST
        Uri: arn:aws:apigateway:us-west-1:dynamodb:action/PutItem
        PassthroughBehavior: NEVER
        RequestTemplates: 
          application/json: "{\"TableName\":\"data-transformation-tutorial-complete\",\"Item\":{\"id\":{\"N\":$input.json(\"$.id\")},\"type\":{\"S\":$input.json(\"$.type\")},\"price\":{\"N\":$input.json(\"$.price\")} }}"
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: "{\"message\": \"Your response was recorded at $context.requestTime\"}"
      MethodResponses:
        - StatusCode: '200'

  ApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - PetsMethodGet
    Properties:
      RestApiId: !Ref Api
      StageName: !Sub '${StageName}'
Outputs:
  ApiId:
    Description: API ID for CLI commands
    Value: !Ref Api
  ResourceId:
    Description: /pets resource ID for CLI commands
    Value: !Ref PetsResource
  ApiRole:
    Description: Role ID to allow API Gateway to put and scan items in DynamoDB table
    Value: !Ref APIGatewayRole
  DDBTableName:
    Description: DynamoDB table name
    Value: !Ref DynamoDBTable
```

# Examples using variables for mapping template transformations for API Gateway
<a name="api-gateway-mapping-variable-examples"></a>

The following examples show how to use `$context`, `input`, and `util` variables in mapping templates. You can use a mock integration or a Lambda non-proxy integration that returns the input event back to API Gateway. For a list of all supported variables for data transformations, see [Variables for data transformations for API Gateway](api-gateway-mapping-template-reference.md).

## Example 1: Pass multiple `$context` variables to the integration endpoint
<a name="context-variables-template-example"></a>

The following example shows a mapping template that maps incoming `$context` variables to backend variables with slightly different names in an integration request payload:

```
{
    "stage" : "$context.stage",
    "request_id" : "$context.requestId",
    "api_id" : "$context.apiId",
    "resource_path" : "$context.resourcePath",
    "resource_id" : "$context.resourceId",
    "http_method" : "$context.httpMethod",
    "source_ip" : "$context.identity.sourceIp",
    "user-agent" : "$context.identity.userAgent",
    "account_id" : "$context.identity.accountId",
    "api_key" : "$context.identity.apiKey",
    "caller" : "$context.identity.caller",
    "user" : "$context.identity.user",
    "user_arn" : "$context.identity.userArn"
}
```

The output of this mapping template should look like the following:

```
{
  stage: 'prod',
  request_id: 'abcdefg-000-000-0000-abcdefg',
  api_id: 'abcd1234',
  resource_path: '/',
  resource_id: 'efg567',
  http_method: 'GET',
  source_ip: '192.0.2.1',
  user-agent: 'curl/7.84.0',
  account_id: '111122223333',
  api_key: 'MyTestKey',
  caller: 'ABCD-0000-12345',
  user: 'ABCD-0000-12345',
  user_arn: 'arn:aws:sts::111122223333:assumed-role/Admin/carlos-salazar'
}
```

One of the variables is an API key. This example assumes that the method requires an API key.

## Example 2: Pass all request parameters to the integration endpoint via a JSON payload
<a name="input-examples-mapping-templates"></a>

The following example passes all request parameters, including `path`, `querystring`, and `header` parameters, through to the integration endpoint via a JSON payload:

```
#set($allParams = $input.params())
{
  "params" : {
    #foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
    "$type" : {
      #foreach($paramName in $params.keySet())
      "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
      #if($foreach.hasNext),#end
      #end
    }
    #if($foreach.hasNext),#end
    #end
  }
}
```

If a request has the following input parameters:
+ A path parameter named `myparam`
+ Query string parameters `querystring1=value1,value2`
+ Headers `"header1" : "value1"`.

The output of this mapping template should look like the following:

```
{"params":{"path":{"example2":"myparamm"},"querystring":{"querystring1":"value1,value2"},"header":{"header1":"value1"}}}
```

## Example 3: Pass a subsection of a method request to the integration endpoint
<a name="input-example-json-mapping-template"></a>

 The following example uses the input parameter `name` to retrieve only the `name` parameter and the input parameter `input.json('$')` to retrieve the entire body of the method request:

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$') 
}
```

For a request that includes the query string parameters `name=Bella&type=dog` and the following body:

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

The output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body" : {"Price":"249.99","Age":"6"}
}
```

This mapping template removes the query string parameter `type=dog`.

 If the JSON input contains unescaped characters that cannot be parsed by JavaScript, API Gateway might return a 400 response. Apply `$util.escapeJavaScript($input.json('$'))` to ensure the JSON input can be parsed properly. 

The previous example with `$util.escapeJavaScript($input.json('$'))` applied is as follows:

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$'))"
}
```

In this case, the output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body": {"Price":"249.99","Age":"6"}
}
```

## Example 4: Use JSONPath expression to pass a subsection of a method request to the integration endpoint
<a name="input-example-inputs-mapping-template"></a>

The following example uses the JSONPath expressions to retrieve only the input parameter `name` and the `Age` from the request body:

```
{
    "name" : "$input.params('name')",
    "body" : $input.json('$.Age')  
}
```

For a request that includes the query string parameters `name=Bella&type=dog` and the following body:

```
{
    "Price" : "249.99",
    "Age": "6"
}
```

The output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body" : "6"
}
```

This mapping template removes the query string parameter `type=dog` and the `Price` field from the body.

 If a method request payload contains unescaped characters that cannot be parsed by JavaScript, API Gateway might return a `400` response. Apply `$util.escapeJavaScript()` to ensure the JSON input can be parsed properly.

The previous example with `$util.escapeJavaScript($input.json('$.Age'))` applied is as follows:

```
{
    "name" : "$input.params('name')",
    "body" : "$util.escapeJavaScript($input.json('$.Age'))" 
}
```

In this case, the output of this mapping template should look like the following:

```
{
    "name" : "Bella",
    "body": "\"6\""
}
```

## Example 5: Use a JSONPath expression to pass information about a method request to the integration endpoint
<a name="input-example-request-and-response"></a>

The following example uses `$input.params()`, `$input.path()`, and `$input.json()` to send information about a method request to the integration endpoint. This mapping template uses the `size()` method to provide the number of elements in a list.

```
{
    "id" : "$input.params('id')",
    "count" : "$input.path('$.things').size()",
    "things" : $input.json('$.things')
}
```

For a request that includes the path parameter `123` and the following body:

```
{
      "things": {
            "1": {},
            "2": {},
            "3": {}
      }
}
```

The output of this mapping template should look like the following:

```
{"id":"123","count":"3","things":{"1":{},"2":{},"3":{}}}
```

 If a method request payload contains unescaped characters that cannot be parsed by JavaScript, API Gateway might return a `400` response. Apply `$util.escapeJavaScript()` to ensure the JSON input can be parsed properly.

The previous example with `$util.escapeJavaScript($input.json('$.things'))` applied is as follows:

```
{
     "id" : "$input.params('id')",
     "count" : "$input.path('$.things').size()",
     "things" : "$util.escapeJavaScript($input.json('$.things'))"
}
```

The output of this mapping template should look like the following:

```
{"id":"123","count":"3","things":"{\"1\":{},\"2\":{},\"3\":{}}"}
```

# Variables for data transformations for API Gateway
<a name="api-gateway-mapping-template-reference"></a>

When you create a parameter mapping, you can use context variables as your data source. When you create mapping template transformations, you can use context variables, input, and util variables in scripts you write in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html). For example mapping templates that use these reference variables, see [Examples using variables for mapping template transformations for API Gateway](api-gateway-mapping-variable-examples.md).

For a list of reference variables for access logging, see [Variables for access logging for API Gateway](api-gateway-variables-for-access-logging.md).

## Context variables for data transformations
<a name="context-variable-reference"></a>

You can use the following case-sensitive `$context` variables for data transformations.


| Parameter | Description | 
| --- | --- | 
| \$1context.accountId |  The API owner's AWS account ID.  | 
| \$1context.apiId |  The identifier API Gateway assigns to your API.  | 
| \$1context.authorizer.claims.property |  A property of the claims returned from the Amazon Cognito user pool after the method caller is successfully authenticated. For more information, see [Control access to REST APIs using Amazon Cognito user pools as an authorizer](apigateway-integrate-with-cognito.md).  Calling `$context.authorizer.claims` returns null.   | 
| \$1context.authorizer.principalId |  The principal user identification associated with the token sent by the client and returned from an API Gateway Lambda authorizer (formerly known as a custom authorizer). For more information, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).  | 
| \$1context.authorizer.property |  The stringified value of the specified key-value pair of the `context` map returned from an API Gateway Lambda authorizer function. For example, if the authorizer returns the following `context` map:  <pre>"context" : {<br />  "key": "value",<br />  "numKey": 1,<br />  "boolKey": true<br />}</pre> Calling `$context.authorizer.key` returns the `"value"` string, calling `$context.authorizer.numKey` returns the `"1"` string, and calling `$context.authorizer.boolKey` returns the `"true"` string. For *property*, the only supported special character is the underscore `(_)` character. For more information, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).  | 
| \$1context.awsEndpointRequestId |  The AWS endpoint's request ID.  | 
| \$1context.deploymentId | The ID of the API deployment. | 
| \$1context.domainName |  The full domain name used to invoke the API. This should be the same as the incoming `Host` header.  | 
| \$1context.domainPrefix |  The first label of the `$context.domainName`.  | 
| \$1context.error.message |  A string containing an API Gateway error message. This variable can only be used for simple variable substitution in a [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) body-mapping template, which is not processed by the Velocity Template Language engine, and in access logging. For more information, see [Monitor WebSocket API execution with CloudWatch metrics](apigateway-websocket-api-logging.md) and [Setting up gateway responses to customize error responses](api-gateway-gatewayResponse-definition.md#customize-gateway-responses).  | 
| \$1context.error.messageString | The quoted value of \$1context.error.message, namely "\$1context.error.message". | 
| \$1context.error.responseType |  A [type](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html#responseType) of [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html). This variable can only be used for simple variable substitution in a [GatewayResponse](https://docs.aws.amazon.com/apigateway/latest/api/API_GatewayResponse.html) body-mapping template, which is not processed by the Velocity Template Language engine, and in access logging. For more information, see [Monitor WebSocket API execution with CloudWatch metrics](apigateway-websocket-api-logging.md) and [Setting up gateway responses to customize error responses](api-gateway-gatewayResponse-definition.md#customize-gateway-responses).  | 
| \$1context.error.validationErrorString |  A string containing a detailed validation error message.  | 
| \$1context.extendedRequestId | The extended ID that API Gateway generates and assigns to the API request. The extended request ID contains useful information for debugging and troubleshooting. | 
| \$1context.httpMethod |  The HTTP method used. Valid values include: `DELETE`, `GET`, `HEAD`, `OPTIONS`, `PATCH`, `POST`, and `PUT`.  | 
| \$1context.identity.accountId |  The AWS account ID associated with the request.  | 
| \$1context.identity.apiKey |  For API methods that require an API key, this variable is the API key associated with the method request. For methods that don't require an API key, this variable is null. For more information, see [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md).  | 
| \$1context.identity.apiKeyId | The API key ID associated with an API request that requires an API key. | 
| \$1context.identity.caller |  The principal identifier of the caller that signed the request. Supported for resources that use IAM authorization.  | 
| \$1context.identity.cognitoAuthenticationProvider |  A comma-separated list of all the Amazon Cognito authentication providers used by the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  For example, for an identity from an Amazon Cognito user pool, `cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` For information about the available Amazon Cognito authentication providers, see [Using Federated Identities](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) in the *Amazon Cognito Developer Guide*. | 
| \$1context.identity.cognitoAuthenticationType |  The Amazon Cognito authentication type of the caller making the request. Available only if the request was signed with Amazon Cognito credentials. Possible values include `authenticated` for authenticated identities and `unauthenticated` for unauthenticated identities. | 
| \$1context.identity.cognitoIdentityId |  The Amazon Cognito identity ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.cognitoIdentityPoolId |  The Amazon Cognito identity pool ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.principalOrgId |  The [AWS organization ID](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html).  | 
| \$1context.identity.sourceIp |  The source IP address of the immediate TCP connection making the request to the API Gateway endpoint.  | 
| \$1context.identity.clientCert.clientCertPem |  The PEM-encoded client certificate that the client presented during mutual TLS authentication. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.subjectDN |  The distinguished name of the subject of the certificate that a client presents. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.issuerDN |  The distinguished name of the issuer of the certificate that a client presents. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.serialNumber |  The serial number of the certificate. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.validity.notBefore |  The date before which the certificate is invalid. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
| \$1context.identity.clientCert.validity.notAfter |  The date after which the certificate is invalid. Present when a client accesses an API by using a custom domain name that has mutual TLS enabled. Present only in access logs if mutual TLS authentication fails.  | 
|  \$1context.identity.vpcId | The VPC ID of the VPC making the request to the API Gateway endpoint. | 
|  \$1context.identity.vpceId |  The VPC endpoint ID of the VPC endpoint making the request to the API Gateway endpoint. Present only when you have a private API.  | 
| \$1context.identity.user |  The principal identifier of the user that will be authorized against resource access. Supported for resources that use IAM authorization.  | 
| \$1context.identity.userAgent |  The [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) header of the API caller.  | 
| \$1context.identity.userArn |  The Amazon Resource Name (ARN) of the effective user identified after authentication. For more information, see [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html).  | 
| \$1context.isCanaryRequest |  Returns `true` if the request was directed to the canary and `false` if the request was not directed to the canary. Present only when you have a canary enabled. | 
| \$1context.path | The request path. For example, for a non-proxy request URL of https://\$1rest-api-id\$1.execute-api.\$1region\$1.amazonaws.com/\$1stage\$1/root/child, the \$1context.path value is /\$1stage\$1/root/child.  | 
| \$1context.protocol | The request protocol, for example, HTTP/1.1.  API Gateway APIs can accept HTTP/2 requests, but API Gateway sends requests to backend integrations using HTTP/1.1. As a result, the request protocol is logged as HTTP/1.1 even if a client sends a request that uses HTTP/2.   | 
| \$1context.requestId |  An ID for the request. Clients can override this request ID. Use `$context.extendedRequestId` for a unique request ID that API Gateway generates.  | 
| \$1context.requestOverride.header.header\$1name |  The request header override. If this parameter is defined, it contains the headers to be used instead of the **HTTP Headers** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.requestOverride.path.path\$1name |  The request path override. If this parameter is defined, it contains the request path to be used instead of the **URL Path Parameters** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.requestOverride.querystring.querystring\$1name |  The request query string override. If this parameter is defined, it contains the request query strings to be used instead of the **URL Query String Parameters** that are defined in the **Integration Request** pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md).  | 
| \$1context.responseOverride.header.header\$1name | The response header override. If this parameter is defined, it contains the header to be returned instead of the Response header that is defined as the Default mapping in the Integration Response pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md). | 
| \$1context.responseOverride.status | The response status code override. If this parameter is defined, it contains the status code to be returned instead of the Method response status that is defined as the Default mapping in the Integration Response pane. For more information, see [Override your API's request and response parameters and status codes for REST APIs in API Gateway](apigateway-override-request-response-parameters.md). | 
| \$1context.requestTime | The [CLF](https://httpd.apache.org/docs/current/logs.html#common)-formatted request time (dd/MMM/yyyy:HH:mm:ss \$1-hhmm). | 
| \$1context.requestTimeEpoch | The [Epoch](https://en.wikipedia.org/wiki/Unix_time)-formatted request time, in milliseconds. | 
| \$1context.resourceId |  The identifier that API Gateway assigns to your resource.  | 
| \$1context.resourcePath |  The path to your resource. For example, for the non-proxy request URI of `https://{rest-api-id}.execute-api.{region}.amazonaws.com/{stage}/root/child`, The `$context.resourcePath` value is `/root/child`. For more information, see [Tutorial: Create a REST API with an HTTP non-proxy integration](api-gateway-create-api-step-by-step.md).   | 
| \$1context.stage |  The deployment stage of the API request (for example, `Beta` or `Prod`).  | 
| \$1context.wafResponseCode |  The response received from [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html): `WAF_ALLOW` or `WAF_BLOCK`. Will not be set if the stage is not associated with a web ACL. For more information, see [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md).  | 
| \$1context.webaclArn |  The complete ARN of the web ACL that is used to decide whether to allow or block the request. Will not be set if the stage is not associated with a web ACL. For more information, see [Use AWS WAF to protect your REST APIs in API Gateway](apigateway-control-access-aws-waf.md).  | 

## Input variables
<a name="input-variable-reference"></a>

You can use the following case-sensitive `$input` variables to refer to the method request payload and method request parameters. The following functions are available:


| Variable and function | Description | 
| --- | --- | 
| \$1input.body |  Returns the raw request payload as a string. You can use `$input.body` to preserve entire floating point numbers, such as `10.00`. | 
| \$1input.json(x) | This function evaluates a JSONPath expression and returns the results as a JSON string. For example, `$input.json('$.pets')` returns a JSON string representing the `pets` structure. For more information about JSONPath, see [JSONPath](https://goessner.net/articles/JsonPath/) or [JSONPath for Java](https://github.com/json-path/JsonPath). | 
| \$1input.params() |  Returns a map of all the request parameters. We recommend that you use `$util.escapeJavaScript` to sanitize the result to avoid a potential injection attack. For full control of request sanitization, use a proxy integration without a template and handle request sanitization in your integration. | 
| \$1input.params(x) | Returns the value of a method request parameter from the path, query string, or header value (searched in that order), given a parameter name string `x`. We recommend that you use `$util.escapeJavaScript` to sanitize the parameter to avoid a potential injection attack. For full control of parameter sanitization, use a proxy integration without a template and handle request sanitization in your integration. | 
| \$1input.path(x) | Takes a JSONPath expression string (`x`) and returns a JSON object representation of the result. This allows you to access and manipulate elements of the payload natively in [Apache Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html). For example, if the expression `$input.path('$.pets')` returns an object like this: <pre>[<br />  { <br />    "id": 1, <br />    "type": "dog", <br />    "price": 249.99 <br />  }, <br />  { <br />    "id": 2, <br />    "type": "cat", <br />    "price": 124.99 <br />  }, <br />  { <br />    "id": 3, <br />    "type": "fish", <br />    "price": 0.99 <br />  } <br />]</pre> `$input.path('$.pets').size()` would return `"3"`. For more information about JSONPath, see [JSONPath](https://goessner.net/articles/JsonPath/) or [JSONPath for Java](https://github.com/json-path/JsonPath). | 

## Stage variables
<a name="stagevariables-template-reference"></a>

You can use the following stage variables as placeholders for ARNs and URLs in method integrations. For more information, see [Use stage variables for a REST API in API Gateway](stage-variables.md).


| Syntax | Description | 
| --- | --- | 
| \$1stageVariables.variable\$1name, \$1stageVariables['variable\$1name'], or \$1\$1stageVariables['variable\$1name']\$1  |  *variable\$1name* represents a stage variable name.  | 

## Util variables
<a name="util-template-reference"></a>

You can use the following case-sensitive `$util` variables to use utility functions for mapping templates. Unless otherwise specified, the default character set is UTF-8.


| Function | Description | 
| --- | --- | 
| \$1util.escapeJavaScript() |  Escapes the characters in a string using JavaScript string rules.  This function will turn any regular single quotes (`'`) into escaped ones (`\'`). However, the escaped single quotes are not valid in JSON. Thus, when the output from this function is used in a JSON property, you must turn any escaped single quotes (`\'`) back to regular single quotes (`'`). This is shown in the following example:  <pre> "input" : "$util.escapeJavaScript(data).replaceAll("\\'","'")"</pre>   | 
| \$1util.parseJson() |   Takes "stringified" JSON and returns an object representation of the result. You can use the result from this function to access and manipulate elements of the payload natively in Apache Velocity Template Language (VTL). For example, if you have the following payload:  <pre>{"errorMessage":"{\"key1\":\"var1\",\"key2\":{\"arr\":[1,2,3]}}"}</pre>  and use the following mapping template  <pre>#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))<br />{<br />   "errorMessageObjKey2ArrVal" : $errorMessageObj.key2.arr[0]<br />}<br /></pre> You will get the following output: <pre>{<br />   "errorMessageObjKey2ArrVal" : 1<br />}<br /></pre>  | 
| \$1util.urlEncode() | Converts a string into "application/x-www-form-urlencoded" format. | 
| \$1util.urlDecode() | Decodes an "application/x-www-form-urlencoded" string. | 
| \$1util.base64Encode() | Encodes the data into a base64-encoded string. | 
| \$1util.base64Decode() | Decodes the data from a base64-encoded string. | 