Access the Alexa Shopping and To-Do Lists

Alexa customers currently have access to two built-in lists: Alexa to-do and Alexa shopping.

Customers can review and modify their Alexa lists using voice through a device with Alexa or via the Alexa app. For example, a customer can tell Alexa to add items to the Alexa Shopping List at home, and then while at the store, view the items via the Alexa app, and check them off.

Third-party developers can make their skills have the ability to read and modify these two Alexa lists. See this code sample and tutorial that demonstrates how to integrate list management capabilities with your skill.

This document provides a technical overview of how a custom skill can integrate with Alexa lists. If you do not already have a custom skill, you can create one following Steps to Build a Custom Skill.

To integrate these list management capabilities into your custom skill, follow these steps:

  1. Configure your skill in the Amazon Developer Portal to indicate that it requires Lists Read or Lists Write permissions, or both.
  2. Devise a user intent model that uses customer Alexa lists.
  3. Implement the list management capabilities in your skill service code.

A customer grants permissions to a skill through the Skills section of the Alexa app. Once a customer grants permissions, the skill will have access to the customer’s Alexa lists until permissions are explicitly revoked. At any time, the customer can change the allowed access for that skill in Manage Settings on the skill’s page in the Alexa app.

A skill developer is expected to gracefully handle the cases when customer has not granted all the requested permissions. This can be accomplished via a voice prompt and a permissions missing card. See Skill Behavior When Missing Permissions for details about the use of such a card.

In addition to the list management capabilities described in this document, a skill can also access list events and skill events. These events can be used to enhance the skill’s functionality. To use SMAPI in a skill service, the developer must manage the skill through the Alexa Skills Kit Command Line Interface (ASK CLI). Once a skill is managed through ASK CLI, the developer cannot return its management to the Amazon Developer Portal.

Set Up Permissions

In order for your skill to have read or write access to customers’ Alexa lists, it must have the appropriate permissions which you can set up in the Amazon Developer Portal.

  1. Open the Amazon Developer Portal, and select Get Started for the Alexa Skills Kit. The Building Alexa Skills with the Alexa Skills Kit page opens.

  2. Click Edit an existing skill, and select Configuration at the left.

  3. In the Permissions section of the Configuration page, select the Lists Read or Lists Write check boxes, or both, depending on the requirements of your skill. Do not ask for more permissions than your skill requires. Click Save.

Configuration for Lists
Configuration for Lists

Access to Alexa Lists

To access these list management capabilities, a skill requires a consent token specific to a customer to access that customer’s Alexa lists. This token can be obtained with an in-session request, which is a customer voice request, or an out-of-session request.

In-Session Intent Request

After customer consent is obtained, each request will include the customer consent token. Thus, an in-session intent request to your skill from Alexa includes a user object that contains a consent token. You will need to retrieve this token value and use it in the requests related to list management.

The form of the full request is shown below. The user object is nested in the System object, which is nested in the context object, and the user object is also duplicated in the session object. For more information about the parameters of such a request, see: Request Body Syntax.

{
  "version": "string",
  "session": {
    "new": true,
    "sessionId": "string",
    "application": {
      "applicationId": "string"
    },
    "attributes": {
      "string": {}
    },
    "user": {
      "userId": "amzn1.ask.account.<userId_value>",
         "permissions": {
             "consentToken": "Atza|MQEWY...6fnLok"
      },	  
      "accessToken": "string"
    }
  },
  "context": {
    "System": {
      "application": {
        "applicationId": "string"
      },
      "user": {
        "userId": "amzn1.ask.account.<userId_value>",
           "permissions": {
             "consentToken": "Atza|MQEWY...6fnLok"
      },		
        "accessToken": "string"
      },
      "device": {
        "deviceId": "string",	  
        "supportedInterfaces": {
          "AudioPlayer": {}
        }
      },
      "apiEndpoint": "string"
    },
    "AudioPlayer": {
      "token": "string",
      "offsetInMilliseconds": 0,
      "playerActivity": "string"
    }
  },
  "request": {}
}

Thus: consentToken = this.event.context.System.user.permissions.consentToken

See also: Handling Requests Sent by Alexa

Out-of-Session Interaction

Your app can request an out-of-session access token when it needs to access the customer Alexa lists outside of the customer’s voice request, following these steps:

  1. Obtain the Skill Messaging API access token, using the ClientId and ClientSecret as inputs. To get these ClientId and ClientSecret values, refer to the Configuration tab for your skill in the Amazon Developer Portal. See the request format in Configure an Application or Service to Send Messages to Your Skill. If your skill has been managed through SMAPI, you can still see these values in the developer portal. Go to the list of skills. Those skills that have the appropriate permissions will show the link View Skill ID and Client Secret. When you click this link, the Skill ID, Client ID, and Client Secret appear in a popup.

  2. Once the access token is obtained, the app makes an asynchronous call to the Skill Messaging API using the Skill Messaging API access token and the userId value, which was obtained during an earlier customer voice interaction. The Skill Messaging API calls the skill back with the customer consent token.

See: - Skill Messaging API

Out-of-session token workflow
Out-of-session token workflow

Skill Messaging API Access Token

The third-party application requires authorization to send messages to the skill. This authorization is obtained with the following API via an HTTPS request, as described.

Request Format

This section documents the format for the request.

HTTP Header

POST /auth/O2/token HTTP/1.1`
Host : api.amazon.com
Content-Type : application/x-www-form-urlencoded;charset=UTF-8
 
Parameter Description Example
Content-Type The content type of the resource. Must be application/x-www-form-urlencoded Content-Type: application/x-www-form-urlencoded

Request Body Syntax

grant_type=client_credentials&client_id=(clientID)&client_secret=(clientSecret)&scope=alexa:skill_messaging

Request Body Parameters

 
Parameter Description Example
grant_type Value must be client_credentials grant_type=client_credentials
client_id The ClientId value client_id=amzn1.iba-client…
client_secret The ClientSecret value client_secret=…
scope Value must be alexa:skill_messaging scope=alexa:skill_messaging

Sample cURL Request

curl -k -X POST -H
 'Content-Type: application/x-www-form-urlencoded' -d
'grant_type=client_credentials&client_id=xxxx&client_secret=yyyy&scope=alexa:skill_messaging'
 https://api.amazon.com/auth/O2/token

Response Format

If your request is not successful, you will receive a non-200 error status code. In the case of a non-200 code, the response message may contain the following parameter in the body of the JSONObject:

reason: <<The reason the request was not accepted>>

A successful response format is as follows.

HTTP Header

X-Amzn-RequestId: d917ceac-2245-11e2-a270-0bc161cb589d
 Content-Type: application/json

Response Body Syntax

{
  "access_token": "Atc|MQEWYJxEnP3I1ND03ZzbY_NxQkA7Kn7Aioev_OfMRcyVQ4NxGzJMEaKJ8f0lSOiV-yW270o6fnkI",
  "expires_in": 3600,
  "scope": "alexa:skill_messaging",
  "token_type": "Bearer"
}

Request Body Parameters

 
Parameter Description Example
access_token An access token that must be used for all requests "access_token":"Atc|MQEWYJxEnP3I1ND03Zz..."
expires_in The duration in seconds of the access token lifetime. For example, 3600 denotes that the access token expires in one hour from the time the response was generated. "expires_in":3600
scope Value will be alexa:skill_messaging "scope":"alexa:skill_messaging"
token_type Only Bearer tokens are supported "token_type":"Bearer"

Errors

Status CodeTypeDescription
400INVALID_REQUESTReasons for this response include:
- The content type is not supported by the authorization server. In other words, it is not application/x-www-form-urlencoded.
- The request is missing a required parameter: grant-type, scope, client_id, client_secret.
- The request is otherwise malformed.
400 UNAUTHORIZED_CLIENT The client is not authorized for the requested operation.
400 UNSUPPORTED_GRANT_TYPE The grant type is not supported by the authorization server. In other words, it is not client_credentials.
400 INVALID_SCOPE The requested scope is invalid, which means it is not alexa:skill_messaging.
401 INVALID_CLIENT The client authentication failed.
500 SERVER_ERROR There was an internal server error. The requester may retry the request.
503 SERVICE_UNAVAILABLE The server is temporarily unavailable. The requester must retry later honoring the Retry-After header included in the response. See the HTTP/1.1 specification, section 14.37, for possible formats for the Retry-After value.

Handle Missing Permissions Grants

When a skill requires Lists Read or Lists Write access, and the customer has not granted access, the skill developer must gracefully handle this use case in the skill service code. As a best practice, the skill must display a permissions card in the Alexa app, and the skill should provide a voice prompt that explains to the customer to look in the Alexa app in order to grant the required access.

Here is a sample card format that a skill can issue, in this example for write permissions to a customer’s Alexa lists.

{
  "version": "1.0",
  "response": {
    "card": {
      "type": "AskForPermissionsConsent",
      "permissions": [
           read::alexa:household:list,
		   write::alexa:household:list
        }
      ]
    }
  }
}

The list permissions are read::alexa:household:list and write::alexa:household:list for read and write respectively.

List Management Capabilities

These list management capabilities provide create, read, update, and delete (CRUD) operations for your skill. This API exposes information about customer Alexa lists, and it supports list traversal. Each list item exposed through the API has properties such as value and itemId.

Skills that call this API should be resilient when API responses contain new fields. All API parameters are strings unless otherwise specified. Each itemId is unique in a list.

List Management Quick Reference

List Management Domain: https://api.amazonalexa.com/

APIMethodURI Endpoint
Get lists metadataGETv2/householdlists/
Get a listGETv2/householdlists/{listId}/{status}
Get a list itemGETv2/householdlists/{listId}/items/{itemId}
Update a list itemPUTv2/householdlists/{listId}/items/{itemId}
Create a new list itemPOSTv2/householdlists/{listId}/items
Delete a list itemDELETEv2/householdlists/{listId}/items/{itemId}

HTTP Methods for List Management

In the following APIs, {listId} refers to the customer’s listId and {itemId} refers to the itemId for the specified list item.

GetListsMetadata

Retrieves the metadata for all customer Alexa lists.

Endpoint: https://api.amazonalexa.com/v2/householdlists/

Request Format

GET: v2/householdlists/
Authorization: Bearer auth_token_for_customer
Content-Type: application/json

Response Format

HTTP 200 OK, on success
{
    "lists":
    [
        {
            "listId": // list id (String)
            "name": // list name (String)
            "statusMap": [
                { "status": "active" // (Enum) ,  
                  "href": // active list items URL },
                { "status": "completed" // (Enum), 
                  "href": // completed list items URL }
            ]
        }
    ]
}

HTTP 403 Forbidden, if customer authorization token is not valid/expired
{
    "message": "request is unauthorized"
    "type": "Unauthorized"
}

HTTP 500 Internal Server Error, if Alexa encountered a server error 
{
    "message": // error message (String)
    "type": "InternalError"
}

GetList

Retrieves a customer’s Alexa list.

Use the listId retrieved from a call to GetListsMetadata to specify the listId in the request path. You must specify the status variable in the query path. This enables you to retrieve active or completed items. The response to a GetList call includes a relative URL to retrieve the next page of list items, if it exists. GetList exposes the Alexa-imposed list item order. An external app can choose to present Alexa list items in the order desired.

Endpoint: https://api.amazonalexa.com/v2/householdlists/{listId}/{status}

Request Format

GET: v2/householdlists/{listId}/{status}
where {listId} is customer's list id and {status} is "active" or "completed"

Authorization: Bearer auth_token_for_customer
Content-Type: application/json

Response Format

HTTP 200 OK, on success

{
    "listId": // list id (String)
    "name": // list name (String)
    // default page size today is 100 and cannot be controlled by the client
    "items":
    [
	    {
            "id": // item id (String, limit 256 characters)
            "version": // item version (Positive integer)
            "value": // item value (String, limit 256 characters)
            "status": // item status (Enum: "active" or "completed")
            "createdTime": // created time in format Wed Jul 19 23:24:10 UTC 2017 
            "updatedTime": // updated time in format Wed Jul 19 23:24:10 UTC 2017 
            "href": // URL to retrieve the item (String)
         },
         ...
    ]
    "links": {
        "next": "v2/householdlists/{listId}/{status}?nextToken={nextToken}"
    }
}

HTTP 400 Bad Request, if input is malformed
{
    "message": // (String) (e.g., "invalid list items status)"
    "type": "InvalidInput"
}
 
HTTP 403 Forbidden, if a customer authorization token is not valid/expired
{
    "message": "request is unauthorized"
    "type": "Unauthorized"
}

HTTP 404 Not Found, if the list is not found
{
    "message": "list not found"
    "type": "ObjectNotFound"
}

HTTP 500 Internal Server Error, if Alexa encountered a server error
{
    "message": // error message (String)
    "type": "InternalError"
}

If the links/next property is not populated, then the requestor has reached the end of the list. The list items are returned in reverse chronological order based on the item creation time.

GetListItem

Retrieves a single list item within a list.

The listId is obtained from a call to GetListsMetadata.

Endpoint: v2/householdlists/{listId}/items/{itemId}

Request Format

GET: v2/householdlists/{listId}/items/{itemId}
where {listId} is customer's list id and {itemId} is the item id

Authorization: Bearer auth_token_for_customer
Content-Type: application/json

Response Format


HTTP 200 OK, on success

{
    "id": // item id (String)
    "version": // item version when it was read (Positive integer)
    "value": // item value (String)
    "status": // item status (Enum: "active" or "completed")
    "createdTime": // created time (ISO 8601 time format with time zone)
    "updatedTime": // updated time (ISO 8601 time format with time zone)
    "href": // URL to retrieve the item (String)
}
 
HTTP 403 Forbidden, if a customer authorization token is not valid/expired
{
    "message": "request is unauthorized"
    "type": "Unauthorized"
}

HTTP 404 Not Found, if the list or list item is not found
{
    "message": // error message (String) (e.g., "item is not found")
    "type": "ObjectNotFound"
}

HTTP 500 Internal Server Error, if Alexa encountered a server error
{
    "message": // error message (String)
    "type": "InternalError"
}

UpdateListItem

Updates an Alexa list item after a list item has been updated through the skill.

An UpdateListItem call will expose the change to a customer’s list through Alexa.

Endpoint: v2/householdlists/{listId}/items/{itemId}

Request Format

PUT: v2/householdlists/{listId}/items/{itemId}
where {listId} is customer's list id and {itemId} is the item id

Authorization: Bearer auth_token_for_customer
Content-Type: application/json

{
    "id": // item id (String)
    "version": // item version when it was read (Positive integer)
    "value": // updated item value (String, limit is 256 characters)
    "status": // item status (Enum: "active" or "completed")
}

Response Format

HTTP 200 OK, on success
 
{
    "id": // item id (String)
    "version": // updated item version (Positive integer)
    "value": // item value (String, limit is 256 characters)
    "status": // item status (Enum: "active" or "completed")
    "createdTime": // created time (ISO 8601 time format with time zone)
    "updatedTime": // updated time (ISO 8601 time format with time zone)
    "href": // URL to retrieve the item (String)
}
 
HTTP 403 Forbidden, if a customer authorization token is not valid, or has expired
{
    "message": "request is unauthorized"
    "type": "Unauthorized"
}

HTTP 404 Not Found, if the list or list item is not found
{
    "message": // error message (String) (for example, "item is not found")
    "type": "ObjectNotFound"
}
 
HTTP 409 Conflict, if the item versions mismatch
{
    "message": "item versions mismatch"
    "type": "Conflict"
}

HTTP 500 Internal Server Error, if Alexa has encountered a server error
{
    "message": // error message (String)
    "type": "InternalError"
}

CreateListItem

Creates a new Alexa list item.

Endpoint: v2/householdlists/{listId}/items

Request Format

POST: v2/householdlists/{listId}/items

Authorization: Bearer auth_token_for_customer
Content-Type: application/json

{
    "value": // new item value (String, limit is 256 characters)
    "status": // item status (Enum: "active" or "completed")
}

Response Format

HTTP 201 OK, on success
Location: v2/householdlists/{listid}/items/{itemId}
 
{
    "id": // item id (String)
    "version": // item version (Positive integer)
    "value": // item value (String, limit is 256 characters)
    "status": // item status (Enum: "active" or "completed")
    "createdTime": // created time (ISO 8601 time format with time zone)
    "updatedTime": // updated time (ISO 8601 time format with time zone)
    "href": // URL to retrieve the item (String)
}

HTTP 403 Forbidden, if a customer authorization token is not valid/expired
{
    "message": "request is unauthorized"
    "type": "Unauthorized"
}

HTTP 404 Not Found, if the list is not found
{
    "message": "list is not found"
    "type": "ObjectNotFound"
}

HTTP 500 Internal Server Error, if Alexa encountered a server error
{
    "message": // error message (String)
    "type": "InternalError"
}

DeleteListItem

Deletes an Alexa list item.

Endpoint: v2/householdlists/{listId}/items/{itemId}

Request Format

DELETE: v2/householdlists/{listId}/items/{itemId}

Authorization: Bearer auth_token_for_customer
Content-Type: application/json

Response Format

HTTP 200 OK, on success

HTTP 403 Forbidden, if a customer authorization token is not valid/expired
{
    "message": "request is unauthorized"
    "type": "Unauthorized"
}

HTTP 404 Not Found, if the list or list item is not found
{
    "message": // error message (String)
    "type": "ObjectNotFound"
}

HTTP 500 Internal Server Error, if Alexa encountered a server error
{
    "message": // error message (String)
    "type": "InternalError"
}

FAQ

Q: Can a skill use both account linking and these list management capabilities?

Yes. This feature allows the skill developer to reference customer Alexa lists in their external apps. To set up account linking, see Linking an Alexa User with a User in Your System.

Q: Can an Alexa customer grant access to Alexa to-do and shopping lists to more than one skill?

Yes.

Q: Can a customer delete their Alexa list?

A customer cannot delete an Alexa list. However, a customer can delete all the items on an Alexa list.

Q: Can a customer grant access to a single Alexa list?

No, a customer cannot limit the lists they share with a skill. However, a skill may choose to interact only with those lists that are of interest.

Q: Do these list management capabilities support custom list metadata?

No.

Q: Can Alexa customers share their lists with other customers within Amazon?

Yes, if the other customers are within the same Amazon household. For a discussion of Amazon Household, see Household Profiles on Alexa Devices.

Reference materials:

Code samples: