Get started with Amazon Alexa Skills Proactive Events API

Get started with Amazon Alexa Skills Proactive Events APISergey SmolnikovBlockedUnblockFollowFollowingJun 10Amazon Alexa Skills are serverless applications, which allows people interact with Alexa enabled devices with voice or on-screen controls — voice and on-screen assistance.

Amazon Echo DotUsually it is expected that a user starts interaction, triggering an Alexa Skill to respond on commands or questions.

This way the user decides when to start interaction.

Request-respond voice interactionHowever, in some cases users would have to regularly request for updated or new information.

In such cases — notifications, initiated by an Alexa device, could be preferable.

Proactive Events API provide this option.

Short video presentation provides quick introduction about Alexa and Proactive Events.

To start with Proactive Events API, we need to create a simple Alexa Skill and AWS Lambda function, which will be used as a playground in this article.

This article and video tutorial maybe used as a guide.

Setup ASK-CLIInstall ASK CLI — Alexa Skills Kit command line tool.

It is needed, because Alexa Skill Management API (SMAPI) is used for setup and some features, supported in SMAPI, are not supported on the Amazon Developer Portal.

The skill events feature is one of them, it can only be managed with ASK CLI, and not with the Amazon Developer Portal.

sudo npm install -g ask-cliInitialize ASK CLI.

This will setup an access to API services.

Please find more details in the Manage Credentials with ASK CLI guideline.

ask initDuring the initialization process a browser with a login page will be automatically opened.

Please follow the instruction to fill in the requested AWS Access Key ID and AWS Secret Access Key.

Alternative of using ask init is to configure AWS CLI with admin user’s AWS Access Key ID and AWS Secret Access Key we will useAdd events to skillWith ASK CLI — proactive events need to be added to the manifest of the skill.

Select one or several event schemas to be sent as notifications (they have different payload structures and properties).

List of event schemas is regularly extending, please vote for missed schemas and features.

Currently available event schemas:AMAZON.

WeatherAlert.

ActivatedAMAZON.

SportsEvent.

UpdatedAMAZON.

MessageAlert.

ActivatedAMAZON.

OrderStatus.

UpdatedAMAZON.

Occasion.

UpdatedAMAZON.

TrashCollectionAlert.

ActivatedAMAZON.

MediaContent.

AvailableAMAZON.

SocialGameInvite.

AvailableGet the skill manifest as a json-fileask api get-skill -s skill_id > skill.

jsonOpen this file in your favourite text editorAdd notification.

write permission to the manifest section"permissions": [{"name": "alexa::devices:all:notifications:write"}],Add selected event names to the manifest section.

In this example — two event schemas were selected: AMAZON.

OrderStatus.

Updated and AMAZON.

MediaContent.

Available.

Put the Alexa Skill AWS Lambda function ARN to the endpoint property (more details about endpoints and Lambda functions in this guideline)Revise carefully double quote characters, which may be replaced by some editors with similar alternative characters.

Update the skill with the corrected manifest (put the actual skill_id in the command)ask api update-skill -s skill_id -f skill.

jsonCheck skill status — if it is updated correct, status will contain SUCCESSask api get-skill-status -s skill_idSkill Client Id and Client SecretDeveloper Console for the Alexa Skill should contain now Client Id and Client Secret for this skillOpen an Alexa mobile app (iOS, Android) or Alexa web-dashboard.

Open the skill and enable itAlexa Skill should have now a section THIS SKILL NEEDS PERMISSION TO ACCESS with Alexa NotificationsHit the SETTINGS button, and the MANAGE PERMISSIONS buttonTurn on the switch to allow notifications, hit the SAVE PERMISSIONS button to save changesNow the Alexa device with this skill can receive Proactive events, specified in the skill manifest.

Events can be sent by regular HTTP clients.

For example: Postman, cUrl, IntelliJ IDEA “HTTP Client”-plugin, etc.

This is a test with Postman client.

Request a bearer tokenIn the Postman — hit a “+” tab to add a new request tab, select POST as a request type and enter the bearer token API URLhttps://api.

amazon.

com/auth/o2/tokenOpen the Headers tab and add a key Content-Type with a valueapplication/x-www-form-urlencodedOptional Bulk Edit mode allows to fill-in key-value pairs as a text, Key-Value Edit mode fills-in pairs as a tableOpen the Body tab and add following key-values, with selected option x-www-form-urlencoded.

Put actual client_id and client_secret taken from Developer Console, Build tab, PERMISSIONS tab (described earlier)Key:"grant_type" Value:"client_credentials"Key:"client_id" Value:"amzn1.

application-oa2-client.

a478.

"Key:"client_secret" Value:"ef1286b2.

"Key:"scope" Value:"alexa::proactive_events"Note: the value of the key scope contains double semicolon, which might confuse some HTTP clients, when setup request with bulk/text edit mode.

{ "access_token”:”accessToken”, "expires_in":3600, "scope":"alexa::proactive_events", "token_type":"Bearer" }Hit the Send button an with Pretty/JSON options — look at the respond, which should contain the access_tokenThis token is expired in 3600 second (in one hour).

After this period a new request will get respond-code 403 (Unauthorized) — new token need to be requested to proceed with further requests.

This bearer token should accompany each requests to the event API.

This API has separate endpoints for three regions, and also development and production environments.

With development environment endpoints events will not be send to real customers, it is made for testing purpose:Developmenthttps://api.

amazonalexa.

com/v1/proactiveEvents/stages/development (North America)https://api.

eu.

amazonalexa.

com/v1/proactiveEvents/stages/development (Europe)https://api.

fe.

amazonalexa.

com/v1/proactiveEvents/stages/development (Far East)Productionhttps://api.

amazonalexa.

com/v1/proactiveEvents/ (North America)https://api.

eu.

amazonalexa.

com/v1/proactiveEvents/ (Europe)https://api.

fe.

amazonalexa.

com/v1/proactiveEvents/ (Far East)Send Proactive notificationIn the Postman application — hit another “+” tab to add a new request tab, select POST as a request type and enter the development event API URLhttps://api.

amazonalexa.

com/v1/proactiveEvents/stages/developmentOpen the Headers tab and add a key Content-Type with a valueapplication/jsonAdd another key Authorization with a valueBearer Atc|.

Where “Atc|…” is a value from the access_token property of the response from bearer token API, received earlier.

Note: there is a space between the term Bearer and the token value.

Open the Body tab and add event’s json-content, with the selected option raw{ .

.

.

"event": { "name": "AMAZON.

MediaContent.

Available", .

.

.

"localizedAttributes": [ { "locale": "en-US", "providerName": "Alexa Events Example", "contentName": "Some event" } ], "relevantAudience": { "type": "Multicast", "payload": {}` }}This body content corresponds to the AMAZON.

MediaContent.

Available schema and in this example a media-related event is:“Alexa Events Example” (“providerName”) notifies that a new “episode” (“contentType”) of “Some event” (“contentName") will take place via “air” (“method”) at “8pm June 8th 2019 EDT” (“startTime”).

This notification will expire at “2pm June 8th 2019” (“expiryTime”).

Hit the Send button.

If the bearer token and event content are correct — the respond-code will be 202 (Accepted) and the content-length is zero (no respond-body).

Turned on Alexa device makes the notification sound and start blinking.

To read notifications — ask, “Alexa, what are my notifications?” or “Alexa, what did I miss?”, and all notifications, collected by this time, will be pronounces.

Notice that time will be pronounced not for the Alexa device time-zone.

I guess it corresponds to the API region or its configured AWS Lambda function, or a skill region — I have not found this certainly.

Date-time values should be in ISO 8601 format, ended with “Z” (for UTC) or with time-zone shift period“startTime”: “2019–06–10T00:00:00Z"startTime": "2019-06-10T05:00:00+05:00"After a notification is read, it is archived in the cloud for few hours and then automatically deleted.

To read those archived notifications — ask Alexa: “Alexa, what are my old notifications?”Notifications can be deleted with the command “Alexa, delete all my notifications”.

FailuresIf something is wrong with the request — the respond-code will have 4** code and respond-body will contain error description.

Examples of such issues:Set invalid “expiryTime”.

It should be at least 5 minutes in the future and no more than 24 hours after the current time:Set invalid property value, not supported in the event schema.

Look through the “message” value, which contains information, relevant to a particular issue.

In value characters “.” can be replaced with new-line, “”” with double-quote, then it become more readable.

But even without such correction the issue can be figure-outAs an example of correction in the Visual Studio Code – characters can be replaced with Regular Expression option.

Fix new lines:Fix double-quotesSave the corrected file with json-extension gives some highlight in additionEvent audience optionsEvent can be sent to all particular skill users (those, who allowed notifications from this skill) or to specific users, using their user-id.

The property “relevantAudience” controls this option with values “Multicast” and “Unicast”.

Send en event to all users (broadcasting or multicasting):"relevantAudience": { "type": "Multicast", "payload": {} }Send en event to specific user:"relevantAudience": { "type": "Unicast", "payload": { "user": "specific-user-Id" } }To track user-ids — subscribe on an event, notifying that a user turned on/off proactive notifications.

To make the skill’s Lambda function receive this event — add following subscription section to the Alexa skill manifest (to the “events” property) and update the manifest with the ASK-CLI"subscriptions": [ { "eventName": "SKILL_PROACTIVE_SUBSCRIPTION_CHANGED" }]Update the skill with the corrected manifest (put the actual skill_id in the command)ask api update-skill -s skill_id -f skill.

jsonAdd a request handler to the Alexa Skill AWS Lambda function to handle this event (the example code extends an Lambda function, created in this tutorial)Add the instance of this handler to the SkillStreamHandler builderBuild the jar-file and upload it to the Lambda function.

Open an Alexa mobile app or Alexa web-dashboard, open the skill, hit the SETTINGS button and turn on or off the switch to allow notifications, hit the SAVE PERMISSIONS button to save changesSubscribe to proactive events request in the CustomProactiveSubscriptionChangedRequestHandler.

Request body contains “subscriptions” as “eventName” list:proactiveSubscriptionChangedRequest.

getBody().

getSubscriptions()Un-subscribe from proactive events request in the CustomProactiveSubscriptionChangedRequestHandler.

Request body does not existproactiveSubscriptionChangedRequest.

getBody() == nullPick “userId” and a list of event names to manage individual notificationsString userId = input.

getRequestEnvelope().

getContext().

getSystem().

getUser().

getUserId();//userId looks like "amzn1.

ask.

account.

AFE2.

"and send notifications to particular users with and “Unicast” “relevantAudience”"relevantAudience": { "type": "Unicast", "payload": {"user": "amzn1.

ask.

account.

AFE2.

"} }Possible issuesAttempt to send a notification to a particular user, which has not allowed notifications for the skill — returns an error:“Can’t find any subscription for stage=development, skillId=amzn1.

ask.

skill.

e2af…, topicId=AMAZON.

MediaContent.

Available”In the response message: “stage” can be “development” or “live”, corresponding “skillId” and an event schema name, for which event has been sent.

Following issue might happen with a request about an event to a particular user, with valid bearer-token and correct userId, but this bearer-token is for different skill then the userId generated for.

Maybe there are other causes for this issue.

{ “type”: “Forbidden”, “message”: “No enablement for clientId: amzn1.

application-oa2-client.

d6ad.

, userId: amzn1.

ask.

account.

AFE.

”}Event ProactiveSubscriptionChanged will not be send when a user disables the skill.

When this user enables this skill again — the user is assigned with a new userId.

Because of this it makes sense to track at least an event “AlexaSkillEvent.

SkillDisabled”.

also events about activate/deactivate skill, enable/change/disable permissions (including permission to receive proactive notifications).

To make the skill’s Lambda function receive these events — add following subscription section to the Alexa skill manifest (to the “events” property) and update the manifest with the ASK-CLI"subscriptions": [ { "eventName": "SKILL_ENABLED" }, { "eventName": "SKILL_DISABLED" }, { "eventName": "SKILL_PERMISSION_ACCEPTED" }, { "eventName": "SKILL_PERMISSION_CHANGED" }]RequestHandlers are similar to the CustomProactiveSubscriptionChangedRequestHandler — all they implement interfaces with names, corresponding to event names (e.

g.

PermissionAcceptedRequestHandler), which has boilerplate code in the default method implementations@Overridedefault boolean canHandle(HandlerInput handlerInput) { if (handlerInput.

getRequest() instanceof PermissionAcceptedRequest) { return canHandle(handlerInput, (PermissionAcceptedRequest)handlerInput.

getRequest()); } return false;}@Overridedefault Optional<Response> handle(HandlerInput handlerInput) { return handle(handlerInput, (PermissionAcceptedRequest)handlerInput.

getRequest());}Technically boilerplate logic from these handlers can be merged to one handler.

Final skill manifest with all these events would look like thisUsing the code build the jar-file an upload it to the Lambda function, connected to the Alexa Skill.

There is pre-build release with jar-file for this function.

Enable/disable the skill and turn on/off notification settings in the mobile app of web-dashboard and look at the Cloud Watch log for the Lambda function to see activity.

Note: events can arrive out of order, use the timestamp in the event to correctly record the latest subscription state for a customer.

Language and regionCreating Alexa Skills and Lambda for their backend has options for different regions.

AWS Lambda should be configured for each geographic region where the skill requires permissions.

For example, a skill sends change report events in the US and the UK, AWS Lambdas need to be configured for both North America and Europe.

For training and evaluation purpose it would be easier to make skills for US language, Lambda function for N.

Virginia (us-east-1) region.

Source codePublished on GitHub.

Pre-build release with jar-file.

Participate in API improvementsYou can vote for features and missed event types on the Alexa Skills developer forum.

Amazon Web Services, and AWS Lambda are trademarks of Amazon.

com, Inc.

or its affiliates in the United States and/or other countries.

.. More details

Leave a Reply