Connect to AVS with HTTP/2

The Alexa Voice Service (AVS) exposes an HTTP/2 endpoint and supports AVS-initiated directives, which enable your device to access available Alexa features. This page provides instructions for creating and maintaining an HTTP/2 connection with AVS.

Prerequisites

Address the following prerequisites before creating an HTTP/2 connection:

Obtain a Login with Amazon (LWA) access token

To access AVS, your device must obtain a Login with Amazon (LWA) access token, which grants your device access to the AVS APIs on behalf of the user. To learn about the available authorization options for AVS, see Authorize an AVS Device

You must send the LWA access token to AVS in the header of each event. If authentication fails for any reason the connection with AVS closes.

The following is a sample header. In addition to your access token, include a boundary term in the header of each event sent to AVS.

:method = POST  
:scheme = https  
:path = /{{API version}}/events
authorization = Bearer {{YOUR_ACCESS_TOKEN}}
content-type = multipart/form-data;  boundary={{BOUNDARY_TERM_HERE}}

Choose an HTTP/2 client library

You can use the following HTTP/2 client libraries with AVS:

Language Library
C / C++ nghttp2
C / C++ curl and libcurl
Java OkHttp
Java Netty
Java Jetty

For a complete list of implementations, see GitHub.

Open and close event and downchannel streams

This section describes the different expected lifecycles for the event stream and downchannel stream.

Open and close an event stream

The device sends each new event on its own stream. Typically, these streams close after AVS returns the appropriate directives and corresponding audio attachments to your device.

Handle requests sequentially. Send new requests AVS begins responding to your previous request, which is after the previous request returns headers.

To open and close an event stream

  1. Your device opens a stream and sends a multipart message consisting of one JSON-formatted event and up to one binary audio attachment. For more details, see Structuring an HTTP/2 Request.
  2. AVS returns multipart messages consisting of one more JSON-formatted directives and corresponding audio attachments on the same stream, potentially before streaming is complete. The URL attribute that follows cid: in a Play or Speak directive also appears in the header of the associated audio attachment.
  3. After receiving a response from AVS, close the event stream.

Open and close a downchannel stream

In parallel, AVS might send directives to your device on the downchannel. Primarily, use the downchannel for AVS-initiated directives.

To open and close a downchannel stream

  1. The device makes a GET request to the directives path within 10 seconds of creating a connection with AVS.
  2. This stream sends your device AVS-initiated directives and audio attachments, such as timers, alarms, and instructions originating from the Amazon Alexa app. Unlike an event stream, the downchannel doesn't instantly close and is should remain open in a half-closed state from the device and from AVS for prolonged periods of time.
  3. When the downchannel stream closes, your device must immediately establish a new downchannel to make sure that your device can receive AVS-initiated directives.

Create an HTTP/2 connection

When a user powers on your device, create a single HTTP2 connection with AVS. This connection handles all directives and events, including anything that AVS sends to your device on the downchannel stream. For additional details about connection management, see server-initiated disconnects.

Maintaining a connection with AVS has two requirements:

To create an HTTP/2 connection

  1. Create a downchannel stream. Your device must make a GET request to /{{API version}}/directives within 10 seconds of opening the connection with AVS. The request should look like the following example:

    :method = GET  
    :scheme = https  
    :path = /{{API version}}/directives
    authorization = Bearer {{YOUR_ACCESS_TOKEN}}   
    

    Following a successful request, the downchannel stream remains open in a half-closed state from the device and open from AVS for the duration of the connection. Long pauses could occur between AVS-initiated directives.

  2. After establishing the downchannel stream, your device must synchronize the states of its components with AVS. Make a POST request to /{{API version}}/events on a new event stream on the existing connection without opening a new connection. Close this event stream when your device receives a directive response. The following example shows a SynchronizeState event:

    :method = POST  
    :scheme = https  
    :path = /{{API version}}/events
    authorization = Bearer {{YOUR_ACCESS_TOKEN}}
    content-type = multipart/form-data; boundary={{BOUNDARY_TERM_HERE}}  
    
    --{{BOUNDARY_TERM_HERE}}
    Content-Disposition: form-data; name="metadata"  
    Content-Type: application/json; charset=UTF-8  
    
    {  
        "context": [   
           // This is an array of context objects that are used to communicate the
           // state of all device components to Alexa. See Context for details.
        ],  
        "event": {  
            "header": {  
                "namespace": "System",  
                "name": "SynchronizeState",  
                "messageId": "{{STRING}}"  
            },  
            "payload": {  
            }  
        }  
    }  
    
    --{{BOUNDARY_TERM_HERE}}--
    

After synchronizing state, your device should be able to use this connection to send events and receive directives:

  • Send events to and receive directives from AVS.
  • Receive directives on the downchannel stream.

Maintain the HTTP/2 connection

Use pings and timeouts to keep the HTTP/2 connection between your device and AVS open. If the server disconnects you, reconnect to AVS following the instructions in the next section.

Ping and timeout

Your device must perform one of the following actions. Failure to do so causes the connection to close:

  • Send a PING frame to AVS every 5 minutes when the connection is idle.
  • Make a GET request to /ping every 5 minutes when the connection is idle.

Sample Request

:method = GET  
:scheme = https  
:path = /ping  
authorization = Bearer {{YOUR_ACCESS_TOKEN}}
   

On a failed PING, close the connection and create a new connection.

Server-initiated Disconnects

When the server initiates a disconnect, your device should follow this sequence::

  1. Open a new connection and route any new requests through it.
  2. Close the old connection after processing all open requests and closing their corresponding streams.
  3. Maintain a connection to any stream URL established before the disconnect occurred, such as Amazon Music or Audible. A stream playing before a server-initiated disconnect occurs should continue to play as long as bytes are available.

If the attempt to create a new connection fails, the device should try again with an exponential back-off.