Call Alexa Service APIs Out of Session With Node.js

You can use some of the Alexa service APIs outside of your skill logic. For example, you can use the Skill Messaging API to send messages to a skill. When using a service outside of your skill logic, you must configure the skill so that when the service sends out-of-session requests, the skill can handle the events sent through the requests.

When the service call is out of session for the skill context, you need to provide an access token that has service-dependent scope. To perform the service call without using the SDK, you would need to do the following to obtain and use an access token:

  • Obtain the required access token by using the ClientId and ClientSecret as shown on the Permissions tab in developer console, calling the Alexa endpoint with proper scope. For more details on obtaining the required access token, see Request Format to Obtain Access Token.
  • Call the service API with appropriate input parameters along with the required access token.

The SDK provides a service client that combines the steps into a single service call, reducing the boilerplate code needed to get the service call running. The service client takes the ClientId and ClientSecret, injects the required scope for the service, retrieves an access token, uses the access token to call the Alexa service, and provides the response object.

The service clients aren't available under serviceClientFactory in the handlerInput object because the service clients are out of context of a skill session. For details on the services you can call in a skill session context, see Calling Alexa Service APIs.

Available service clients

The following are the service clients for services that you can use outside of your skill logic:

  • Proactive Events: ask-sdk-model.services.proactiveEvents.ProactiveEventsServiceClient
  • Skill Messaging: ask-sdk-model.services.skillMessaging.SkillMessagingServiceClient

The service clients must have instances of ask-sdk-model.services.ApiConfiguration and ask-sdk-model.services.AuthenticationConfiguration in the constructor.

AuthenticationConfiguration

The ask-sdk-model.services.AuthenticationConfiguration is the configuration class that accepts the ClientId and ClientSecret for retrieving the access token from Alexa.

ApiConfiguration

The ask-sdk-model.services.ApiConfiguration is required for configuring the apiClient that you use to make the service calls.

ProactiveEventsServiceClient

The Proactive Events API enables you to send events to Alexa that represent data that might interest a customer. Upon receiving an event, Alexa proactively delivers the information to customers subscribed to receive the events.

The Proactive Events API currently supports one proactive channel, which is Alexa Notifications.

Type definition

class ProactiveEventsServiceClient {
    createProactiveEvent(createProactiveEventRequest: services.proactiveEvents.CreateProactiveEventRequest, stage: services.proactiveEvents.SkillStage): Promise<void>;
}

interface CreateProactiveEventRequest {
    'timestamp': string;
    'referenceId': string;
    'expiryTime': string;
    'event': services.proactiveEvents.Event;
    'localizedAttributes': Array<any>;
    'relevantAudience': services.proactiveEvents.RelevantAudience;
}

type SkillStage = 'DEVELOPMENT' | 'LIVE';

interface Event {
    'name': string;
    'payload': any;
}

interface RelevantAudience {
    'type': services.proactiveEvents.RelevantAudienceType;
    'payload': any;
}

type RelevantAudienceType = 'Unicast' | 'Multicast';

For more details on the models, see Module proactiveEvents.

Code sample

The following example shows how to send a sample weather proactive event to Alexa, which multicasts it to all users registered on the skill.

const Alexa = require('ask-sdk-core');
const { ProactiveEventsServiceClient } = require('ask-sdk-model').services.proactiveEvents;

function createNotification() {
    const clientId = 'xxxx';
    const clientSecret = 'xxxx';
    const userId = 'xxxx';

    const apiConfiguration = {
        apiClient: new Alexa.DefaultApiClient(),
        apiEndpoint: 'https://api.amazonalexa.com'
    }
    const authenticationConfiguration = {
        clientId,
        clientSecret
    }

    const proactiveClient = new ProactiveEventsServiceClient(apiConfiguration, authenticationConfiguration);
    const weatherEvent = {
        name: 'AMAZON.WeatherAlert.Activated',
        payload: {
            weatherAlert: {
                alertType: 'SNOW_STORM',
                source: 'localizedattribute:source'
            }
        }
    }
    const relevantAudience = {
        type: 'Multicast',
        payload: {}
    }

    const now = new Date();
    const createEvent = {
        timestamp: now.toString(),
        referenceId: '1234',
        expiryTime: new Date(now.getTime() + 10000).toString(),
        event: weatherEvent,
        localizedAttributes: [{locale: 'en-US', source: 'Foo'}],
        relevantAudience
    }
    const stage = 'DEVELOPMENT';

    proactiveClient.createProactiveEvent(createEvent, stage);
}

SkillMessagingServiceClient

You can use the Skill Messaging API to send a message request to a skill for a specified user.

Type definition

class SkillMessagingServiceClient {
    sendSkillMessage(userId: string, sendSkillMessagingRequest: services.skillMessaging.SendSkillMessagingRequest): Promise<void>;
}

interface SendSkillMessagingRequest {
    'data': any;
    'expiresAfterSeconds'?: number;
}

For more details on the models, see Module skillMessaging.

Code sample

The following example shows a message sent to a skill for the purpose of reminders, where the skill has a handler for requests of type Messaging.MessageReceived.

const Alexa = require('ask-sdk-core');
const { SkillMessagingServiceClient } = require('ask-sdk-model').services.proactiveEvents;

function sendSkillMessaging() {
    const reminderId = 'xxxx';
    const clientId = 'xxxx';
    const clientSecret = 'xxxx';
    const userId = 'xxxx';

    const apiConfiguration = {
        apiClient: new Alexa.DefaultApiClient(),
        apiEndpoint: 'https://api.amazonalexa.com'
    }
    const authenticationConfiguration = {
        clientId,
        clientSecret
    }

    const proactiveClient = new SkillMessagingServiceClient(apiConfiguration, authenticationConfiguration);
    const message = {
        data: {
            reminderId,
        }
    }
    
    proactiveClient.sendSkillMessage(userId, message);
}

LwaServiceClient

Other out-of-session service clients use the LwaServiceClient to obtain the access token from Alexa, with the required scope specific to the service. Provided a specific scope, you can also use the LwaServiceClient natively to obtain access tokens.

Type definition

class LwaServiceClient {
    getAccessTokenForScope(scope: string): Promise<string>;
}

interface AccessTokenRequest {
    clientId: string;
    clientSecret: string;
    scope: string;
}

For more details on the models, see Module services.

Code sample

The following example shows how to obtain an access token for a scope alexa:abc.

const Alexa = require('ask-sdk-core');
const { LwaServiceClient } = require('ask-sdk-model').services;

function outOfSessionReminderUpdate() {
    const clientId = 'xxxx';
    const clientSecret = 'xxxx';
    const scope = 'alexa:abc';

    const apiConfiguration = {
        apiClient: new Alexa.DefaultApiClient(),
        apiEndpoint: 'https://api.amazonalexa.com'
    }
    const authenticationConfiguration = {
        clientId,
        clientSecret
    }

    const lwaServiceClient = new LwaServiceClient(apiConfiguration, authenticationConfiguration);
    const accessToken = lwaServiceClient.getAccessTokenForScope(scope);
}