APL Extensions


Extensions are optional enhancements to an Alexa Presentation Language (APL) runtime that provide additional sources of data, commands, and event handlers. Extensions provide additional functionality to APL, but a given extension might not be available on all devices.

Available extensions:

Request an extension

Before you can use an extension in an APL document, your skill must request it. For some extensions, you must do two steps:

  • Request the extension in the skill manifest.
  • Request the extension in the APL document.

Not all extensions must be included in the manifest. Refer to the documentation for the extension for the extension-specific requirements.

Request an extension in the skill manifest

For some extensions, you must declare the extension in the skill manifest before you can use it. In addition, some extensions have default behavior that you can turn on or off in the manifest.

Declare these extensions in the manifest in apis.custom.interfaces, in the ALEXA_EXTENSION interface. The ALEXA_EXTENSION interface has the following properties.

Name Type Description

type

String

Must be ALEXA_EXTENSION.

requestedExtensions

Array of objects

Contains an array of extensions you want to use in your APL document. Each object in the array has the uri property set to the URI for the extension to enable. The extension defines the uri. For example, for the smart-motion extension, the URI is alexaext:smartmotion:10.

See the documentation for the extension to determine its uri and whether it requires you to request the extension in the requestedExtensions property.

autoInitializedExtensions

Array of objects

Contains an array of extensions that you can configure with default behavior. This lets you turn on "no code" behavior for extensions that support it. Each object has two properties:

  • uri – The URI for the extension to configure. This must be the URI of an extension that supports default settings.
  • settings – A set of key/value pairs for each extension setting you can configure in the skill manifest.

For example, for the smart-motion extension, you can set a default wakeWordResponse in autoInitializedExtensions. Your skill then uses the specified settings and no further configuration is required in your APL document.

The following example illustrates the manifest configured for the smart-motion and entity-sensing extensions. In this example, the smart-motion extension uses turnToWakeWord as its default wake word response.

{
  "apis": {
    "custom": {
      "interfaces": [
        {
          "type": "ALEXA_EXTENSION",
          "requestedExtensions": [
            {
              "uri": "alexaext:smartmotion:10"
            },
            {
              "uri": "alexaext:entitysensing:10"
            }
          ],
          "autoInitializedExtensions": [
            {
              "uri": "alexaext:smartmotion:10",
              "settings": {
                "wakeWordResponse": "turnToWakeWord"
              }
            }
          ]
        }
      ]
    }
  }
}

For details about the settings you can configure for an extension, see the documentation for that extension. The smart-motion extension has settings you can configure in the skill manifest.

Request an extension in the APL document

To use the commands, properties, and event handlers from an extension, you must explicitly request the extension in your APL document or in an imported APL package. Then, before you use an extension in the document, verify whether the device supports the extension.

You request the set of extensions to load in the extensions property. The extensions property contains a list of objects, each with a name property you use to refer to the extensions, and the uri for the extension. The extension defines the specific uri. You set the name to the string value you want to use when referring to the extension.

For example, assume there is an extension that reads current weather information and has the URI "aplext:weather_info_deluxe:v10".

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "Weather",
      "uri": "aplext:weather_info_deluxe:v10",
      "required": true
    }
  ]
}

The APL document can check the whether the weather extension exists on the user's device by reading ${environment.extension.Weather}.

Each extension has a unique uri. The URI is defined by the extension and is documented with the extension. For example, the Backstack extension uses the uri "aplext:backstack:10".

APL attempts to load all extensions requested by the document and associated packages. A document can load the same extension using two different names; both names work for sending extension commands and registering extension event handlers. Using one name to request two different extensions fails and prevents the document from loading.

When the required property for a particular extension request is set to true and the extension isn't available or doesn't register, the document doesn't inflate. This behavior might not be what you want. A document that fails to connect to an extension is usually still usable at some level of reduced functionality. Set the required property to true only when you have a fallback plan if the document fails to load.

The extensions property in the data-binding context exposes the state of the requested and loaded extensions.

For more about how a document requests an extension, see the document extensions property. For more about getting the global properties from an extension, see the environment.extensions property.

Extension settings

The document settings property can contain settings information for the requested extension. The requested extension retrieves settings information using the aliased name of the extension. APL loads the extension before processing and displaying the document. With APL version 2023.3 and later, APL supports data-binding expressions for settings. However, the data-binding expressions are limited to the properties available in the initial data-binding context. You can get information about the device, such as environment, but not data from a data source.

For example, consider a runtime extension that enables customized metric logging. The metric-logging extension could use settings to configure core information about the client:

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "ManyMetrics",
      "uri": "aplext:many_metrics.somebigcompanyname.com:1.2"
    }
  ],
  "settings": {
    "ManyMetrics": {
      "applicationName": "MyMovieSearcher",
      "applicationCategory": "Entertainment",
      "applicationAuthor": "Generic Movie Corp"
    }
  }
}

In this example, the document requests the extension under the alias "ManyMetrics". The runtime is responsible for checking for the presence of that extension and passing the "settings.ManyMetrics" object to it if it exists.

A single extension might be requested multiple times by a single document under different aliases. This can occur if the same extension is listed multiple times in the document extensions property or if the same extension is requested by different packages. Each alias is represented in the "environment.extension" environment property. Because a given extension can only be loaded once, any extension settings are merged together before the extension is loaded. The settings are merged in package order, so later packages (and the document) override settings defined in earlier packages.

It can be difficult to identify setting-merge errors, so it is recommended that extensions with settings should only requested by a single package or by the main document.

Extension commands

An "extension" command is a custom command defined by a registered extension. Extension commands inherit all the base command properties, so they automatically support type, description, delay, screenLock, sequencer, and when. The registered extension may specify additional required or optional properties in the extension command.

Extension commands are invoked in the same way as regular commands. The type of the command should be set to the "EXTENSION_NAME:COMMAND_NAME", where EXTENSION_NAME is the name property used when requesting the extension and COMMAND_NAME is the extension's defined command name. In other words the name property defined when requesting an extension is used as a namespace when invoking the extension command.

As an example, assume an APL-enabled fishtank with the FishFeeder extension (URI="aplext:fishfeeder:10"). This extension provides a custom command named "Feed" that requires the "amount" property be set to a number between 1 and 100 (grams of fish food). The following examples show how an APL document can use this command:

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "Fish",
      "uri": "aplext:fishfeeder:10"
    }
  ],
  "mainTemplate": {
    "items": [
      {
        "when": "${environment.extension.Fish}",
        "type": "Container",
        "data": [
          10,
          25,
          100
        ],
        "items": {
          "type": "TouchWrapper",
          "items": {
            "type": "Text",
            "text": "Feed my fish ${data} grams of food"
          },
          "onPress": {
            "type": "Fish:Feed",
            "amount": "${data}"
          }
        }
      },
      {
        "description": "Fallback in case no FishFeeder extension",
        "type": "Text",
        "text": "No FishFeeder available"
      }
    ]
  }
}

The above example requests the "aplext:fishfeeder:10" extension. If the extension is installed, it creates a list of three buttons; if not installed it shows a warning message. Each button generates a Feed custom event and specifies the amount of food to dispense.

Extension event handlers

APL extensions can send custom events to the document. These custom events are received in the document by extension event handlers. Each APL extension may define any number of custom events. Refer to the extension's documentation to find the names of the events and if they are invoked in normal or fast mode.

The event received in the event handler has the form:

"event": {
  "source": {
    "type": "Document",
    "handler": NAME,   // Name of the handler
    "id": null,        // No value reported
    "uid": null,       // No value reported
    "value": null      // No value reported
  }
}

The extension event handler may report additional property values at the same level as the "event" property. For illustration we will assume an extension "aplext:remotebutton:13" supporting a wireless physical button. When the button is pushed, the extension sends an "OnPress" event containing the properties "buttonName" and "buttonColor" (we'll assume that the button has a name and randomly changes color). The data-binding context generated by this event is:

{
  "buttonName": "BigRedButton",  // or whatever value was passed from the button
  "buttonColor": "red",   // or whatever color was passed from the button
  "event": {
    "source": {
      "type": "Document",
      "handler": "OnPress",
      "id": null,        // No value reported
      "uid": null,       // No value reported
      "value": null      // No value reported
    },
  }
}

Named event handlers at the top-level of the document receive the extension events. The name of the event handler is "EXTENSION_NAME:EVENT_NAME", where the EXTENSION_NAME is the name property used when loading the extension and the EVENT_NAME is defined by the extension. For example:

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "Button",
      "uri": "aplext:remotebutton:13"
    }
  ],
  "mainTemplate": {
    "items": {
      "type": "Text",
      "id": "MyTextBox",
      "text": "${environment.extension.Button ? 'No button has been pushed' : 'Buy a button!'}",
      "color": "gray"
    }
  },
  "Button:OnPress": [
    {
      "type": "SetValue",
      "componentId": "MyTextBox",
      "property": "text",
      "value": "The ${buttonName} was pushed"
    },
    {
      "type": "SetValue",
      "componentId": "MyTextBox",
      "property": "color",
      "value": "${buttonColor}"
    }
  ]
}

In the above example the "aplext:remotebutton13" handler has been assigned the name "Button". The extension sends an event named "OnPress", so the document-level event handler is "Button:OnPress".

Extension live data

APL extensions may add custom live data objects to the global data-binding context for the document. Unlike the environment.extension environment property, which only reports the static state of the extension on load of the document, these live data objects may change over the lifecycle of the document depending on the extension's use cases. Each APL extension may define any number of custom live data objects.

Live data objects implemented by the extension SHOULD be exposed to the document through the extension settings properties for indicating the document's intended name for the data object in the global data-binding context.

If a document does not provide a valid settings property for any of the extension's available live data objects, then those objects should NOT be added to the data-binding context.

Refer to the extension's documentation to find information on the associated settings properties, format, and intended usage of any live data provided by the extension.

As an example, assume an APL-enabled fishtank with the FishFeeder extension (URI="aplext:fishfeeder:10"). The FishFeeder extension has a live data object available to expose to the document's data-binding context with the following format:

{
  "rayFinnedFish":[],
  "lobeFinnedFish":[],
  "lampreys":[]
}

The extension should also provide a settings property by which the document can define the name of the available live data object to use in data-binding. Here's an example of how the extension should document that data object.

Name Type Default Description
fishTypeDataName String null Name to use when adding fishType live data object to the data-binding context.

The extension's live data object can then be accessed in the APL document by providing a value for the extension's fishTypeDataName settings property as defined above:

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "Fish",
      "uri": "aplext:fishfeeder:10"
    }
  ],
  "settings": {
    "Fish": {
      "fishTypeDataName": "fishType"
    }
  },
  "mainTemplate": {
    "items": [
      {
        "when": "${environment.extension.Fish}",
        "type": "Container",
        "items": [
          {
            "type": "Text",
            "text": "There are ${fishType.rayFinnedFish.length} Ray Finned Fish in the tank right now."
          }
        ]
      },
      {
        "description": "Fallback in case no FishFeeder extension",
        "type": "Text",
        "text": "No FishFeeder available"
      }
    ]
  }
}

In the above example the data-binding name "fishType" has been defined for the live data object exposed by the "aplext:fishfeeder:10" extension. The extension adds the live data object fishType to the global data-binding context as "fishType".

Extension image filters

An APL extension can define custom image filters to modify images. Invoke an extension image filter the same way as a regular filter by including the filter in the filters property of the Image component. Set the type of the filter to "EXTENSION_NAME:FILTER_NAME". The name property defined when requesting an extension is used as a namespace when invoking a filter provided by the extension.

For example, consider an extension that provides the "Canny" filter for running the Canny edge detection algorithm on an image. The algorithm takes two inputs: a lower threshold and an upper threshold, both normalized values from 0.0 to 1.0. The following table shows the properties used by this filter.

Property Type Default Description
type Canny REQUIRED Defines the type of filter
lower Number 0.1 Lower bound for edge detection
upper Number 0.9 Upper bound for edge detection
source Integer -1 Index of the source image

The following example shows how an APL document could use this filter to show the edges with a yellow tint.

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "Edges",
      "uri": "aplext:edgedetectorfilters:11"
    }
  ],
  "mainTemplate": {
    "items": {
      "type": "Image",
      "width": "100%",
      "height": "100%",
      "scale": "best-fit",
      "source": "https://example.com/images/imageToProcess.png",
      "filters": [
        {
          "type": "Color",
          "color": "yellow"
        },
        {
          "type": "Edges:Canny",
          "lower": 0.2,
          "upper": 0.7,
          "source": -2
        },
        {
          "type": "Blend",
          "mode": "multiply"
        }
      ]
    }
  }
}

Was this page helpful?

Last updated: Nov 28, 2023