Alexa for Apps V1 to V2 Migration Guide

This document is for developers who have an existing skill that uses Alexa for Apps V1, and are migrating it to Alexa for Apps V2.

The V2 API allows your skill to bridge voice-to-app experiences starting on any Alexa-enabled device, including Echo devices.

User experience difference between V1 and V2

The key difference between V1 and V2 is that your skill can now bridge customers from your skill to your app not only on mobile devices, but also from any Alexa-enabled device, such as an Amazon Echo device.

Procedure overview

The following task list outlines the procedure that you must follow to migrate your skill to Alexa for Apps V2.

How to update your skill to Alexa for Apps V2

Step 1: Update your skill manifest

Update your skill manifest to declare support for Alexa for Apps V2 and declare intents.

To update your skill manifest

  1. In the manifest.apis.custom.interfaces section, replace "type": "APP_LINKS" with "type": "APP_LINKS_V2"

    This tells Alexa that your skill can support the AppLink V2 interface. You cannot declare both AppLink V1 and AppLink V2 interfaces.

  2. Under manifest.permissions, add alexa::devices:app:push_notifications to add the Send to Phone push permission.

    This permission is for the user to allow your skill to send push notifications in the Alexa app. Alexa for Apps handles scenarios where the user hasn't yet enabled the permission, using voice consent. Your skill doesn't need to check for this permission or prompt the user to enable it. You only need to add this line to the permissions section of your manifest.

  3. If your skill uses Android custom intents, update the appLink section in the skill manifest as shown in the following example.

    "appLink": {
       "linkedApplications": [
          {
             "friendlyName": {
                "default": "GrubbHouse",
                "localizedNames": [
                   {
                      "locale": "de-DE",
                      "name": "GrubbHaus"
                   }
                ]
             },
             "catalogInfo": {
                "type": "GOOGLE_PLAY_STORE",
                "identifier": "com.someapp"
             },
             "customSchemes": [
                "grubbhouse://",
                "grbh://"
             ],
             "domains": [
                "grubbhouse.com",
                "grbh.com"
             ],
             # declaring an Android custom intent
             "androidCustomIntents": [
                {
                   "component": "com.someapp.SomeActivity",
                   "action": "com.someapp.SOME_ACTION"
                }
             ]
          }
       ]
    }
    
  4. If you're adding deep-link types that are new in Alexa for Apps V2 (website-only links, common URI schemes, or Android common intents), update the appLink section to add any needed linkedWebDomains, linkedCommonSchemes, or linkedAndroidCommonIntents properties as shown in the following example. For details, see Alexa for Apps V2 Skill Connection Request Reference.

    "appLink": {
       "linkedWebDomains": [
          "grubbhouse.com",
             "amazon.com",
             "yahoo.com"
       ],
       "linkedCommonSchemes": {
          "IOS_APP_STORE": [
             "MAPS",
             "TEL"
          ],
          "GOOGLE_PLAY_STORE": [
             "MAPS",
             "TEL"
          ]
       },
       "linkedAndroidCommonIntents": [
          {
             "intentName": "SHOW_IN_MAP",
             "catalogType": "GOOGLE_PLAY_STORE"
          }
       ]
    }
    

Step 2: Update your skill endpoint code

In Step 1 you declared support for Alexa for Apps V2 in your skill manifest. This results in changes to the following payloads:

  • The request payload that your skill receives in an inbound request
  • The request payload that your skill sends in a skill connection request
  • The skill connection response payload that your skill receives

In this step, you update your skill endpoint code to handle these changes.

Step 2a: Parse the updated incoming request payload

The skill request payload is the object that your skill receives in inbound requests. There are two sections in this object that change in Alexa for Apps V2: context.System.device.supportedInterfaces and context.AppLink. If your skill request handlers expect these sections, you must update your code so it parses them correctly.

  1. In the context.System.device.supportedInterfaces section, the presence of an AppLink property indicates that your skill can make an Alexa for Apps request. In V1, the AppLink property is an empty object. In V2 it contains a version field with value "2.0", as shown in the following example. This value indicates that the request is an Alexa for Apps V2 request.

    "supportedInterfaces": {
       "AudioPlayer": {...},
    ===== ALEXA FOR APPS ADDITIONS START =====
       "AppLink": {
          "version": "2.0"
       },
    ===== ALEXA FOR APPS ADDITIONS END =====
    }
    
  2. In Alexa for Apps V1, the context.AppLink object contains only a supportedCatalogTypes field, which indicates the mobile OS the customer is using. In Alexa for Apps V2, this object adds the directLaunch and sendToDevice fields to indicate support for the mobile and non-mobile experiences. The directLaunch field indicates whether a direct launch of the app is possible. The sendToDevice field indicates whether a push notification flow is possible.

    The OS type for mobile requests moved to a child object underneath the directLaunch property.

    Request from a mobile device

    As in Alexa for Apps V1, when a customer makes a request on a mobile device, you typically have the option to use either a direct launch or a push notification. Typically it's easier for the customer to have your app launched hands-free. However, you might send a notification instead, if you want to be less intrusive by having your skill keep talking to the customer instead of directly launching your app or website. To determine whether the mobile direct launch experience is possible, your skill should examine the context.AppLink.directLaunch field. If the request came from an iOS device, this property includes the key "IOS_APP_STORE", as shown in the following example.

    "AppLink": {
       "directLaunch": {
          "IOS_APP_STORE": {}
       }
    }
    

    If the request comes from an Android device, this property includes the key "GOOGLE_PLAY_STORE", as shown in the following example.

    "AppLink": {
       "directLaunch": {
          "GOOGLE_PLAY_STORE": {}
       }
    }
    

    Request from an Alexa-enabled device

    When the request comes from an Alexa-enabled device, such as an Amazon Echo, your skill can send links to the customer's mobile device in a notification from the Alexa app. To determine whether it can send a notification to a customer's phone, your skill should check the context.AppLink.sendToDevice field, as in the following example.

    "AppLink": {
       "sendToDevice": {}
    }
    

    The following example shows a skill receiving a request from an iOS device that can handle both Direct launch and Send to phone.

    "AppLink": {
       "directLaunch": {
          "IOS_APP_STORE": {}
       },
       "sendToDevice": {}
    }
    

Step 2b: Send the new payload format in the skill connection request

Alexa for Apps V2 adds a new URI endpoint for you to use when making your skill connection request to directly launch an app or to send the customer a notification with a deep link. The Alexa for Apps request payload structure has changed format, though much of the actual information that you provide is the same. For details, see Alexa for Apps V2 Skill Connection Request Reference.

Make the following changes in your skill connections payload that you send to Alexa for Apps to request a deep-link.

To request a deep link

  1. In the response.directives.uri field, append "/2" to your skill's LinkApp connections URI as follows:
    "uri": "connection://AMAZON.LinkApp/2"
    
  2. In the response.directives.input field, make the following changes:
    • Provide any verbal response that precedes your deep-link by using the response.outputSpeech property. For example, an airline skill might say, "Your flight is on time and leaves Los Angeles International Airport at 2pm PT", and then send the customer a deep link to their flight details page.
    • Remove the onAppLinked and onScreenLocked fields, and add a "topic" field, which Alexa for Apps uses to respond in various scenarios, such as if a customer has their phone locked when they make a request that triggers a deep-link, for example, "To see your messages, please unlock your device." Limit the topic to 23 characters, and make it an action clause – in English this is an imperative phrase, such as "see your messages" or "view the lasagna recipe". This format makes it possible for Alexa to reuse the topic in sentences such as "I'll send John a link to view the lasagna recipe."
    • You can no longer specify or suppress the locked device helper response. However, you can still suppress the default unlocked mobile direct launch helper TTS of "Here's <myAppName>." To do so, set input.prompt.directLaunchDefaultPromptBehavior to "SUPPRESS".
  3. Provide deep links for each catalog type you support. Alexa selects the appropriate links to use based on the customer's receiving device (iOS or Android).

  4. By default, if a request originates from a mobile device, Alexa for Apps attempts to open your app on the customer's phone. To disable this behavior, set directLaunch.enabled to false in the skill connection request payload. If a request originates from an Alexa-enabled device, Alexa for Apps by default attempts to send a push notification to the customer's phone.

Example: Direct launch only - Android Custom Intent with intent extras

The following example shows a payload for a skill connection request that uses an ANDROID_CUSTOM_INTENT deep link. Because the skill only wants to launch the app directly on mobile, it explicitly sets the value of the sendToDevice.enabled property to false.

{
   "version": "1.0",
   "sessionAttributes": {},
   "response": {
      "outputSpeech": {...},
      "card": {...},
      "reprompt": {...},
      "directives": [
================== ALEXA FOR APPS ADDITIONS START ==================
         {
         "type": "Connections.StartConnection",
         "uri": "connection://AMAZON.LinkApp/2",
         "input": {
            "links": {
                "GOOGLE_PLAY_STORE": {
                    "primary": {
                        "ANDROID_CUSTOM_INTENT": {
                            "appIdentifier": "com.cityguide.app",
                            "intentSchemeUri": "intent:#Intent;package=com.cityguide.app;component=com.cityguide.app.SearchActivity;i.some_int=100;S.some_str=hello;end"
                        }
                    }
                }
            },
            "prompt": {
                "topic": "see your search detail",
            },
            "sendToDevice": {
                "enabled": false
            }
         },
================== ALEXA FOR APPS ADDITIONS END ====================
      ]
   }
}

Example: Send to phone only - Android Common Intent and Common Scheme

The following example shows a payload for a skill connection request that uses both a Android common intent and a common URI scheme for deep links. This approach is less intrusive, because it only sends a push notification and doesn't directly launch the app on the customer's phone. To disable launching the app, the skill explicitly sets the value of directLaunch.enabled to false.

{
   "version": "1.0",
   "sessionAttributes": {},
   "response": {
      "outputSpeech": {...},
      "card": {...},
      "reprompt": {...},
      "directives": [
================== ALEXA FOR APPS ADDITIONS START ==================
         {
         "type": "Connections.StartConnection",
         "uri": "connection://AMAZON.LinkApp/2",
         "input": {
            "links": {
                "GOOGLE_PLAY_STORE": {
                    "primary": {
                        "ANDROID_COMMON_INTENT": {
                            "intentName": "OPEN_SETTINGS",
                            "intentSchemeUri": "intent:#Intent;action=android.settings.WIFI_SETTINGS;end"
                        }
                    }
                },
                "IOS_APP_STORE": {
                    "primary": {
                        "COMMON_SCHEME": {
                            "scheme": "TEL",
                            "uri": "tel:1234567"
                        }
                    }
                }
            },
            "prompt": {
                "topic": "see your settings"
            },
            "directLaunch": {
                "enabled": false
            }
         },
================== ALEXA FOR APPS ADDITIONS END ====================
      ]
   }
}

Step 2c: Handle the updated Alexa for Apps response payload

In Alexa for Apps V2, the cause.result field in the response payload contains either directLaunch or sendToDevice. The presence of directLaunch indicates that Alexa for Apps attempted to launch your app. The presence of sendToDevice indicates that Alexa for Apps attempted to send a link to the customer's mobile device. Your response handler should check to see whether directLaunch or sendToDevice is present. It should also check the status code and an error code to determine whether the attempted action was successful.

In all cases where Alexa for Apps attempts the sendToDevice experience, your skill can resume interaction with the customer.

Sample response for Direct launch

{
  "type": "SessionResumedRequest",
  "requestId": "<string>",
  "timestamp": "<string>",
  "locale": "<string>",
  "cause": {
    "type": "ConnectionCompleted",
    "token": "1234",
    "status": {
      "code": "200",     // This is the status code for the connection call itself
      "message": "OK"
    },
    "result": {
      "directLaunch": {    // This indicates that Alexa attempted a direct launch
        "primary": {
           "status": "FAILURE",
           "errorCode": "APP_INCOMPATIBLE"  // The primary link failed
        },
        "fallback": {
           "status": "SUCCESS"  // Fallback was successful
        }
      }
    }
  }
}

Sample response for Send to phone

{
  "type": "SessionResumedRequest",
  "requestId": "<string>",
  "timestamp": "<string>",
  "locale": "<string>",
  "cause": {
    "type": "ConnectionCompleted",
    "token": "1234",
    "status": {
      "code": "200",
      "message": "OK"
    },
    "result": {
      "sendToDevice": {
        "status": "SUCCESS"
      }
    }
  }
}

Step 3: Test and Publish your skill