

# API Gateway WebSocket APIs


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

API Gateway WebSocket APIs are bidirectional. A client can send messages to a service, and services can independently send messages to clients. This bidirectional behavior enables richer client/service interactions because services can push data to clients without requiring clients to make an explicit request. WebSocket APIs are often used in real-time applications such as chat applications, collaboration platforms, multiplayer games, and financial trading platforms.

For an example app to get started with, see [Tutorial: Create a WebSocket chat app with a WebSocket API, Lambda and DynamoDB](websocket-api-chat-app.md).

In this section, you can learn how to develop, publish, protect, and monitor your WebSocket APIs using API Gateway.

**Topics**
+ [

# Overview of WebSocket APIs in API Gateway
](apigateway-websocket-api-overview.md)
+ [

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

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

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

# Monitor WebSocket APIs in API Gateway
](websocket-api-monitor.md)

# Overview of WebSocket APIs in API Gateway
Overview of WebSocket APIs

In API Gateway you can create a WebSocket API as a stateful frontend for an AWS service (such as Lambda or DynamoDB) or for an HTTP endpoint. The WebSocket API invokes your backend based on the content of the messages it receives from client apps.

Unlike a REST API, which receives and responds to requests, a WebSocket API supports two-way communication between client apps and your backend. The backend can send callback messages to connected clients.

In your WebSocket API, incoming JSON messages are directed to backend integrations based on routes that you configure. (Non-JSON messages are directed to a `$default` route that you configure.)

A *route* includes a *route key*, which is the value that is expected once a *route selection expression* is evaluated. The `routeSelectionExpression` is an attribute defined at the API level. It specifies a JSON property that is expected to be present in the message payload. For more information about route selection expressions, see [Route selection expressions](websocket-api-develop-routes.md#apigateway-websocket-api-route-selection-expressions).

For example, if your JSON messages contain an `action` property, and you want to perform different actions based on this property, your route selection expression might be `${request.body.action}`. Your routing table would specify which action to perform by matching the value of the `action` property against the custom route key values that you have defined in the table.

## Use routes for a WebSocket API


There are three predefined routes that can be used: `$connect`, `$disconnect`, and `$default`. In addition, you can create custom routes.
+ API Gateway calls the `$connect` route when a persistent connection between the client and a WebSocket API is being initiated.
+ API Gateway calls the `$disconnect` route when the client or the server disconnects from the API.
+ API Gateway calls a custom route after the route selection expression is evaluated against the message if a matching route is found; the match determines which integration is invoked.
+ API Gateway calls the `$default` route if the route selection expression cannot be evaluated against the message or if no matching route is found.

For more information about the `$connect` and `$disconnect` routes, see [Manage connected users and client apps: `$connect` and `$disconnect` routes](apigateway-websocket-api-route-keys-connect-disconnect.md).

For more information about the `$default` route and custom routes, see [Invoke your backend integration with the `$default` Route and custom routes in API Gateway](apigateway-websocket-api-routes-integrations.md).

## Send data to connected client apps


Backend services can send data to connected client apps. You can send data by doing the following:
+ Use an integration to send a response, which is returned to the client by a route response that you have defined.
+ You can use the `@connections` API to send a POST request. For more information, see [Use `@connections` commands in your backend service](apigateway-how-to-call-websocket-api-connections.md).

## WebSocket API status codes


API Gateway WebSocket APIs use the following status codes for communication from the server to client as described in the [WebSocket Close Code Number Registry](https://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number):

1001  
API Gateway returns this status code when the client is idle for 10 minutes or reaches the maximum 2 hour connection lifetime.

1003  
API Gateway returns this status code when an endpoint receives a binary media type. Binary media types aren't supported for WebSocket APIs.

1005  
API Gateway returns this status code if the client sends a close frame without a closure code.

1006  
API Gateway returns this status code if there is an unexpected closure of the connection, such as the TCP connection closed without a WebSocket close frame.

1008  
API Gateway returns this status code when an endpoint receives too many requests from a particular client.

1009  
API Gateway returns this status code when an endpoint receives a message that is too big for it to process.

1011  
API Gateway returns this status code when there is an internal server error. 

1012  
API Gateway returns this status code if the service restarts.

# Manage connected users and client apps: `$connect` and `$disconnect` routes
Manage connected users and client apps

The following section describes how to use the `$connect` and `$disconnect` routes for your WebSocket API.

**Topics**
+ [

## The `$connect` route
](#apigateway-websocket-api-routes-about-connect)
+ [

## Passing connection information from the `$connect` route
](#apigateway-websocket-api-passing-connectionId-on-connect)
+ [

## The `$disconnect` route
](#apigateway-websocket-api-routes-about-disconnect)

## The `$connect` route


Client apps connect to your WebSocket API by sending a WebSocket upgrade request. If the request succeeds, the `$connect` route is executed while the connection is being established.

Because the WebSocket connection is a stateful connection, you can configure authorization on the `$connect` route only. `AuthN`/`AuthZ` will be performed only at connection time.

Until execution of the integration associated with the `$connect` route is completed, the upgrade request is pending and the actual connection will not be established. If the `$connect` request fails (e.g., due to `AuthN`/`AuthZ` failure or an integration failure), the connection will not be made.

**Note**  
If authorization fails on `$connect`, the connection will not be established, and the client will receive a `401` or `403` response.

Setting up an integration for `$connect` is optional. You should consider setting up a `$connect` integration if:
+ You want to enable clients to specify subprotocols by using the `Sec-WebSocket-Protocol` field. For example code, see [Set up a `$connect` route that requires a WebSocket subprotocol](websocket-connect-route-subprotocol.md).
+ You want to be notified when clients connect.
+ You want to throttle connections or control who connects.
+ You want your backend to send messages back to clients using a callback URL.
+ You want to store each connection ID and other information into a database (for example, Amazon DynamoDB).

## Passing connection information from the `$connect` route


 You can use both proxy and non-proxy integrations to pass information from the `$connect` route to a database or other AWS service. 

### To pass connection information using a proxy integration


You can access the connection information from a Lambda proxy integration in the event. Use another AWS service or AWS Lambda function to post to the connection. 

The following Lambda function shows how to use the `requestContext` object to log the connection ID, domain name, stage name, and query strings. 

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

```
 export const handler = async(event, context) => {
    const connectId = event["requestContext"]["connectionId"]
    const domainName = event["requestContext"]["domainName"]
    const stageName = event["requestContext"]["stage"]
    const qs = event['queryStringParameters']
    console.log('Connection ID: ', connectId, 'Domain Name: ', domainName, 'Stage Name: ', stageName, 'Query Strings: ', qs )
    return {"statusCode" : 200}
};
```

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

```
import json
import logging
logger = logging.getLogger()
logger.setLevel("INFO")


def lambda_handler(event, context):
    connectId = event["requestContext"]["connectionId"]
    domainName = event["requestContext"]["domainName"]
    stageName = event["requestContext"]["stage"]
    qs = event['queryStringParameters']
    connectionInfo = {
        'Connection ID': connectId,
        'Domain Name': domainName,
        'Stage Name': stageName,
        'Query Strings': qs}
    logging.info(connectionInfo)
    return {"statusCode": 200}
```

------

### To pass connection information using a non-proxy integration

+ You can access the connection information with a non-proxy integration. Set up the integration request and provide a WebSocket API request template. The following [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) mapping template provides an integration request. This request sends the following details to a non-proxy integration: 
  + Connection ID
  + Domain name
  + Stage name
  + Path
  + Headers
  + Query strings

  This request sends the connection ID, domain name, stage name, paths, headers, and query strings to a non-proxy integration.

  ```
  {
      "connectionId": "$context.connectionId",
      "domain": "$context.domainName",
      "stage": "$context.stage",
      "params": "$input.params()"
  }
  ```

  For more information about setting up data transformations, see [Data transformations for WebSocket APIs in API Gateway](websocket-api-data-transformations.md).

  To complete the integration request, set `StatusCode: 200` for the integration response. To learn more about setting up an integration response, see [Set up an integration response using the API Gateway console](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-using-console).

## The `$disconnect` route


The `$disconnect` route is executed after the connection is closed.

The connection can be closed by the server or by the client. As the connection is already closed when it is executed, `$disconnect` is a best-effort event. API Gateway will try its best to deliver the `$disconnect` event to your integration, but it cannot guarantee delivery.

The backend can initiate disconnection by using the `@connections` API. For more information, see [Use `@connections` commands in your backend service](apigateway-how-to-call-websocket-api-connections.md).

# Invoke your backend integration with the `$default` Route and custom routes in API Gateway
Invoke your backend integration

The following section describes how to invoke your backend integration using either the `$default` route or a custom route for a WebSocket API.

**Topics**
+ [

## Using routes to process messages
](#apigateway-websocket-api-overview-routes)
+ [

## The `$default` route
](#apigateway-websocket-api-routes-about-default)
+ [

## Custom routes
](#apigateway-websocket-api-routes-about-custom)
+ [

## Using API Gateway WebSocket API integrations to connect to your business logic
](#apigateway-websocket-api-overview-integrations)
+ [

## Important differences between WebSocket APIs and REST APIs
](#apigateway-websocket-api-overview-integrations-differences)

## Using routes to process messages


In API Gateway WebSocket APIs, messages can be sent from the client to your backend service and vice versa. Unlike HTTP's request/response model, in WebSocket the backend can send messages to the client without the client taking any action.

Messages can be JSON or non-JSON. However, only JSON messages can be routed to specific integrations based on message content. Non-JSON messages are passed through to the backend by the `$default` route.

**Note**  
API Gateway supports message payloads up to 128 KB with a maximum frame size of 32 KB. If a message exceeds 32 KB, you must split it into multiple frames, each 32 KB or smaller. If a larger message (or frame) is received, the connection is closed with code 1009.  
Currently binary payloads are not supported. If a binary frame is received, the connection is closed with code 1003. However, it is possible to convert binary payloads to text. See [Binary media types for WebSocket APIs in API Gateway](websocket-api-develop-binary-media-types.md).

With WebSocket APIs in API Gateway, JSON messages can be routed to execute a specific backend service based on message content. When a client sends a message over its WebSocket connection, this results in a *route request* to the WebSocket API. The request will be matched to the route with the corresponding route key in API Gateway. You can set up a route request for a WebSocket API in the API Gateway console, by using the AWS CLI, or by using an AWS SDK.

**Note**  
In the AWS CLI and AWS SDKs, you can create routes before or after you create integrations. Currently the console does not support reuse of integrations, so you must create the route first and then create the integration for that route.

You can configure API Gateway to perform validation on a route request before proceeding with the integration request. If the validation fails, API Gateway fails the request without calling your backend, sends a `"Bad request body"` gateway response similar to the following to the client, and publishes the validation results in CloudWatch Logs: 

```
{"message" : "Bad request body", "connectionId": "{connectionId}", "messageId": "{messageId}"}
```

This reduces unnecessary calls to your backend and lets you focus on the other requirements of your API.

You can also define a route response for your API's routes to enable two-way communication. A route response describes what data will be sent to your client upon completion of a particular route's integration. It is not necessary to define a response for a route if, for example, you want a client to send messages to your backend without receiving a response (one-way communication). However, if you don't provide a route response, API Gateway won't send any information about the result of your integration to your clients.

## The `$default` route


Every API Gateway WebSocket API can have a `$default` route. This is a special routing value that can be used in the following ways:
+ You can use it together with defined route keys, to specify a "fallback" route (for example, a generic mock integration that returns a particular error message) for incoming messages that don't match any of the defined route keys.
+ You can use it without any defined route keys, to specify a proxy model that delegates routing to a backend component.
+ You can use it to specify a route for non-JSON payloads.

## Custom routes


If you want to invoke a specific integration based on message content, you can do so by creating a custom route.

A custom route uses a route key and integration that you specify. When an incoming message contains a JSON property, and that property evaluates to a value that matches the route key value, API Gateway invokes the integration. (For more information, see [Overview of WebSocket APIs in API Gateway](apigateway-websocket-api-overview.md).)

For example, suppose you wanted to create a chat room application. You might start by creating a WebSocket API whose route selection expression is `$request.body.action`. You could then define two routes: `joinroom` and `sendmessage`. A client app might invoke the `joinroom` route by sending a message such as the following:

```
{"action":"joinroom","roomname":"developers"}
```

And it might invoke the `sendmessage` route by sending a message such as the following:

```
{"action":"sendmessage","message":"Hello everyone"}
```

## Using API Gateway WebSocket API integrations to connect to your business logic


After setting up a route for an API Gateway WebSocket API, you must specify the integration you'd like to use. As with a route, which can have a route request and a route response, an integration can have an *integration request* and an *integration response*. An *integration request* contains the information expected by your backend in order to process the request that came from your client. An *integration response* contains the data that your backend returns to API Gateway, and that may be used to construct a message to send to the client (if a route response is defined).

For more information about setting up integrations, see [Integrations for WebSocket APIs in API Gateway](apigateway-websocket-api-integrations.md).

## Important differences between WebSocket APIs and REST APIs


Integrations for WebSocket APIs are similar to integrations for REST APIs, except for the following differences:
+ Currently, in the API Gateway console you must create a route first and then create an integration as that route's target. However, in the API and CLI, you can create routes and integrations independently, in any order.
+ You can use a single integration for multiple routes. For example, if you have a set of actions that closely relate to each other, you might want all of those routes to go to a single Lambda function. Rather than defining the details of the integration multiple times, you can specify it once and assign it to each of the related routes.
**Note**  
Currently the console does not support reuse of integrations, so you must create the route first and then create the integration for that route.  
In the AWS CLI and AWS SDKs, you can reuse an integration by setting the route's target to a value of `"integrations/{integration-id}"`, where `{integration-id}"` is the unique ID of the integration to be associated with the route.
+ API Gateway provides multiple [selection expressions](apigateway-websocket-api-selection-expressions.md) you can use in your routes and integrations. You don't need to rely on the content type to select an input template or output mapping. As with route selection expressions, you can define a selection expression to be evaluated by API Gateway to choose the right item. All of them will fall back to the `$default` template if a matching template is not found.
  + In integration requests, the template selection expression supports `$request.body.<json_path_expression>` and static values.
  + In integration responses, the template selection expression supports `$request.body.<json_path_expression>`, `$integration.response.statuscode`, `$integration.response.header.<headerName>`, and static values.

In the HTTP protocol, in which requests and responses are sent synchronously; communication is essentially one-way. In the WebSocket protocol, communication is two-way. Responses are asynchronous and are not necessarily received by the client in the same order as the client's messages were sent. In addition, the backend can send messages to the client.

**Note**  
For a route that is configured to use `AWS_PROXY` or `LAMBDA_PROXY` integration, communication is one-way, and API Gateway will not pass the backend response through to the route response automatically. For example, in the case of `LAMBDA_PROXY` integration, the body that the Lambda function returns will not be returned to the client. If you want the client to receive integration responses, you must define a route response to make two-way communication possible.

# WebSocket selection expressions
WebSocket selection expressions

API Gateway uses selection expressions as a way to evaluate request and response context and produce a key. The key is then used to select from a set of possible values, typically provided by you, the API developer. The exact set of supported variables will vary depending on the particular expression. Each expression is discussed in more detail below.

For all of the expressions, the language follows the same set of rules:
+ A variable is prefixed with `"$"`.
+ Curly braces can be used to explicitly define variable boundaries, e.g., `"${request.body.version}-beta"`.
+ Multiple variables are supported, but evaluation occurs only once (no recursive evaluation).
+ A dollar sign (`$`) can be escaped with `"\"`. This is most useful when defining an expression that maps to the reserved `$default` key, e.g., `"\$default"`.
+ In some cases, a pattern format is required. In this case, the expression should be wrapped with forward slashes (`"/"`), e.g. `"/2\d\d/"` to match `2XX` status codes.

**Topics**
+ [

## Route response selection expressions
](#apigateway-websocket-api-route-response-selection-expressions)
+ [

## API key selection expressions
](#apigateway-websocket-api-apikey-selection-expressions)
+ [

## API mapping selection expressions
](#apigateway-websocket-api-mapping-selection-expressions)
+ [

## WebSocket selection expression summary
](#apigateway-websocket-api-selection-expression-table)

## Route response selection expressions


A [route response](apigateway-websocket-api-route-response.md) is used for modeling a response from the backend to the client. For WebSocket APIs, a route response is optional. When defined, it signals to API Gateway that it should return a response to a client upon receiving a WebSocket message.

Evaluation of the *route response selection expression* produces a route response key. Eventually, this key will be used to choose from one of the [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html) associated with the API. However, currently only the `$default` key is supported.

## API key selection expressions


This expression is evaluated when the service determines the given request should proceed only if the client provides a valid [API key](api-gateway-basic-concept.md#apigateway-definition-api-key).

Currently the only two supported values are `$request.header.x-api-key` and `$context.authorizer.usageIdentifierKey`.

## API mapping selection expressions


This expression is evaluated to determine which API stage is selected when a request is made using a custom domain.

Currently, the only supported value is `$request.basepath`.

## WebSocket selection expression summary


The following table summarizes the use cases for selection expressions in WebSocket APIs:


| Selection expression | Evaluates to key for | Notes | Example use case | 
| --- | --- | --- | --- | 
| Api.RouteSelectionExpression | Route.RouteKey | \$1default is supported as a catch-all route. | Route WebSocket messages based on the context of a client request. | 
| Route.ModelSelectionExpression | Key for Route.RequestModels | Optional. If provided for non-proxy integration, model validation occurs. `$default` is supported as a catch-all.  | Perform request validation dynamically within the same route. | 
| Integration.TemplateSelectionExpression | Key for Integration.RequestTemplates |  Optional. May be provided for non-proxy integration to manipulate incoming payloads. `${request.body.jsonPath}` and static values are supported. `$default` is supported as a catch-all.  | Manipulate the caller's request based on dynamic properties of the request. | 
| Integration.IntegrationResponseSelectionExpression | IntegrationResponse.IntegrationResponseKey |  Optional. May be provided for non-proxy integration. Acts as a pattern match for error messages (from Lambda) or status codes (from HTTP integrations). `$default` is required for non-proxy integrations to act as the catch-all for successful responses.  |  Manipulate the response from the backend. Choose the action to occur based on the dynamic response of the backend (e.g., handling certain errors distinctly).  | 
| IntegrationResponse.TemplateSelectionExpression | Key for IntegrationResponse.ResponseTemplates | Optional. May be provided for non-proxy integration. \$1default is supported.  |  In some cases, a dynamic property of the response may dictate different transformations within the same route and associated integration. `${request.body.jsonPath}`, `${integration.response.statuscode}`, `${integration.response.header.headerName}`, `${integration.response.multivalueheader.headerName}`, and static values are supported. `$default` is supported as a catch-all.  | 
| Route.RouteResponseSelectionExpression | RouteResponse.RouteResponseKey |  Should be provided to initiate two-way communication for a WebSocket route. Currently, this value is restricted to `$default` only.  |  | 
| RouteResponse.ModelSelectionExpression | Key for RouteResponse.RequestModels | Currently unsupported. |  | 

# Develop WebSocket APIs in API Gateway
Develop

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

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

**Topics**
+ [

# Create WebSocket APIs in API Gateway
](apigateway-websocket-api-create-empty-api.md)
+ [

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

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

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

# Integrations for WebSocket APIs in API Gateway
](apigateway-websocket-api-integrations.md)
+ [

# Request validation for WebSocket APIs in API Gateway
](websocket-api-request-validation.md)
+ [

# Data transformations for WebSocket APIs in API Gateway
](websocket-api-data-transformations.md)
+ [

# Binary media types for WebSocket APIs in API Gateway
](websocket-api-develop-binary-media-types.md)
+ [

# Invoke WebSocket APIs
](apigateway-how-to-call-websocket-api.md)

# Create WebSocket APIs in API Gateway
Create and configure

You can create a WebSocket API in the API Gateway console, by using the AWS CLI [create-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) command, or by using the `CreateApi` command in an AWS SDK. The following procedures show how to create a new WebSocket API.

**Note**  
WebSocket APIs only support TLS 1.2 and TLS 1.3. Earlier TLS versions are not supported.

## Create a WebSocket API using AWS CLI commands


The following [create-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) command creates an API with the `$request.body.action` route selection expression:

```
aws apigatewayv2 --region us-east-1 create-api --name "myWebSocketApi3" --protocol-type WEBSOCKET --route-selection-expression '$request.body.action'
```

The output looks like the following:

```
{
    "ApiKeySelectionExpression": "$request.header.x-api-key",
    "Name": "myWebSocketApi3",
    "CreatedDate": "2018-11-15T06:23:51Z",
    "ProtocolType": "WEBSOCKET",
    "RouteSelectionExpression": "'$request.body.action'",
    "ApiId": "aabbccddee"
}
```

## Create a WebSocket API using the API Gateway console


You can create a WebSocket API in the console by choosing the WebSocket protocol and giving the API a name.

**Important**  
Once you have created the API, you cannot change the protocol you have chosen for it. There is no way to convert a WebSocket API into a REST API or vice versa.

**To create a WebSocket API using the API Gateway console**

1. Sign in to the API Gateway console and choose **Create API**.

1. Under **WebSocket API**, choose **Build**. Only Regional endpoints are supported.

1. For **API name**, enter the name of your API.

1. For **Route selection expression**, enter a value. For example, `$request.body.action`. 

   For more information about route selection expressions, see [Route selection expressions](websocket-api-develop-routes.md#apigateway-websocket-api-route-selection-expressions).

1. Do one of the following:
   + Choose **Create blank API** to create an API with no routes.
   + Choose **Next** to attach routes to your API.

   You can attach routes after you create your API.

# IP address types for WebSocket APIs in API Gateway


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

## Considerations for IP address types


The following considerations might impact your use of IP address types:
+ The default IP address type for all WebSocket APIs is IPv4.
+ If you change the IP address type for an existing API from IPv4 to dualstack, confirm that any policies controlling access to your APIs have been updated to account for IPv6 calls. When you change the IP address type, the change takes effect immediately.
+ Your API can be mapped to a custom domain name with a different IP address type than your API. If you disable your default API endpoint, this might affect how callers can invoke your API.

## Change the IP address type of an WebSocket API


You can change the IP address type by updating the API’s configuration. You can update the API's configuration by using the AWS Management Console, the AWS CLI, CloudFormation, or an AWS SDK. If you change the API’s IP address type, you don't redeploy your API for the changes to take effect. 

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

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

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

1. Choose a WebSocket API.

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

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

1. Choose **Save**.

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

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

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

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

The output will look like the following:

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

------

# Create routes for WebSocket APIs in API Gateway
Routes

In your WebSocket API, incoming JSON messages are directed to backend integrations based on routes that you configure. (Non-JSON messages are directed to a `$default` route that you configure.)

A *route* includes a *route key*, which is the value that is expected once a *route selection expression* is evaluated. The `routeSelectionExpression` is an attribute defined at the API level. It specifies a JSON property that is expected to be present in the message payload. For more information about route selection expressions, see [Route selection expressions](#apigateway-websocket-api-route-selection-expressions).

For example, if your JSON messages contain an `action` property and you want to perform different actions based on this property, your route selection expression might be `${request.body.action}`. Your routing table would specify which action to perform by matching the value of the `action` property against the custom route key values that you have defined in the table.

There are three predefined routes that can be used: `$connect`, `$disconnect`, and `$default`. In addition, you can create custom routes.
+ API Gateway calls the `$connect` route when a persistent connection between the client and a WebSocket API is being initiated.
+ API Gateway calls the `$disconnect` route when the client or the server disconnects from the API.
+ API Gateway calls a custom route after the route selection expression is evaluated against the message if a matching route is found; the match determines which integration is invoked.
+ API Gateway calls the `$default` route if the route selection expression cannot be evaluated against the message or if no matching route is found.

## Route selection expressions


A *route selection expression* is evaluated when the service is selecting the route to follow for an incoming message. The service uses the route whose `routeKey` exactly matches the evaluated value. If none match and a route with the `$default` route key exists, that route is selected. If no routes match the evaluated value and there is no `$default` route, the service returns an error. For WebSocket-based APIs, the expression should be of the form `$request.body.{path_to_body_element}`.

For example, suppose you are sending the following JSON message:

```
{
    "service" : "chat",
    "action" : "join",
    "data" : {
        "room" : "room1234"
   }
}
```

You might want to select your API's behavior based on the `action` property. In that case, you might define the following route selection expression:

```
$request.body.action
```

In this example, `request.body` refers to your message's JSON payload, and `.action` is a [JSONPath](https://goessner.net/articles/JsonPath/) expression. You can use any JSON path expression after `request.body`, but keep in mind that the result will be stringified. For example, if your JSONPath expression returns an array of two elements, that will be presented as the string `"[item1, item2]"`. For this reason, it's a good practice to have your expression evaluate to a value and not an array or an object.

You can simply use a static value, or you can use multiple variables. The following table shows examples and their evaluated results against the preceding payload.


| Expression | Evaluated result | Description | 
| --- | --- | --- | 
| \$1request.body.action | join | An unwrapped variable | 
| \$1\$1request.body.action\$1 | join | A wrapped variable | 
| \$1\$1request.body.service\$1/\$1\$1request.body.action\$1 | chat/join | Multiple variables with static values | 
| \$1\$1request.body.action\$1-\$1\$1request.body.invalidPath\$1  | join- | If the JSONPath is not found, the variable is resolved as "". | 
| action | action | Static value | 
| \$1\$1default | \$1default | Static value | 

The evaluated result is used to find a route. If there is a route with a matching route key, the route is selected to process the message. If no matching route is found, then API Gateway tries to find the `$default` route if available. If the `$default` route is not defined, then API Gateway returns an error.

## Set up routes for a WebSocket API in API Gateway
Set up WebSocket API routes

When you first create a new WebSocket API, there are three predefined routes: `$connect`, `$disconnect`, and `$default`. You can create them by using the console, API, or AWS CLI. If desired, you can create custom routes. For more information, see [Overview of WebSocket APIs in API Gateway](apigateway-websocket-api-overview.md).

**Note**  
In the CLI, you can create routes before or after you create integrations, and you can reuse the same integration for multiple routes.

### Create a route using the API Gateway console


**To create a route using the API Gateway console**

1. Sign in to the API Gateway console, choose the API, and choose **Routes**.

1. Choose **Create route**

1. For **Route key**, enter the route key name. You can create the predefined routes (`$connect`, `$disconnect`, and `$default`), or a custom route.
**Note**  
When you create a custom route, do not use the `$` prefix in the route key name. This prefix is reserved for predefined routes.

1. Select and configure the integration type for the route. For more information, see [Set up a WebSocket API integration request using the API Gateway console](apigateway-websocket-api-integration-requests.md#apigateway-websocket-api-integration-request-using-console).

### Create a route using the AWS CLI


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

```
aws apigatewayv2 --region us-east-1 create-route --api-id aabbccddee --route-key $default
```

The output will look like a following:

```
{
    "ApiKeyRequired": false,
    "AuthorizationType": "NONE",
    "RouteKey": "$default",
    "RouteId": "1122334"
}
```

### Specify route request settings for `$connect`


When you set up the `$connect` route for your API, the following optional settings are available to enable authorization for your API. For more information, see [The `$connect` route](apigateway-websocket-api-route-keys-connect-disconnect.md#apigateway-websocket-api-routes-about-connect).
+ **Authorization**: If no authorization is needed, you can specify `NONE`. Otherwise, you can specify: 
  + `AWS_IAM` to use standard AWS IAM policies to control access to your API. 
  + `CUSTOM` to implement authorization for an API by specifying a Lambda authorizer function that you have previously created. The authorizer can reside in your own AWS account or a different AWS account. For more information about Lambda authorizers, see [Use API Gateway Lambda authorizers](apigateway-use-lambda-authorizer.md).
**Note**  
In the API Gateway console, the `CUSTOM` setting is visible only after you have set up an authorizer function as described in [Configure a Lambda authorizer (console)](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-with-console).
**Important**  
The **Authorization** setting is applied to the entire API, not just the `$connect` route. The `$connect` route protects the other routes, because it is called on every connection.
+ **API key required**: You can optionally require an API key for an API's `$connect` route. You can use API keys together with usage plans to control and track access to your APIs. For more information, see [Usage plans and API keys for REST APIs in API Gateway](api-gateway-api-usage-plans.md).

### Set up the `$connect` route request using the API Gateway console


To set up the `$connect` route request for a WebSocket API using the API Gateway console:

1. Sign in to the API Gateway console, choose the API, and choose **Routes**.

1. Under **Routes**, choose `$connect`, or create a `$connect` route by following [Create a route using the API Gateway console](#apigateway-websocket-api-route-using-console).

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

1. For **Authorization**, select an authorization type.

1. To require an API for the `$connect` route, select **Require API key**.

1. Choose **Save changes**.

# Set up route responses for WebSocket APIs in API Gateway
Set up WebSocket API route responses

WebSocket routes can be configured for two-way or one-way communication. API Gateway will not pass the backend response through to the route response, unless you set up a route response. 

**Note**  
You can only define the `$default` route response for WebSocket APIs. You can use an integration response to manipulate the response from a backend service. For more information, see [Overview of integration responses](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-overview). 

You can configure route responses and response selection expressions by using the API Gateway console or the AWS CLI or an AWS SDK. 

For more information about route response selection expressions, see [Route response selection expressions](apigateway-websocket-api-selection-expressions.md#apigateway-websocket-api-route-response-selection-expressions).

**Topics**
+ [

## Set up a route response using the API Gateway console
](#apigateway-websocket-api-route-response-using-console)
+ [

## Set up a route response using the AWS CLI
](#apigateway-websocket-api-route-response-using-awscli)

## Set up a route response using the API Gateway console


After you have created a WebSocket API and attached a proxy Lambda function to the default route, you can set up route response using the API Gateway console:

1. Sign in to the API Gateway console, choose a WebSocket API with a proxy Lambda function integration on the `$default` route.

1. Under **Routes**, choose the `$default` route.

1. Choose **Enable two-way communication**. 

1. Choose **Deploy API**.

1. Deploy your API to a stage.

 Use the following [ wscat](https://www.npmjs.com/package/wscat) command to connect to your API. For more information about `wscat`, see [Use `wscat` to connect to a WebSocket API and send messages to it](apigateway-how-to-call-websocket-api-wscat.md). 

```
wscat -c wss://api-id.execute-api.us-east-2.amazonaws.com/test
```

 Press the enter button to call the default route. The body of your Lambda function should return.

## Set up a route response using the AWS CLI


The following [create-route-response](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route-response.html) command creates a route response for the `$default` route. You can identify the API ID and route ID by using the [get-apis](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-apis.html) and [get-routes](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-routes.html) commands.

```
aws apigatewayv2 create-route-response \
    --api-id aabbccddee \
    --route-id 1122334  \
    --route-response-key '$default'
```

The output will look like the following:

```
{
    "RouteResponseId": "abcdef",
    "RouteResponseKey": "$default"
}
```

# Set up a `$connect` route that requires a WebSocket subprotocol
Subprotocol support

Clients can use the `Sec-WebSocket-Protocol` field to request a [WebSocket subprotocol](https://datatracker.ietf.org/doc/html/rfc6455#page-12) during the connection to your WebSocket API. You can set up an integration for the `$connect` route to allow connections only if a client requests a subprotocol that your API supports.

The following example Lambda function returns the `Sec-WebSocket-Protocol` header to clients. The function establishes a connection to your API only if the client specifies the `myprotocol` subprotocol.

For an CloudFormation template that creates this example API and Lambda proxy integration, see [samples/ws-subprotocol.zip](samples/ws-subprotocol.zip).

```
export const handler = async (event) => {
    if (event.headers != undefined) {
        const headers = toLowerCaseProperties(event.headers);
        
        if (headers['sec-websocket-protocol'] != undefined) {
            const subprotocolHeader = headers['sec-websocket-protocol'];
            const subprotocols = subprotocolHeader.split(',');
            
            if (subprotocols.indexOf('myprotocol') >= 0) {
                const response = {
                    statusCode: 200,
                    headers: {
                        "Sec-WebSocket-Protocol" : "myprotocol"
                    }
                };
                return response;
            }
        }
    }
    
    const response = {
        statusCode: 400
    };
        
    return response;
};

function toLowerCaseProperties(obj) {
    var wrapper = {};
    for (var key in obj) {
        wrapper[key.toLowerCase()] = obj[key];
    }
    return wrapper;
}
```

You can use [https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat) to test that your API allows connections only if a client requests a subprotocol that your API supports. The following commands use the `-s` flag to specify subprotocols during the connection.

The following command attempts a connection with an unsupported subprotocol. Because the client specified the `chat1` subprotocol, the Lambda integration returns a 400 error, and the connection is unsuccessful.

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1
error: Unexpected server response: 400
```

The following command includes a supported subprotocol in the connection request. The Lambda integration allows the connection.

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1,myprotocol
connected (press CTRL+C to quit)
```

To learn more about invoking WebSocket APIs, see [Invoke WebSocket APIs](apigateway-how-to-call-websocket-api.md).

# Control and manage access to WebSocket APIs in API Gateway
Access control

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

You can use the following mechanisms for authentication and authorization:
+ **Standard AWS IAM roles and policies** offer flexible and robust access controls. You can use IAM roles and policies for controlling who can create and manage your APIs, as well as who can invoke them. For more information, see [Control access to WebSocket APIs with IAM authorization](apigateway-websocket-control-access-iam.md).
+ **IAM tags** can be used together with IAM policies to control access. For more information, see [Using tags to control access to API Gateway REST API resources](apigateway-tagging-iam-policy.md).
+ **Lambda authorizers** are Lambda functions that control access to APIs. For more information, see [Control access to WebSocket APIs with AWS Lambda REQUEST authorizers](apigateway-websocket-api-lambda-auth.md).

To improve your security posture, we recommend that you configure an authorizer for the `$connect` route on all your WebSocket APIs. You might need to do this to comply with various compliance frameworks. For more information, see [Amazon API Gateway controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html) in the *AWS Security Hub User Guide*.

**Topics**
+ [

# Control access to WebSocket APIs with IAM authorization
](apigateway-websocket-control-access-iam.md)
+ [

# Control access to WebSocket APIs with AWS Lambda REQUEST authorizers
](apigateway-websocket-api-lambda-auth.md)

# Control access to WebSocket APIs with IAM authorization


IAM authorization in WebSocket APIs is similar to that for [REST APIs](api-gateway-control-access-using-iam-policies-to-invoke-api.md), with the following exceptions:
+ The `execute-api` action supports `ManageConnections` in addition to existing actions (`Invoke`, `InvalidateCache`). `ManageConnections` controls access to the @connections API.
+ WebSocket routes use a different ARN format:

  ```
  arn:aws:execute-api:region:account-id:api-id/stage-name/route-key
  ```
+ The `@connections` API uses the same ARN format as REST APIs:

  ```
  arn:aws:execute-api:region:account-id:api-id/stage-name/POST/@connections
  ```

**Important**  
When you use [IAM authorization](#apigateway-websocket-control-access-iam), you must sign requests with [Signature Version 4 (SigV4)](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html).

For example, you could set up the following policy to the client. This example allows everyone to send a message (`Invoke`) for all routes except for a secret route in the `prod` stage and prevents everyone from sending a message back to connected clients (`ManageConnections`) for all stages.

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

****  

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

------

# Control access to WebSocket APIs with AWS Lambda REQUEST authorizers


A Lambda authorizer function in WebSocket APIs is similar to that for [REST APIs](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-lambda-function-create), with the following exceptions:
+  You can only use a Lambda authorizer function for the `$connect` route. 
+ You cannot use path variables (`event.pathParameters`), because the path is fixed.
+ `event.methodArn` is different from its REST API equivalent, because it has no HTTP method. In the case of `$connect`, `methodArn` ends with `"$connect"`:

  ```
  arn:aws:execute-api:region:account-id:api-id/stage-name/$connect
  ```
+ The context variables in `event.requestContext` are different from those for REST APIs.

 The following example shows an input to a `REQUEST` authorizer for a WebSocket API:

```
{
    "type": "REQUEST",
    "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/default/$connect",
    "headers": {
        "Connection": "upgrade",
        "content-length": "0",
        "HeaderAuth1": "headerValue1",
        "Host": "abcdef123.execute-api.us-east-1.amazonaws.com",
        "Sec-WebSocket-Extensions": "permessage-deflate; client_max_window_bits",
        "Sec-WebSocket-Key": "...",
        "Sec-WebSocket-Version": "13",
        "Upgrade": "websocket",
        "X-Amzn-Trace-Id": "...",
        "X-Forwarded-For": "...",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    },
    "multiValueHeaders": {
        "Connection": [
            "upgrade"
        ],
        "content-length": [
            "0"
        ],
        "HeaderAuth1": [
            "headerValue1"
        ],
        "Host": [
            "abcdef123.execute-api.us-east-1.amazonaws.com"
        ],
        "Sec-WebSocket-Extensions": [
            "permessage-deflate; client_max_window_bits"
        ],
        "Sec-WebSocket-Key": [
            "..."
        ],
        "Sec-WebSocket-Version": [
            "13"
        ],
        "Upgrade": [
            "websocket"
        ],
        "X-Amzn-Trace-Id": [
            "..."
        ],
        "X-Forwarded-For": [
            "..."
        ],
        "X-Forwarded-Port": [
            "443"
        ],
        "X-Forwarded-Proto": [
            "https"
        ]
    },
    "queryStringParameters": {
        "QueryString1": "queryValue1"
    },
    "multiValueQueryStringParameters": {
        "QueryString1": [
            "queryValue1"
        ]
    },
    "stageVariables": {},
    "requestContext": {
        "routeKey": "$connect",
        "eventType": "CONNECT",
        "extendedRequestId": "...",
        "requestTime": "19/Jan/2023:21:13:26 +0000",
        "messageDirection": "IN",
        "stage": "default",
        "connectedAt": 1674162806344,
        "requestTimeEpoch": 1674162806345,
        "identity": {
            "sourceIp": "..."
        },
        "requestId": "...",
        "domainName": "abcdef123.execute-api.us-east-1.amazonaws.com",
        "connectionId": "...",
        "apiId": "abcdef123"
    }
}
```

The following example Lambda authorizer function is a WebSocket version of the Lambda authorizer function for REST APIs in [Additional examples of Lambda authorizer functions](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-lambda-function-create):

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

```
   // A simple REQUEST authorizer example to demonstrate how to use request 
   // parameters to allow or deny a request. In this example, a request is  
   // authorized if the client-supplied HeaderAuth1 header and QueryString1 query parameter
   // in the request context match the specified values of
   // of 'headerValue1' and 'queryValue1' respectively.
            export const handler = function(event, context, callback) {
    console.log('Received event:', JSON.stringify(event, null, 2));

   // Retrieve request parameters from the Lambda function input:
   var headers = event.headers;
   var queryStringParameters = event.queryStringParameters;
   var stageVariables = event.stageVariables;
   var requestContext = event.requestContext;
       
   // Parse the input for the parameter values
   var tmp = event.methodArn.split(':');
   var apiGatewayArnTmp = tmp[5].split('/');
   var awsAccountId = tmp[4];
   var region = tmp[3];
   var ApiId = apiGatewayArnTmp[0];
   var stage = apiGatewayArnTmp[1];
   var route = apiGatewayArnTmp[2];
       
   // Perform authorization to return the Allow policy for correct parameters and 
   // the 'Unauthorized' error, otherwise.
   var authResponse = {};
   var condition = {};
    condition.IpAddress = {};
    
   if (headers.HeaderAuth1 === "headerValue1"
       && queryStringParameters.QueryString1 === "queryValue1") {
        callback(null, generateAllow('me', event.methodArn));
    }  else {
        callback(null, generateDeny('me', event.methodArn)); 
    }
}
    
// Helper function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
   // Required output:
   var authResponse = {};
    authResponse.principalId = principalId;
   if (effect && resource) {
       var policyDocument = {};
        policyDocument.Version = '2012-10-17		 	 	 '; // default version
       policyDocument.Statement = [];
       var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; // default action
       statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
   // Optional output with custom properties of the String, Number or Boolean type.
   authResponse.context = {
       "stringKey": "stringval",
       "numberKey": 123,
       "booleanKey": true
    };
   return authResponse;
}
    
var generateAllow = function(principalId, resource) {
   return generatePolicy(principalId, 'Allow', resource);
}
    
var generateDeny = function(principalId, resource) {
   return generatePolicy(principalId, 'Deny', resource);
}
```

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

```
# A simple REQUEST authorizer example to demonstrate how to use request
# parameters to allow or deny a request. In this example, a request is
# authorized if the client-supplied HeaderAuth1 header and QueryString1 query parameter
# in the request context match the specified values of
# of 'headerValue1' and 'queryValue1' respectively.

import json


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

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

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

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

    authResponse = {}
    condition = {}
    condition['IpAddress'] = {}

    if (headers['HeaderAuth1'] ==
            "headerValue1" and queryStringParameters["QueryString1"] == "queryValue1"):
        response = generateAllow('me', event['methodArn'])
        print('authorized')
        return json.loads(response)
    else:
        response = generateDeny('me', event['methodArn'])
        print('unauthorized')
        return json.loads(response)

    # Help function to generate IAM policy


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

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

    authResponse_JSON = json.dumps(authResponse)

    return authResponse_JSON


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


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

------

To configure the preceding Lambda function as a `REQUEST` authorizer function for a WebSocket API, follow the same procedure as for [REST APIs](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-with-console).

To configure the `$connect` route to use this Lambda authorizer in the console, select or create the `$connect` route. In the **Route request settings** section, choose **Edit**. Select your authorizer in the **Authorization** dropdown menu, and then choose **Save changes**.

To test the authorizer, you need to create a new connection. Changing authorizer in `$connect` doesn't affect the already connected client. When you connect to your WebSocket API, you need to provide values for any configured identity sources. For example, you can connect by sending a valid query string and header using `wscat` as in the following example:

```
wscat -c 'wss://myapi.execute-api.us-east-1.amazonaws.com/beta?QueryString1=queryValue1' -H HeaderAuth1:headerValue1
```

If you attempt to connect without a valid identity value, you'll receive a `401` response:

```
wscat -c wss://myapi.execute-api.us-east-1.amazonaws.com/beta
error: Unexpected server response: 401
```

# Integrations for WebSocket APIs in API Gateway
Integrations

After setting up an API route, you must integrate it with an endpoint in the backend. A backend endpoint is also referred to as an integration endpoint and can be a Lambda function, an HTTP endpoint, or an AWS service action. The API integration has an integration request and an integration response.

In this section, you can learn how to set up integration requests and integration responses for your WebSocket API. 

**Topics**
+ [

# Set up a WebSocket API integration request in API Gateway
](apigateway-websocket-api-integration-requests.md)
+ [

# Set up a WebSocket API integration response in API Gateway
](apigateway-websocket-api-integration-responses.md)

# Set up a WebSocket API integration request in API Gateway
Integration request

Setting up an integration request involves the following:
+ Choosing a route key to integrate to the backend.
+ Specifying the backend endpoint to invoke. WebSocket APIs support the following integration types:
  + `AWS_PROXY`
  + `AWS`
  + `HTTP_PROXY`
  + `HTTP`
  + `MOCK`

  For more information about integration types, see [IntegrationType](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationtype) in the API Gateway V2 REST API.
+ Configuring how to transform the route request data, if necessary, into integration request data by specifying one or more request templates.

## Set up a WebSocket API integration request using the API Gateway console


**To add an integration request to a route in a WebSocket API using the API Gateway console**

1. Sign in to the API Gateway console, choose the API, and choose **Routes**.

1. Under **Routes**, choose the route.

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

1. For **Integration type**, select one of the following:
   + Choose **Lambda function** only if your API will be integrated with an AWS Lambda function that you have already created in this account or in another account.

     To create a new Lambda function in AWS Lambda, to set a resource permission on the Lambda function, or to perform any other Lambda service actions, choose **AWS Service** instead.
   + Choose **HTTP** if your API will be integrated with an existing HTTP endpoint. For more information, see [HTTP integrations for REST APIs in API Gateway](setup-http-integrations.md).
   + Choose **Mock** if you want to generate API responses from API Gateway directly, without the need for an integration backend. For more information, see [Mock integrations for REST APIs in API Gateway](how-to-mock-integration.md).
   + Choose **AWS service** if your API will be integrated with an AWS service.
   + Choose **VPC link** if your API will use a `VpcLink` as a private integration endpoint. For more information, see [Set up a private integration](set-up-private-integration.md).

1. If you chose **Lambda function**, do the following:

   1. For **Use Lambda proxy integration**, choose the check box if you intend to use [Lambda proxy integration](set-up-lambda-proxy-integrations.md#api-gateway-create-api-as-simple-proxy) or [cross-account Lambda proxy integration](apigateway-cross-account-lambda-integrations.md).

   1. For **Lambda function**, specify the function in one of the following ways:
      + If your Lambda function is in the same account, enter the function name and then select the function from the dropdown list.
**Note**  
The function name can optionally include its alias or version specification, as in `HelloWorld`, `HelloWorld:1`, or `HelloWorld:alpha`.
      + If the function is in a different account, enter the ARN for the function.

   1. To use the default timeout value of 29 seconds, keep **Default timeout** turned on. To set a custom timeout, choose **Default timeout** and enter a timeout value between `50` and `29000` milliseconds.

1. If you chose **HTTP**, follow the instructions in step 4 of [Set up an API integration request using the API Gateway console](how-to-method-settings-console.md).

1. If you chose **Mock**, proceed to the **Request Templates** step.

1. If you chose **AWS service**, follow the instructions in step 6 of [Set up an API integration request using the API Gateway console](how-to-method-settings-console.md).

1. If you chose **VPC link**, do the following:

   1. For **VPC proxy integration**, choose the check box if you want your requests to be proxied to your `VPCLink`'s endpoint.

   1. For **HTTP method**, choose the HTTP method type that most closely matches the method in the HTTP backend.

   1. From the **VPC link** dropdown list, select a VPC link. You can select `[Use Stage Variables]` and enter **\$1\$1stageVariables.vpcLinkId\$1** in the text box below the list.

      You can define the `vpcLinkId` stage variable after deploying the API to a stage and set its value to the ID of the `VpcLink`.

   1. For **Endpoint URL**, enter the URL of the HTTP backend you want this integration to use.

   1. To use the default timeout value of 29 seconds, keep **Default timeout** turned on. To set a custom timeout, choose **Default timeout** and enter a timeout value between `50` and `29000` milliseconds.

1. Choose **Save changes**.

1. Under **Request templates**, do the following:

   1. To enter a **Template selection expression**, under **Request templates**, choose **Edit**.

   1. Enter a **Template selection expression**. Use an expression that API Gateway looks for in the message payload. If it is found, it is evaluated, and the result is a template key value that is used to select the data mapping template to be applied to the data in the message payload. You create the data mapping template in the next step. Choose **Edit** to save your changes.

   1. Choose **Create template** to create the data mapping template. For **Template key**, enter a template key value that is used to select the data mapping template to be applied to the data in the message payload. Then, enter a mapping template. Choose **Create template**.

      For information about template selection expressions, see [Template selection expressions](websocket-api-data-transformations.md#apigateway-websocket-api-template-selection-expressions).

## Set up an integration request using the AWS CLI


You can set up an integration request for a route in a WebSocket API by using the AWS CLI as in the following example, which creates a mock integration:

1. Create a file named `integration-params.json`, with the following contents:

   ```
   {"PassthroughBehavior": "WHEN_NO_MATCH", "TimeoutInMillis": 29000, "ConnectionType": "INTERNET", "RequestTemplates": {"application/json": "{\"statusCode\":200}"}, "IntegrationType": "MOCK"}
   ```

1. Use the following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command to create the mock integration.

   ```
   aws apigatewayv2 --region us-east-1 create-integration --api-id aabbccddee --cli-input-json file://integration-params.json
   ```

   The output will look like the following:

   ```
   {
       "PassthroughBehavior": "WHEN_NO_MATCH",
       "TimeoutInMillis": 29000,
       "ConnectionType": "INTERNET",
       "IntegrationResponseSelectionExpression": "${response.statuscode}",
       "RequestTemplates": {
           "application/json": "{\"statusCode\":200}"
       },
       "IntegrationId": "0abcdef",
       "IntegrationType": "MOCK"
   }
   ```

Alternatively, you can set up an integration request for a proxy integration by using the AWS CLI.

1. Create a Lambda function in the Lambda console and give it a basic Lambda execution role.

1. Use the following [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) command to create the integration.

   ```
   aws apigatewayv2 create-integration --api-id aabbccddee --integration-type AWS_PROXY --integration-method POST --integration-uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123412341234:function:simpleproxy-echo-e2e/invocations
   ```

The output will look like the following:

```
{
    "PassthroughBehavior": "WHEN_NO_MATCH",
    "IntegrationMethod": "POST",
    "TimeoutInMillis": 29000,
    "ConnectionType": "INTERNET",
    "IntegrationUri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123412341234:function:simpleproxy-echo-e2e/invocations",
    "IntegrationId": "abcdefg",
    "IntegrationType": "AWS_PROXY"
}
```

## Input format of a Lambda function for proxy integration for WebSocket APIs


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

------
#### [ Input from the \$1connect route ]

```
{
    headers: {
      Host: 'abcd123.execute-api.us-east-1.amazonaws.com',
      'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
      'Sec-WebSocket-Key': '...',
      'Sec-WebSocket-Version': '13',
      'X-Amzn-Trace-Id': '...',
      'X-Forwarded-For': '192.0.2.1',
      'X-Forwarded-Port': '443',
      'X-Forwarded-Proto': 'https'
    },
    multiValueHeaders: {
      Host: [ 'abcd123.execute-api.us-east-1.amazonaws.com' ],
      'Sec-WebSocket-Extensions': [ 'permessage-deflate; client_max_window_bits' ],
      'Sec-WebSocket-Key': [ '...' ],
      'Sec-WebSocket-Version': [ '13' ],
      'X-Amzn-Trace-Id': [ '...' ],
      'X-Forwarded-For': [ '192.0.2.1' ],
      'X-Forwarded-Port': [ '443' ],
      'X-Forwarded-Proto': [ 'https' ]
    },
    requestContext: {
      routeKey: '$connect',
      eventType: 'CONNECT',
      extendedRequestId: 'ABCD1234=',
      requestTime: '09/Feb/2024:18:11:43 +0000',
      messageDirection: 'IN',
      stage: 'prod',
      connectedAt: 1707502303419,
      requestTimeEpoch: 1707502303420,
      identity: { sourceIp: '192.0.2.1' },
      requestId: 'ABCD1234=',
      domainName: 'abcd1234.execute-api.us-east-1.amazonaws.com',
      connectionId: 'AAAA1234=',
      apiId: 'abcd1234'
    },
    isBase64Encoded: false
  }
```

------
#### [ Input from the \$1disconnect route ]

```
{
    headers: {
      Host: 'abcd1234.execute-api.us-east-1.amazonaws.com',
      'x-api-key': '',
      'X-Forwarded-For': '',
      'x-restapi': ''
    },
    multiValueHeaders: {
      Host: [ 'abcd1234.execute-api.us-east-1.amazonaws.com' ],
      'x-api-key': [ '' ],
      'X-Forwarded-For': [ '' ],
      'x-restapi': [ '' ]
    },
    requestContext: {
      routeKey: '$disconnect',
      disconnectStatusCode: 1005,
      eventType: 'DISCONNECT',
      extendedRequestId: 'ABCD1234=',
      requestTime: '09/Feb/2024:18:23:28 +0000',
      messageDirection: 'IN',
      disconnectReason: 'Client-side close frame status not set',
      stage: 'prod',
      connectedAt: 1707503007396,
      requestTimeEpoch: 1707503008941,
      identity: { sourceIp: '192.0.2.1' },
      requestId: 'ABCD1234=',
      domainName: 'abcd1234.execute-api.us-east-1.amazonaws.com',
      connectionId: 'AAAA1234=',
      apiId: 'abcd1234'
    },
    isBase64Encoded: false
  }
```

------

# Set up a WebSocket API integration response in API Gateway
Integration responses

The following section provides a brief overview of integration responses for WebSocket API and how to set up an integration response for a WebSocket API. 

**Topics**
+ [

## Overview of integration responses
](#apigateway-websocket-api-integration-response-overview)
+ [

## Integration responses for two-way communication
](#apigateway-websocket-api-integration-response-for-two-way-communication)
+ [

## Set up an integration response using the API Gateway console
](#apigateway-websocket-api-integration-response-using-console)
+ [

## Set up an integration response using the AWS CLI
](#apigateway-websocket-api-integration-response-using-awscli)

## Overview of integration responses


API Gateway's integration response is a way of modeling and manipulating the response from a backend service. There are some differences in setup of a REST API versus a WebSocket API integration response, but conceptually the behavior is the same.

WebSocket routes can be configured for two-way or one-way communication.
+ When a route is configured for two-way communication, an integration response allows you to configure transformations on the returned message payload, similar to integration responses for REST APIs.
+ If a route is configured for one-way communication, then regardless of any integration response configuration, no response will be returned over the WebSocket channel after the message is processed.

 API Gateway will not pass the backend response through to the route response, unless you set up a route response. To learn about setting up a route response, see [Set up route responses for WebSocket APIs in API Gateway](apigateway-websocket-api-route-response.md).

## Integration responses for two-way communication


Integrations can be divided into *proxy* integrations and *non-proxy* integrations.

**Important**  
For *proxy integrations*, API Gateway automatically passes the backend output to the caller as the complete payload. There is no integration response.

For *non-proxy integrations*, you must set up at least one integration response:
+ Ideally, one of your integration responses should act as a catch-all when no explicit choice can be made. This default case is represented by setting an integration response key of `$default`.
+ In all other cases, the integration response key functions as a regular expression. It should follow a format of `"/expression/"`.

For non-proxy HTTP integrations:
+ API Gateway will attempt to match the HTTP status code of the backend response. The integration response key will function as a regular expression in this case. If a match cannot be found, then `$default` is chosen as the integration response.
+ The template selection expression, as described above, functions identically. For example:
  + `/2\d\d/`: Receive and transform successful responses
  + `/4\d\d/`: Receive and transform bad request errors
  + `$default`: Receive and transform all unexpected responses

For more information about template selection expressions, see [Template selection expressions](websocket-api-data-transformations.md#apigateway-websocket-api-template-selection-expressions).

## Set up an integration response using the API Gateway console


To set up a route integration response for a WebSocket API using the API Gateway console:

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

1.  Choose your WebSocket API and choose your route.

1. Choose the **Integration request** tab, and then in the **Integration response settings** section, choose **Create integration response**.

1. For **Response key**, enter a value that will be found in the response key in the outgoing message after evaluating the response selection expression. For instance, you can enter **/4\$1d\$1d/** to receive and transform bad request errors or enter **\$1default** to receive and transform all responses that match the template selection expression. 

1. For **Template selection expression**, enter a selection expression to evaluate the outgoing message.

1. Choose **Create response**.

1. You can also define a mapping template to configure transformations of your returned message payload. Choose **Create template**.

1. Enter a key name. If you are choosing the default template selection expression, enter **\$1\$1default**.

1. For **Response template**, enter your mapping template in the code editor.

1. Choose **Create template**.

1. Choose **Deploy API** to deploy your API.

 Use the following [ wscat](https://www.npmjs.com/package/wscat) command to connect to your API. For more information about `wscat`, see [Use `wscat` to connect to a WebSocket API and send messages to it](apigateway-how-to-call-websocket-api-wscat.md). 

```
wscat -c wss://api-id.execute-api.us-east-2.amazonaws.com/test
```

 When you call your route, the returned message payload should return. 

## Set up an integration response using the AWS CLI


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

```
aws apigatewayv2 create-integration-response \
    --api-id vaz7da96z6 \
    --integration-id a1b2c3 \
    --integration-response-key '$default'
```

# Request validation for WebSocket APIs in API Gateway
Request validation

You can configure API Gateway to perform validation on a route request before proceeding with the integration request. If the validation fails, API Gateway fails the request without calling your backend, sends a "Bad request body" gateway response to the client, and publishes the validation results in CloudWatch Logs. Using validation this way reduces unnecessary calls to your API backend.

## Model selection expressions


You can use a model selection expression to dynamically validate requests within the same route. Model validation occurs if you provide a model selection expression for either proxy or non-proxy integrations. You might need to define the `$default` model as a fallback when no matching model is found. If there is no matching model and `$default` isn't defined, the validation fails. The selection expression looks like `Route.ModelSelectionExpression` and evaluates to the key for `Route.RequestModels`.

When you define a route for a WebSocket API, you can optionally specify a *model selection expression*. This expression is evaluated to select the model to be used for body validation when a request is received. The expression evaluates to one of the entries in a route's [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes.html#apis-apiid-routes-prop-route-requestmodels](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes.html#apis-apiid-routes-prop-route-requestmodels).

A model is expressed as a [JSON schema](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04) and describes the data structure of the request body. The nature of this selection expression enables you to dynamically choose the model to validate against at runtime for a particular route. For information about how to create a model, see [Data models for REST APIs](models-mappings-models.md). 

## Set up request validation using the API Gateway console


The following example shows you how to set up request validation on a route.

 First, you create a model, and then you create a route. Next, you configure request validation on the route you just created. Lastly, you deploy and test your API. To complete this tutorial, you need a WebSocket API with `$request.body.action` as the route selection expression and an integration endpoint for your new route.

You also need `wscat` to connect to your API. For more information, see [Use `wscat` to connect to a WebSocket API and send messages to it](apigateway-how-to-call-websocket-api-wscat.md).

**To create a model**

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

1. Choose a WebSocket API.

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

1. Choose **Create model**.

1. For **Name**, enter **emailModel**.

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

1. For **Model schema**, enter the following model:

   ```
   {
       "$schema": "http://json-schema.org/draft-04/schema#",
       "type" : "object",
       "required" : [ "address"],
       "properties" : {
           "address": {
               "type": "string"
           }
       }
   }
   ```

   This model requires that the request contains an email address.

1. Choose **Save**.

In this step, you create a route for your WebSocket API.

**To create a route**

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

1. Choose **Create route**.

1. For **Route key**, enter **sendMessage**.

1. Choose an integration type and specify an integration endpoint. For more information see [Integrations for WebSocket APIs in API Gateway](apigateway-websocket-api-integrations.md).

1. Choose **Create route**.

In this step, you set up request validation for the `sendMessage` route.

**To set up request validation**

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

1. For **Model selection expression**, enter **\$1\$1request.body.messageType\$1**.

   API Gateway uses the `messageType` property to validate the incoming request.

1. Choose **Add request model**.

1. For **Model key**, enter **email**.

1. For **Model**, choose **emailModel**.

   API Gateway validates incoming messages with the `messageType` property set to `email` against this model.
**Note**  
If API Gateway can't match the model selection expression to a model key, then it selects the `$default` model. If there is no `$default` model, then the validation fails. For production APIs, we recommend that you create a `$default` model.

1. Choose **Save changes**.

In this step, you deploy and test your API.

**To deploy and test your API**

1. Choose **Deploy API**.

1. Choose the desired stage from the dropdown list or enter the name of a new stage.

1. Choose **Deploy**.

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

1. Copy your API's WebSocket URL. The URL should look like `wss://abcdef123.execute-api.us-east-2.amazonaws.com/production`.

1. Open a new terminal and run the **wscat** command with the following parameters.

   ```
   wscat -c wss://abcdef123.execute-api.us-west-2.amazonaws.com/production
   ```

   ```
   Connected (press CTRL+C to quit)
   ```

1. Use the following command to test your API.

   ```
   {"action": "sendMessage", "messageType": "email"}
   ```

   ```
   {"message": "Invalid request body", "connectionId":"ABCD1=234", "requestId":"EFGH="}
   ```

   API Gateway will fail the request.

   Use the next command to send a valid request to your API.

   ```
   {"action": "sendMessage", "messageType": "email", "address": "mary_major@example.com"}
   ```

# Data transformations for WebSocket APIs in API Gateway
Data transformations

In API Gateway, a WebSocket API's method request can take a payload in a different format from the corresponding integration request payload, as required in the backend. Similarly, the backend may return an integration response payload different from the method response payload, as expected by the frontend. 

API Gateway lets you use mapping template transformations to map the payload from a method request to the corresponding integration request and from an integration response to the corresponding method response. You create a mapping template and You specify a template selection expression to determine which template to use to perform the necessary data transformations.

You can use data mappings to map data from a [route request](api-gateway-basic-concept.md#apigateway-definition-route-request) to a backend integration. To learn more, see [Set up data mapping for WebSocket APIs in API Gateway](websocket-api-data-mapping.md).

## Mapping templates and models


 A *mapping template* is a script expressed in [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) and applied to the payload using [JSONPath expressions](https://goessner.net/articles/JsonPath/). For more information about API Gateway mapping templates, see [Mapping template transformations for REST APIs in API Gateway](models-mappings.md).

The payload can have a *data model* according to the [JSON schema draft 4](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04). You do not have to define a model to create a mapping template. However, a model can help you create a template because API Gateway generates a template blueprint based on a provided model. For more information about API Gateway models, see [Data models for REST APIs](models-mappings-models.md).

## Template selection expressions


To transform a payload with a mapping template, you specify a WebSocket API template selection expression in an [integration request](apigateway-websocket-api-integration-requests.md) or [integration response](apigateway-websocket-api-integration-responses.md). This expression is evaluated to determine the input or output template (if any) to use to transform either the request body into the integration request body (via an input template) or the integration response body to the route response body (via an output template).

`Integration.TemplateSelectionExpression` supports `${request.body.jsonPath}` and static values.

`IntegrationResponse.TemplateSelectionExpression` supports `${request.body.jsonPath}`, `${integration.response.statuscode}`, `${integration.response.header.headerName}`, `${integration.response.multivalueheader.headerName}`, and static values.

## Integration response selection expressions


When you [set up an integration response](apigateway-websocket-api-integration-responses.md) for a WebSocket API, you can optionally specify an integration response selection expression. This expression determines what `[https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid-integrationresponses-integrationresponseid.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid-integrationresponses-integrationresponseid.html)` should be selected when an integration returns. The value of this expression is currently restricted by API Gateway, as defined below. Realize that this expression is only relevant for *non-proxy integrations*; a proxy integration simply passes the response payload back to the caller without modeling or modification.

Unlike the other preceding selection expressions, this expression currently supports a *pattern-matching* format. The expression should be wrapped with forward slashes.

Currently the value is fixed depending on the `[https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationtype](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationtype)`:
+ For Lambda-based integrations, it is `$integration.response.body.errorMessage`.
+ For `HTTP` and `MOCK` integrations, it is `$integration.response.statuscode`.
+ For `HTTP_PROXY` and `AWS_PROXY`, the expression isn't utilized because you're requesting that the payload pass through to the caller.

# Set up data mapping for WebSocket APIs in API Gateway
Data mapping

*Data mapping* enables you to map data from a [route request](api-gateway-basic-concept.md#apigateway-definition-route-request) to a backend integration.

**Note**  
Data mapping for WebSocket APIs isn't supported in the AWS Management Console. You must use the AWS CLI, AWS CloudFormation, or an SDK to configure data mapping.

**Topics**
+ [

## Map route request data to integration request parameters
](#websocket-mapping-request-parameters)
+ [

## Examples
](#websocket-data-mapping-examples)

## Map route request data to integration request parameters


Integration request parameters can be mapped from any defined route request parameters, the request body, [`context` or ](api-gateway-mapping-template-reference.md#context-variable-reference) [`stage`](api-gateway-mapping-template-reference.md#stagevariables-template-reference) variables, and static values.

The following table shows integration request data mapping expressions. In the table, *`PARAM_NAME`* is the name of a route request parameter of the given parameter type. It must match the regular expression `'^[a-zA-Z0-9._$-]+$]'`. *JSONPath\$1EXPRESSION* is a JSONPath expression for a JSON field of the request body.


| Mapped data source | Mapping expression | 
| --- | --- | 
| Request query string (supported only for the \$1connect route) | route.request.querystring.PARAM\$1NAME | 
| Request header (supported only for the \$1connect route) | route.request.header.PARAM\$1NAME | 
| Multi-value request query string (supported only for the \$1connect route) | route.request.multivaluequerystring.PARAM\$1NAME | 
| Multi-value request header (supported only for the \$1connect route) | route.request.multivalueheader.PARAM\$1NAME | 
| Request body | route.request.body.JSONPath\$1EXPRESSION | 
| Stage variables | stageVariables.VARIABLE\$1NAME | 
| Context variables | context.VARIABLE\$1NAME that must be one of the [supported context variables](api-gateway-mapping-template-reference.md#context-variable-reference). | 
| Static value | 'STATIC\$1VALUE'. The STATIC\$1VALUE is a string literal and must be enclosed in single quotes. | 

When you create a data mapping, using the AWS CLI make sure to follow the correct format for using literals with strings in the AWS CLI. For more information, see [Using quotation marks and literals with strings in the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-quoting-strings.html) in the *AWS Command Line Interface User Guide*.

## Examples


The following AWS CLI examples configure data mappings. For an example CloudFormation template, see [samples/websocket-data-mapping.zip](samples/websocket-data-mapping.zip).

### Map a client's connectionId to a header in an integration request


The following [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-integration.html) command maps a client's `connectionId` to a `connectionId` header in the request to a backend integration:

```
aws apigatewayv2 update-integration \
    --integration-id abc123 \
    --api-id a1b2c3d4 \ 
    --request-parameters 'integration.request.header.connectionId'='context.connectionId'
```

### Map a query string parameter to a header in an integration request


The following example maps an `authToken` query string parameter to an `authToken` header in the integration request.

1. Use the following [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) command to add the `authToken` query string parameter to the route's request parameters.

   ```
   aws apigatewayv2 update-route --route-id 0abcdef \
       --api-id a1b2c3d4 \
       --request-parameters '{"route.request.querystring.authToken": {"Required": false}}'
   ```

1.  Use the following [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-integration.html) command to map the query string parameter to the `authToken` header in the request to the backend integration.

   ```
   aws apigatewayv2 update-integration \
       --integration-id abc123 \
       --api-id a1b2c3d4 \
       --request-parameters 'integration.request.header.authToken'='route.request.querystring.authToken'
   ```

1. (Optional) If necessary, use the following [delete-route-request-parameter](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/delete-route-request-parameter.html) to delete the `authToken` query string parameter from the route's request parameters.

   ```
   aws apigatewayv2 delete-route-request-parameter \
       --route-id 0abcdef \
       --api-id a1b2c3d4 \
       --request-parameter-key 'route.request.querystring.authToken'
   ```

# WebSocket API mapping template reference for API Gateway
WebSocket mapping template reference

This section summarizes the set of variables that are currently supported for WebSocket APIs in API Gateway.


| Parameter | Description | 
| --- | --- | 
| \$1context.connectionId |  A unique ID for the connection that can be used to make a callback to the client.  | 
| \$1context.connectedAt |  The [Epoch](https://en.wikipedia.org/wiki/Unix_time)-formatted connection time.  | 
| \$1context.domainName |  A domain name for the WebSocket API. This can be used to make a callback to the client (instead of a hard-coded value).  | 
| \$1context.eventType |  The event type: `CONNECT`, `MESSAGE`, or `DISCONNECT`.  | 
| \$1context.messageId |  A unique server-side ID for a message. Available only when the `$context.eventType` is `MESSAGE`.  | 
| \$1context.routeKey |  The selected route key.  | 
| \$1context.requestId |  Same as `$context.extendedRequestId`.  | 
| \$1context.extendedRequestId | An automatically generated ID for the API call, which contains more useful information for debugging/troubleshooting. | 
| \$1context.apiId |  The identifier API Gateway assigns to your API.  | 
| \$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) Lambda function.  | 
| \$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.  | 
| \$1context.error.messageString | The quoted value of \$1context.error.message, namely "\$1context.error.message". | 
| \$1context.error.validationErrorString |  A string containing a detailed validation error message.  | 
| \$1context.identity.accountId |  The AWS account ID associated with the request.  | 
| \$1context.identity.apiKey |  The API owner key associated with key-enabled API request.  | 
| \$1context.identity.apiKeyId | The API key ID associated with the key-enabled API request | 
| \$1context.identity.caller |  The principal identifier of the caller making the request.  | 
| \$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.sourceIp |  The source IP address of the immediate TCP connection making the request to API Gateway endpoint.  | 
| \$1context.identity.user |  The principal identifier of the user making the request.  | 
| \$1context.identity.userAgent |  The User Agent of the API caller.  | 
| \$1context.identity.userArn |  The Amazon Resource Name (ARN) of the effective user identified after authentication.  | 
| \$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.stage |  The deployment stage of the API call (for example, Beta or Prod).  | 
| \$1context.status |  The response status.  | 
| \$1input.body | Returns the raw payload as a string. | 
| \$1input.json(x) | This function evaluates a JSONPath expression and returns the results as a JSON string. For example, `$input.json('$.pets')` will return 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.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').count()` would return `"3"`. For more information about JSONPath, see [JSONPath](http://goessner.net/articles/JsonPath/) or [JSONPath for Java](https://github.com/jayway/JsonPath). | 
| \$1stageVariables.<variable\$1name> |  *<variable\$1name>* represents a stage variable name.  | 
| \$1stageVariables['<variable\$1name>'] |  *<variable\$1name>* represents any stage variable name.  | 
| \$1\$1stageVariables['<variable\$1name>']\$1 |  *<variable\$1name>* represents any stage variable name.  | 
| \$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> $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. | 

# Binary media types for WebSocket APIs in API Gateway
Binary media types

API Gateway WebSocket APIs don't currently support binary frames in incoming message payloads. If a client app sends a binary frame, API Gateway rejects it and disconnects the client with code 1003.

There is a workaround for this behavior. If the client sends a text-encoded binary data (e.g., base64) as a text frame, you can set the integration's `contentHandlingStrategy` property to `CONVERT_TO_BINARY` to convert the payload from base64-encoded string to binary. 

To return a route response for a binary payload in non-proxy integrations, you can set the integration response's `contentHandlingStrategy` property to `CONVERT_TO_TEXT` to convert the payload from binary to base64-encoded string.

# Invoke WebSocket APIs
Invoke

After you've deployed your WebSocket API, client applications can connect to it and send messages to it—and your backend service can send messages to connected client applications:
+ You can use `wscat` to connect to your WebSocket API and send messages to it to simulate client behavior. See [Use `wscat` to connect to a WebSocket API and send messages to it](apigateway-how-to-call-websocket-api-wscat.md).
+ You can use the @connections API from your backend service to send a callback message to a connected client, get connection information, or disconnect the client. See [Use `@connections` commands in your backend service](apigateway-how-to-call-websocket-api-connections.md).
+ A client application can use its own WebSocket library to invoke your WebSocket API.

# Use `wscat` to connect to a WebSocket API and send messages to it


The `[wscat](https://www.npmjs.com/package/wscat)` utility is a convenient tool for testing a WebSocket API that you have created and deployed in API Gateway. You can install and use `wscat` as follows:

1. Download `wscat` from [https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat).

1. Install `wscat` by running the following command:

   ```
   npm install -g wscat
   ```

1. To connect to your API, run the `wscat` command as shown in the following example. Note that this example assumes that the `Authorization` setting is `NONE`.

   ```
   wscat -c wss://aabbccddee.execute-api.us-east-1.amazonaws.com/test/
   ```

   You need to replace `aabbccddee` with the actual API ID, which is displayed in the API Gateway console or returned by the AWS CLI [https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) command.

   In addition, if your API is in a Region other than `us-east-1`, you need to substitute the correct Region.

1. To test your API, enter a message such as the following while connected:

   ```
   {"{jsonpath-expression}":"{route-key}"}
   ```

   where *\$1jsonpath-expression\$1* is a JSONPath expression and *\$1route-key\$1* is a route key for the API. For example:

   ```
   {"action":"action1"}
   {"message":"test response body"}
   ```

   For more information about JSONPath, see [JSONPath](https://goessner.net/articles/JsonPath/) or [JSONPath for Java](https://github.com/json-path/JsonPath).

1. To disconnect from your API, enter `ctrl-C`.

# Use `@connections` commands in your backend service


Your backend service can use the following WebSocket connection HTTP requests to send a callback message to a connected client, get connection information, or disconnect the client.

**Important**  
These requests use [IAM authorization](apigateway-websocket-control-access-iam.md), so you must sign them with [Signature Version 4 (SigV4)](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html). To do this, you can use the API Gateway Management API. For more information, see [ApiGatewayManagementApi](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigatewaymanagementapi.html).

In the following command, you need to replace `{api-id}` with the actual API ID, which is displayed in the API Gateway console or returned by the AWS CLI [create-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) command. You must establish the connection before using this command. 

To send a callback message to the client, use:

```
POST https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

You can test this request by using `[Postman](https://www.postman.com/)` or by calling `[awscurl](https://github.com/okigan/awscurl)` as in the following example:

```
awscurl --service execute-api -X POST -d "hello world" https://{prefix}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

You need to URL-encode the command as in the following example:

```
awscurl --service execute-api -X POST -d "hello world" https://aabbccddee.execute-api.us-east-1.amazonaws.com/prod/%40connections/R0oXAdfD0kwCH6w%3D
```

To get the latest connection status of the client, use:

```
GET https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

To disconnect the client, use:

```
DELETE https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

You can dynamically build a callback URL by using the `$context` variables in your integration. For example, if you use Lambda proxy integration with a `Node.js` Lambda function, you can build the URL and send a message to a connected client as follows:

```
import {
  ApiGatewayManagementApiClient,
  PostToConnectionCommand,
} from "@aws-sdk/client-apigatewaymanagementapi";

export const handler = async (event) => {
  const domain = event.requestContext.domainName;
  const stage = event.requestContext.stage;
  const connectionId = event.requestContext.connectionId;
  const callbackUrl = `https://${domain}/${stage}`;
  const client = new ApiGatewayManagementApiClient({ endpoint: callbackUrl });

  const requestParams = {
    ConnectionId: connectionId,
    Data: "Hello!",
  };

  const command = new PostToConnectionCommand(requestParams);

  try {
    await client.send(command);
  } catch (error) {
    console.log(error);
  }

  return {
    statusCode: 200,
  };
};
```

If you use a custom domain name for your WebSocket API, remove the `stage` variable from your function code.

When sending a callback message, your Lambda function must have permission to call the API Gateway Management API. You might receive an error that contains `GoneException` if you post a message before the connection is established, or after the client has disconnected. 

# Publish WebSocket APIs for customers to invoke
Publish

Simply creating and developing an API Gateway API doesn't automatically make it callable by your users. To make it callable, you must deploy your API to a stage. In addition, you might want to customize the URL that your users will use to access your API. You can give it a domain that is consistent with your brand or is more memorable than the default URL for your API.

In this section, you can learn how to deploy your API and customize the URL that you provide to users to access it. 

**Note**  
To augment the security of your API Gateway APIs, the `execute-api.{region}.amazonaws.com` domain is registered in the [Public Suffix List (PSL)](https://publicsuffix.org/). For further security, we recommend that you use cookies with a `__Host-` prefix if you ever need to set sensitive cookies in the default domain name for your API Gateway APIs. This practice will help to defend your domain against cross-site request forgery attempts (CSRF). For more information see the [Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes) page in the Mozilla Developer Network.

**Topics**
+ [

# Create stages for WebSocket APIs in API Gateway
](websocket-api-stages.md)
+ [

# Deploy WebSocket APIs in API Gateway
](apigateway-set-up-websocket-deployment.md)
+ [

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

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

# Create stages for WebSocket APIs in API Gateway
Stages

An API stage is a logical reference to a lifecycle state of your API (for example, `dev`, `prod`, `beta`, or `v2`). API stages are identified by their API ID and stage name, and they're included in the URL you use to invoke the API. Each stage is a named reference to a deployment of the API and is made available for client applications to call.

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

## Stage variables


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

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

**Note**  
Stage variables are not intended to be used for sensitive data, such as credentials. To pass sensitive data to integrations, use an AWS Lambda authorizer. You can pass sensitive data to integrations in the output of the Lambda authorizer. To learn more, see [Lambda authorizer response format](http-api-lambda-authorizer.md#http-api-lambda-authorizer.payload-format-response).

### Examples


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

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

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

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

## API Gateway stage variables reference
Stage variables reference

### HTTP integration URIs


You can use a stage variable as part of an HTTP integration URI, as shown in the following examples.
+ A full URI without protocol – `http://${stageVariables.<variable_name>}`
+ A full domain – `http://${stageVariables.<variable_name>}/resource/operation`
+ A subdomain – `http://${stageVariables.<variable_name>}.example.com/resource/operation`
+ A path – `http://example.com/${stageVariables.<variable_name>}/bar`
+ A query string – `http://example.com/foo?q=${stageVariables.<variable_name>}` 

### Lambda functions


 You can use a stage variable in place of a Lambda function name or alias, as shown in the following examples. 
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:${stageVariables.<function_variable_name>}/invocations`
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:<function_name>:${stageVariables.<version_variable_name>}/invocations`

**Note**  
To use a stage variable for a Lambda function, the function must be in the same account as the API. Stage variables don't support cross-account Lambda functions.

### AWS integration credentials


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

# Deploy WebSocket APIs in API Gateway
Deploy a WebSocket API

 After creating your WebSocket API, you must deploy it to make it available for your users to invoke. 

To deploy an API, you create an [API deployment](api-gateway-basic-concept.md#apigateway-definition-api-deployment) and associate it with a [stage](api-gateway-basic-concept.md#apigateway-definition-api-stage). Each stage is a snapshot of the API and is made available for client apps to call. 

**Important**  
Every time you update an API, you must redeploy it. Changes to anything other than stage settings require a redeployment, including modifications to the following resources:  
Routes
Integrations
Authorizers
By default you are limited to 10 stages for each API. We recommend that you re-use stages for your deployments. 

To call a deployed WebSocket API, the client sends a message to the API's URL. The URL is determined by the API's hostname and stage name.

**Note**  
API Gateway will support payloads up to 128 KB with a maximum frame size of 32 KB. If a message exceeds 32 KB, it must be split into multiple frames, each 32 KB or smaller.

Using the API's default domain name, the URL of (for example) a WebSocket API in a given stage (`{stageName}`) is in the following format:

```
wss://{api-id}.execute-api.{region}.amazonaws.com/{stageName}
```

To make the WebSocket API's URL more user-friendly, you can create a custom domain name (e.g., `api.example.com`) to replace the default host name of the API. The configuration process is the same as for REST APIs. For more information, see [Custom domain name for public REST APIs in API Gateway](how-to-custom-domains.md).

Stages enable robust version control of your API. For example, you can deploy an API to a `test` stage and a `prod` stage, and use the `test` stage as a test build and use the `prod` stage as a stable build. After the updates pass the test, you can promote the `test` stage to the `prod` stage. The promotion can be done by redeploying the API to the `prod` stage. For more details about stages, see [Set up a stage for a REST API in API Gateway](set-up-stages.md).

**Topics**
+ [

## Create a WebSocket API deployment using the AWS CLI
](#apigateway-create-websocket-deployment-using-awscli)
+ [

## Create a WebSocket API deployment using the API Gateway console
](#apigateway-create-websocket-deployment-using-console)

## Create a WebSocket API deployment using the AWS CLI


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

```
aws apigatewayv2 --region us-east-1 create-deployment --api-id aabbccddee
```

The output will look like the following:

```
{
    "DeploymentId": "fedcba",
    "DeploymentStatus": "DEPLOYED",
    "CreatedDate": "2018-11-15T06:49:09Z"
}
```

The deployed API is not callable until you associate the deployment with a stage. You can create a new stage or reuse a stage that you have previously created.

The following [create-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-stage.html) command creates a new stage and associates it with the deployment:

```
aws apigatewayv2 --region us-east-1 create-stage --api-id aabbccddee --deployment-id fedcba --stage-name test
```

The output looks like the following:

```
{
    "StageName": "test",
    "CreatedDate": "2018-11-15T06:50:28Z",
    "DeploymentId": "fedcba",
    "DefaultRouteSettings": {
        "MetricsEnabled": false,
        "ThrottlingBurstLimit": 5000,
        "DataTraceEnabled": false,
        "ThrottlingRateLimit": 10000.0
    },
    "LastUpdatedDate": "2018-11-15T06:50:28Z",
    "StageVariables": {},
    "RouteSettings": {}
}
```

You can also reuse an existing stage by updating the stage's `deploymentId` property with the newly created deployment ID (*deployment-id*). The following [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) command updates the stage's deployment ID:

```
aws apigatewayv2 update-stage --region region \
    --api-id api-id \ 
    --stage-name stage-name \ 
    --deployment-id deployment-id
```

## Create a WebSocket API deployment using the API Gateway console


To use the API Gateway console to create a deployment for a WebSocket API:

1. Sign in to the API Gateway console and choose the API.

1. Choose **Deploy API**.

1. Choose the desired stage from the dropdown list or enter the name of a new stage.

# Security policy for WebSocket APIs in API Gateway


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

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

## Supported TLS protocols and ciphers for WebSocket APIs


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


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

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


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

## OpenSSL and RFC cipher names


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

## Information about REST APIs and HTTP APIs


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

# Custom domain names for WebSocket APIs in API Gateway
Custom domain names

*Custom domain names* are simpler and more intuitive URLs that you can provide to your API users.

After deploying your API, you (and your customers) can invoke the API using the default base URL of the following format: 

```
https://api-id.execute-api.region.amazonaws.com/stage
```

where *api-id* is generated by API Gateway, *region* is the AWS Region, and *stage* is specified by you when deploying the API.

The hostname portion of the URL, `api-id.execute-api.region.amazonaws.com` refers to an API endpoint. The default API endpoint name is randomly generated, difficult to recall, and not user-friendly.

With custom domain names, you can set up your API's hostname, and choose a base path (for example, `myservice`) to map the alternative URL to your API. For example, a more user-friendly API base URL can become:

```
https://api.example.com/myservice
```

## Considerations


The following considerations might impact your use of a custom domain name.
+ If you map a custom domain name to a WebSocket API, you can't map it to a REST API or an HTTP API.
+ Only Regional custom domain names are supported.
+ For the minimum TLS version, only TLS 1.2 is supported.
+ You must create or update your DNS provider's resource record to map to your API endpoint. Without such a mapping, API requests bound for the custom domain name cannot reach API Gateway.
+ You can support an almost infinite number of domain names without exceeding the default quota by using a wildcard certificate. For more information, see [Wildcard custom domain names](http-api-custom-domain-names.md#http-wildcard-custom-domain-names).

## Prerequisites


The following are prerequisites for a custom domain name.

### Register a domain name


You must have a registered internet domain name in order to set up custom domain names for your APIs. You can register your internet domain name using [Amazon Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/) or using a third-party domain registrar of your choice. Your custom domain name can be the name of a subdomain or the root domain (also known as the "zone apex") of a registered internet domain.

Your domain name must follow the [RFC 1035](https://tools.ietf.org/html/rfc1035#section-2.3.4) specification and can have a maximum of 63 octets per label and 255 octets in total.

### Certificates for custom domain names


Before setting up a custom domain name for an API, you must have an SSL/TLS certificate ready in ACM. If ACM is not available in the AWS Region where you are creating your custom domain name, you must import a certificate to API Gateway in that Region.

To import an SSL/TLS certificate, you must provide the PEM-formatted SSL/TLS certificate body, its private key, and the certificate chain for the custom domain name.

Each certificate stored in ACM is identified by its ARN. With certificates issued by ACM, you do not have to worry about exposing any sensitive certificate details, such as the private key. To use an AWS managed certificate for a domain name, you simply reference its ARN. 

If your application uses certificate pinning, sometimes known as SSL pinning, to pin an ACM certificate, the application might not be able to connect to your domain after AWS renews the certificate. For more information, see [Certificate pinning problems](https://docs.aws.amazon.com/acm/latest/userguide/troubleshooting-pinning.html) in the *AWS Certificate Manager User Guide*.

## Wildcard custom domain names


With wildcard custom domain names, you can support an almost infinite number of domain names without exceeding the [default quota](limits.md). For example, you could give each of your customers their own domain name, `customername.api.example.com`.

To create a wildcard custom domain name, specify a wildcard (`*`) as the first subdomain of a custom domain that represents all possible subdomains of a root domain.

For example, the wildcard custom domain name `*.example.com` results in subdomains such as `a.example.com`, `b.example.com`, and `c.example.com`, which all route to the same domain.

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

You can use the `$context.domainName` and `$context.domainPrefix` context variables to determine the domain name that a client used to call your API. To learn more about context variables, see [Variables for data transformations for API Gateway](api-gateway-mapping-template-reference.md).

To create a wildcard custom domain name, you must provide a certificate issued by ACM that has been validated using either the DNS or the email validation method.

**Note**  
You can't create a wildcard custom domain name if a different AWS account has created a custom domain name that conflicts with the wildcard custom domain name. For example, if account A has created `a.example.com`, then account B can't create the wildcard custom domain name `*.example.com`.  
If account A and account B share an owner, you can contact the [AWS Support Center](https://console.aws.amazon.com/support/home#/) to request an exception.

## Next steps for custom domain names


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

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

# Map API stages to a custom domain name for WebSocket APIs
API mappings

You use API mappings to connect API stages to a custom domain name. After you create a domain name and configure DNS records, you use API mappings to send traffic to your APIs through your custom domain name.

An API mapping specifies an API, a stage, and optionally a path to use for the mapping. For example, you can map the `production` stage of an API to `wss://api.example.com/orders`.

Before you create an API mapping, you must have an API, a stage, and a custom domain name. To learn more about creating a custom domain name, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md).

## Restrictions

+ In an API mapping, the custom domain name and mapped APIs must be in the same AWS account.
+ API mappings must contain only letters, numbers, and the following characters: `$-_.+!*'()`.
+ The maximum length for the path in an API mapping is 300 characters.
+ You can't map WebSocket APIs to the same custom domain name as an HTTP API or REST API.
+ If you create an API mappings with multiple levels, API Gateway converts all header names to lowercase.

## Create an API mapping


To create an API mapping, you must first create a custom domain name, API, and stage. For information about creating a custom domain name, see [Set up a Regional custom domain name in API Gateway](apigateway-regional-api-custom-domain-create.md).

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

**To create an API mapping**

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

1. Choose **Custom domain names**.

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

1. Choose **API mappings**.

1. Choose **Configure API mappings**.

1. Choose **Add new mapping**.

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

1. Choose **Save**.

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

The following [create-api-mapping](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api-mapping.html) command creates an API mapping. In this example, API Gateway sends requests to `api.example.com/v1` to the specified API and stage.

```
aws apigatewayv2 create-api-mapping \
    --domain-name api.example.com \
    --api-mapping-key v1 \
    --api-id a1b2c3d4 \
    --stage test
```

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

The following CloudFormation example creates an API mapping.

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

------

# IP address types for custom domain names for WebSocket APIs


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

## Considerations for IP address types


The following considerations might impact your use of IP address types.
+ The default IP address type for API Gateway custom domain names is IPv4.
+ Your custom domain name doesn't need to have the same IP address type for all APIs mapped to it. If you disable your default API endpoint, this might affect how callers can invoke your API.

## Change the IP address type of custom domain name


You can change the IP address type by updating the domain name's endpoint configuration. You can update the endpoint configuration by using the AWS Management Console, the AWS CLI, CloudFormation, or an AWS SDK.

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

**To change the IP address type of a custom domain name**

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

1. Choose a public custom domain name.

1. Choose **Endpoint configuration**.

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

1. Choose **Save**.

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

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

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

The output will look like the following:

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

------

# Disable the default endpoint for WebSocket APIs
Disable the default endpoint

By default, clients can invoke your API by using the `execute-api` endpoint that API Gateway generates for your API. To ensure that clients can access your API only by using a custom domain name, disable the default `execute-api` endpoint. When you disable the default endpoint, it affects all stages of an API.

The following procedure shows how to disable the default endpoint for a WebSocket API.

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

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

1. Choose an WebSocket API.

1. Choose **API settings**.

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

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

1. Choose **Save changes**.

1. On the main navigation pane, choose **Routes**.

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

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

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

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

After you disable the default endpoint, you must deploy your API for the change to take effect.

The following AWS CLI command creates a deployment.

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

------

# Protect your WebSocket APIs in API Gateway
Protect

API Gateway provides a number of ways to protect your API from certain threats, like malicious users or spikes in traffic. You can protect your API using strategies like generating SSL certificates or setting throttling targets. For more information about generating SSL certificates, see [Generate and configure an SSL certificate for backend authentication in API Gateway](getting-started-client-side-ssl-authentication.md). The rest of this section covers setting throttling targets.

You can configure throttling for your APIs to help protect them from being overwhelmed by too many requests. Throttles are applied on a best-effort basis and should be thought of as targets rather than guaranteed request ceilings.

API Gateway throttles requests to your API using the token bucket algorithm, where a token counts for a request. Specifically, API Gateway examines the rate and a burst of request submissions against all APIs in your account, per Region. In the token bucket algorithm, a burst can allow pre-defined overrun of those limits, but other factors can also cause limits to be overrun in some cases.

When request submissions exceed the steady-state request rate and burst limits, API Gateway begins to throttle requests. Clients may receive `429 Too Many Requests` error responses at this point. Upon catching such exceptions, the client can resubmit the failed requests in a way that is rate limiting.

As an API developer, you can set the target limits for individual API stages or routes to improve overall performance across all APIs in your account.

## Account-level throttling per Region


By default, API Gateway limits the steady-state requests per second (RPS) across all APIs within an AWS account, per Region. It also limits the burst (that is, the maximum bucket size) across all APIs within an AWS account, per Region. In API Gateway, the burst limit represents the target maximum number of concurrent request submissions that API Gateway will fulfill before returning `429 Too Many Requests` error responses. For more information on throttling quotas, see [Amazon API Gateway quotas](limits.md).

Per-account limits are applied to all APIs in an account in a specified Region. The account-level rate limit can be increased upon request - higher limits are possible with APIs that have shorter timeouts and smaller payloads. To request an increase of account-level throttling limits per Region, contact the [AWS Support Center](https://console.aws.amazon.com/support/home#/). For more information, see [Amazon API Gateway quotas](limits.md). Note that these limits can't be higher than the AWS throttling limits.

## Route-level throttling


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

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

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

# Monitor WebSocket APIs in API Gateway
Monitor

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

**Note**  
API Gateway might not generate logs and metrics in the following cases:  
413 Request Entity Too Large errors
Excessive 429 Too Many Requests errors
400 series errors from requests sent to a custom domain that has no API mapping
500 series errors caused by internal failures

**Topics**
+ [

# Monitor WebSocket API execution with CloudWatch metrics
](apigateway-websocket-api-logging.md)
+ [

# Configure logging for WebSocket APIs in API Gateway
](websocket-api-logging.md)

# Monitor WebSocket API execution with CloudWatch metrics
Metrics

You can use [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) metrics to monitor WebSocket APIs. The configuration is similar to that used for REST APIs. For more information, see [Monitor REST API execution with Amazon CloudWatch metrics](monitoring-cloudwatch.md).

The following metrics are supported for WebSocket APIs:


| Metric | Description | 
| --- | --- | 
| ConnectCount | The number of messages sent to the \$1connect route integration. | 
| MessageCount | The number of messages sent to the WebSocket API, either from or to the client. | 
| IntegrationError | The number of requests that return a 4XX/5XX response from the integration. | 
| ClientError | The number of requests that have a 4XX response returned by API Gateway before the integration is invoked. | 
| ExecutionError | Errors that occurred when calling the integration. | 
| IntegrationLatency | The time difference between API Gateway sending the request to the integration and API Gateway receiving the response from the integration. Suppressed for callbacks and mock integrations. | 

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


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

# Configure logging for WebSocket APIs in API Gateway
Logging

You can enable logging to write logs to CloudWatch Logs. There are two types of API logging in CloudWatch: execution logging and access logging. In execution logging, API Gateway manages the CloudWatch Logs. The process includes creating log groups and log streams, and reporting to the log streams any caller's requests and responses. 

To improve your security posture, we recommend that you use execution logging at the `ERROR` or `INFO` level. You might need to do this to comply with various compliance frameworks. For more information, see [Amazon API Gateway controls](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html) in the *AWS Security Hub User Guide*.

In access logging, you, as an API developer, want to log who has accessed your API and how the caller accessed the API. You can create your own log group or choose an existing log group that could be managed by API Gateway. To specify the access details, you select `$context` variables (expressed in a format of your choosing) and choose a log group as the destination.

For instructions on how to set up CloudWatch logging, see [Set up CloudWatch API logging using the API Gateway console](set-up-logging.md#set-up-access-logging-using-console).

When you specify the **Log Format**, you can choose which context variables to log. The following variables are supported.


| Parameter | Description | 
| --- | --- | 
| \$1context.apiId |  The identifier API Gateway assigns to your API.  | 
| \$1context.authorize.error | The authorization error message. | 
| \$1context.authorize.latency | The authorization latency in ms. | 
| \$1context.authorize.status | The status code returned from an authorization attempt. | 
| \$1context.authorizer.error | The error message returned from an authorizer. | 
| \$1context.authorizer.integrationLatency | The Lambda authorizer latency in ms. | 
| \$1context.authorizer.integrationStatus | The status code returned from a Lambda authorizer. | 
| \$1context.authorizer.latency | The authorizer latency in ms. | 
| \$1context.authorizer.requestId | The AWS endpoint's request ID. | 
| \$1context.authorizer.status | The status code returned from an authorizer. | 
| \$1context.authorizer.principalId |  The principal user identification that is associated with the token sent by the client and returned from an API Gateway Lambda authorizer Lambda function. (A Lambda authorizer was formerly known as a custom authorizer.)  | 
| \$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.  | 
| \$1context.authenticate.error | The error message returned from an authentication attempt. | 
| \$1context.authenticate.latency | The authentication latency in ms. | 
| \$1context.authenticate.status | The status code returned from an authentication attempt. | 
| \$1context.connectedAt |  The [Epoch](https://en.wikipedia.org/wiki/Unix_time)-formatted connection time.  | 
| \$1context.connectionId |  A unique ID for the connection that can be used to make a callback to the client.  | 
| \$1context.domainName |  A domain name for the WebSocket API. This can be used to make a callback to the client (instead of a hardcoded value).  | 
| \$1context.error.message |  A string that contains an API Gateway error message.  | 
| \$1context.error.messageString | The quoted value of \$1context.error.message, namely "\$1context.error.message". | 
| \$1context.error.responseType |  The error response type.  | 
| \$1context.error.validationErrorString |  A string that contains a detailed validation error message.  | 
| \$1context.eventType |  The event type: `CONNECT`, `MESSAGE`, or `DISCONNECT`.  | 
| \$1context.extendedRequestId | Equivalent to \$1context.requestId. | 
| \$1context.identity.accountId |  The AWS account ID associated with the request.  | 
| \$1context.identity.apiKey |  The API owner key associated with key-enabled API request.  | 
| \$1context.identity.apiKeyId | The API key ID associated with the key-enabled API request | 
| \$1context.identity.caller |  The principal identifier of the caller that signed the request. Supported for routes that use IAM authorization.  | 
| \$1context.identity.cognitoAuthenticationProvider |  A comma-separated list of all the Amazon Cognito authentication providers used by the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  For example, for an identity from an Amazon Cognito user pool, `cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` For information about the available Amazon Cognito authentication providers, see [Using Federated Identities](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) in the *Amazon Cognito Developer Guide*. | 
| \$1context.identity.cognitoAuthenticationType |  The Amazon Cognito authentication type of the caller making the request. Available only if the request was signed with Amazon Cognito credentials. Possible values include `authenticated` for authenticated identities and `unauthenticated` for unauthenticated identities. | 
| \$1context.identity.cognitoIdentityId |  The Amazon Cognito identity ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.cognitoIdentityPoolId |  The Amazon Cognito identity pool ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials.  | 
| \$1context.identity.principalOrgId |  The [AWS organization ID](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html). Supported for routes that use IAM authorization.  | 
| \$1context.identity.sourceIp |  The source IP address of the TCP connection making the request to API Gateway.  | 
| \$1context.identity.user |  The principal identifier of the user that will be authorized against resource access. Supported for routes that use IAM authorization.  | 
| \$1context.identity.userAgent |  The user agent of the API caller.  | 
| \$1context.identity.userArn |  The Amazon Resource Name (ARN) of the effective user identified after authentication.  | 
| \$1context.integration.error | The error message returned from an integration. | 
| \$1context.integration.integrationStatus | For Lambda proxy integration, the status code returned from AWS Lambda, not from the backend Lambda function code. | 
| \$1context.integration.latency | The integration latency in ms. Equivalent to \$1context.integrationLatency. | 
| \$1context.integration.requestId | The AWS endpoint's request ID. Equivalent to \$1context.awsEndpointRequestId. | 
| \$1context.integration.status | The status code returned from an integration. For Lambda proxy integrations, this is the status code that your Lambda function code returns. Equivalent to \$1context.integrationStatus. | 
| \$1context.integrationLatency | The integration latency in ms, available for access logging only. | 
| \$1context.messageId |  A unique server-side ID for a message. Available only when the `$context.eventType` is `MESSAGE`.  | 
| \$1context.requestId |  Same as `$context.extendedRequestId`.  | 
| \$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.routeKey |  The selected route key.  | 
| \$1context.stage |  The deployment stage of the API call (for example, beta or prod).  | 
| \$1context.status |  The response status.  | 
| \$1context.waf.error | The error message returned from AWS WAF. | 
| \$1context.waf.latency | The AWS WAF latency in ms. | 
| \$1context.waf.status | The status code returned from AWS WAF. | 

Examples of some commonly used access log formats are shown in the API Gateway console and are listed as follows.
+ `CLF` ([Common Log Format](https://httpd.apache.org/docs/current/logs.html#common)):

  ```
  $context.identity.sourceIp $context.identity.caller \
  $context.identity.user [$context.requestTime] "$context.eventType $context.routeKey $context.connectionId" \
  $context.status $context.requestId
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.
+  `JSON`: 

  ```
  {
  "requestId":"$context.requestId", \
  "ip": "$context.identity.sourceIp", \
  "caller":"$context.identity.caller", \
  "user":"$context.identity.user", \
  "requestTime":"$context.requestTime", \
  "eventType":"$context.eventType", \
  "routeKey":"$context.routeKey", \
  "status":"$context.status", \
  "connectionId":"$context.connectionId"
  }
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.
+ `XML`: 

  ```
  <request id="$context.requestId"> \
   <ip>$context.identity.sourceIp</ip> \
   <caller>$context.identity.caller</caller> \
   <user>$context.identity.user</user> \
   <requestTime>$context.requestTime</requestTime> \
   <eventType>$context.eventType</eventType> \
   <routeKey>$context.routeKey</routeKey> \
   <status>$context.status</status> \
   <connectionId>$context.connectionId</connectionId> \
  </request>
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.
+ `CSV` (comma-separated values):

  ```
  $context.identity.sourceIp,$context.identity.caller, \
  $context.identity.user,$context.requestTime,$context.eventType, \
  $context.routeKey,$context.connectionId,$context.status, \
  $context.requestId
  ```

  The continuation characters (`\`) are meant as a visual aid. The log format must be a single line. You can add a newline character (`\n`) at the end of the log format to include a newline at the end of each log entry.