APL Data Store Extension


Use the data store extension in your Alexa Presentation Language (APL) document to access data stored in the data store on a device. The data store is an area installed locally to a device that contains data an APL document can access with data binding. Widgets use the data store to display content without sending requests to your skill and waiting on a response.

You must use the data store extension to use data-binding expressions that bind to data in the data store.

Extension summary

Minimum supported APL version

APL 1.4

Extension URI

alexaext:datastore:10

Settings

Environment properties

Live data properties

Commands

Event handlers

Required in skill manifest?

Yes. Add alexaext:datastore:10 to the requestedExtensions property in the ALEXA_EXTENSION object in the manifest.apis.custom.interfaces array.

Auto-initialized settings?

No

About the data store and the data store extension

The data store extension is available on devices that support on-device data storage for skill data. These devices include all devices that support widgets.

Data store hierarchy

The data store on a device stores data as an object or an array of objects. The data store organizes these objects or arrays in a hierarchy consisting of a region, namespace, and key.

Data store hierarchy
Data store hierarchy

The following list provides definitions for the data store hierarchy terms:

  • Region – Globally isolated storage partition in the data store that stores data. Your skill has access to a specific region based on the skill ID. Data store commands and operations set this region for you automatically. You don't specify this location directly.
  • Namespace – Partition within the region. You define the data store namespaces to use with your skill.
  • Key – Unique identifier within a namespace. You define the keys to use within a namespace.
  • Object – Content to store, in the form of an object or an array of objects. You access a data store object with the hierarchical identifier that consists of the region, namespace, and key.

Data store security

The data store prevents unauthorized access to stored content. To read or write objects in the data store, an APL document must have read or write permissions. The following list shows the security policies that apply at each level in the data store hierarchy:

  • Region – If the APL document has read or write permissions at the region level, the document can read or write content for all keys in all namespaces in the region. Your skill has read and write access to a region based on the ID of your skill. Your skill can't access the data store regions for any other skills.
  • Namespace – If the APL document has read or write permissions at the namespace level, the document can read or write content for all keys in the namespace.
  • Key – If the APL document has read or write permissions at the key level, the document can read or write the object or array stored against the single key in the data store.

Enable the data store extension

Enable the extension in your skill manifest and in the APL document. You must include the extension in both places to use it. Then, configure the document-level settings for the extension in the document settings property.

The URI for the data store extension is alexaext:datastore:10.

To add the extension to the skill manifest, add alexaext:datastore:10 to the requestedExtensions property in the ALEXA_EXTENSION object in the manifest.apis.custom.interfaces array.

The following example shows how to enable the extension in the skill manifest.

{
  "manifest": {
    "apis": {
      "custom": {
        "interfaces": [
          {
            "type": "ALEXA_EXTENSION",
            "autoInitializedExtensions": [],
            "requestedExtensions": [
              {
                "uri": "alexaext:datastore:10"
              }
            ]
          }
        ]
      }
    }
  }
}

For details, see Request an extension in the skill manifest.

To request the extension in your APL document, add alexaext:datastore:10 to an object in the extensions array in your document and assign it a name. You use this name to refer to the extension in your document.

The following example requests the data store extension and gives it the name DataStore.

Copied to clipboard.

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "DataStore",
      "uri": "alexaext:datastore:10"
    }
  ]
}

For details about requesting an APL extension in the APL document, see Request an extension in the APL document.

Verify device support for the data store extension

In your document, use the environment.extension property to determine whether the device supports the data store extension. For example, if you use DataStore for the name in the extensions property, the following data-binding expression returns true when the device supports the data store.

${environment.extension.DataStore}

Extension settings

The following table shows the settings for the data store extension.

Name Type Default Description

dataBindings

Object

[ ]

Object array to define data store bindings.

To configure these settings in your APL document, use settings.AssignedName, where AssignedName is the name you assigned the extension in the extensions property.

The following example assigns the extension the name DataStore, and then sets the dataBindings property.

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "DataStore",
      "uri": "alexaext:datastore:10"
    }
  ],
  "settings": {
    "DataStore": {
      "dataBindings": []
    }
  },
  "mainTemplate": {}
}

dataBindings

An array of objects. Each object in this array defines a live data DataBinding object with the specified dataBindingName. The DataBinding object represents an object in the data store. You use the dataBindingName in the data-binding expressions in your document to retrieve data from that object in the data store.

Each definition in the dataBindings array must have the properties shown in the following table.

Name Type Default Description

namespace

String

Required

Set to the data store namespace that stores the object to access. Must be unique within the region for your skill. The namespace must be a be a non-empty string that meets the follow requirements:

  • Fewer than 512 bytes
  • Doesn't begin with the string "sqlite_"
  • Doesn't match any SQLite reserved keywords
  • Doesn't start with an underscore (_)
  • Allowed character set: [_ - . a-z A-Z 0-9]

The namespace name contributes to the data store storage allocated to your skill. For details about limits, see Data store limits.

key

String

Required

Set to the data store key that identifies the object to access. This key should be within the specified namespace. The key must be a non-empty string that meets the following requirements:

  • Fewer than 512 bytes
  • Doesn't start with an underscore (_)
  • Allowed character set: [_ - . a-z A-Z 0-9]

The key name contributes to the data store storage allocated to your skill. For details about limits, see Data store limits.

dataBindingName

String

Required

Set to a name to use to access the DataBinding object. The data store extension adds this name to the data-binding context available to your document. You use this name in your data-binding expressions to access the data in the object stored at the namespace and key.

dataType

String

object

Data type for the object to access. Allowed values: OBJECT, ARRAY.

startIndex

Number

0

Applies when dataType is ARRAY. Specifies the starting index for a range of items from the array stored at the specified namespace and key. The live data DataBinding property initializes to a sub-array containing elements starting with startIndex and ending with endIndex.

endIndex

Number

–1

Applies when dataType is ARRAY. Specifies the ending index for a range of items from the array stored at the specified namespace, and key. The live data DataBinding property initializes to a sub-array containing elements starting with startIndex and ending with endIndex.

namespace and key

Set these properties to reference the object you want to access in your data-binding expressions. You define the namespace and key for your data.

The following example shows a data binding that specifies a namespace called LocationWeather and a key called DS_Weather.

{
  "settings": {
    "DataStore": {
      "dataBindings": [
        {
          "namespace": "LocationWeather",
          "key": "weather",
          "dataBindingName": "DS_Weather"
        }
      ]
    }
  }
}

dataBindingName

Set to a name to use to access the DataBinding object. The data store extension adds this name to the data-binding context available to your document. You use this name in your data-binding expressions to access the data in the object stored at the specified namespace and key in the data store.

The previous example showed a dataBindingName set to DS_Weather. To access data in the weather object, use this name in your data-binding expressions: ${DS_Weather.propertyName}, where propertyName is a property in the stored object. For a full example, see Example: Configure dataBindings and access data.

The extension always creates a DataBinding object with the specified dataBindingName, regardless of whether an object exists in the data store at the specified namespace and key.

  • If the object doesn't exist, the provided dataBindingName is set to null.
  • If the object exists, the provided dataBindingName is set to the object.

dataType

Data type of the item stored in the data store. Can be OBJECT or ARRAY.

startIndex, endIndex

The startIndex and endIndex properties apply when dataType is ARRAY. The properties specify the starting and ending index values for a range of items from the array stored at the specified namespace and key. When you set these properties, the live data DataBinding object initializes to a sub-array containing elements starting with startIndex and ending with endIndex.

The range includes the element at startIndex and the element at endIndex.

The startIndex and endIndex properties are ignored when the dataType is OBJECT.

You can modify the range of elements loaded into the DataBinding object with the UpdateArrayBindingRange command.

Example: Configure dataBindings and access data

The following example shows the relationship between the content stored in the data store, the dataBindings setting, and the data-binding expressions in your document. Assume your skill writes data to the data store at the following location within the region provided for your skill:

  • Namespace: LocationWeather
  • Key: weather

Your skill uses the Data Store REST API to add the following content to the data store on a device.

{
  "location": "Seattle, WA",
  "details": {
    "temperature": "5 °C",
    "precipitation": "20%",
    "humidity": "70%",
    "wind": "4 km/h"
  }
}

In your document, you configure the data store extension with the following item in dataBindings.

{
  "settings": {
    "DataStore": {
      "dataBindings": [
        {
          "namespace": "LocationWeather",
          "key": "weather",
          "dataBindingName": "DS_Weather"
        }
      ]
    }
  }
}

With this configuration, the expression ${DS_Weather.location} returns the string "Seattle, WA".

The following example shows an APL document for a widget that uses this configuration to display the weather data stored in the data store.


If your skill later uses the Data Store REST API to update the data store with new weather information, the widget updates to display the new data. To simulate a data store update in the code sandbox:

  1. Click the Data Store tab.
  2. Click Edit Data Store.
  3. Enter a data store command in in the Commands pane. The example defaults to a sample PUT_OBJECT command that changes the temperature, precipitation, and humidity values.
  4. Click Execute Commands to send the command.

Environment properties (static)

The data store extension adds the following static environment properties.

Name Type Description

version

String

The data store extension version.

Access environment properties in the data-binding context with environment.extension.AssignedName where AssignedName is the name you assigned the extension in the extensions property.

For example, ${environment.extension.DataStore.version} returns the extension version, assuming you assigned the extension the name DataStore.

For more details about the environment.extension property in the data-binding context, see extension.

Live data properties

The data store extension adds live data properties to the data-binding context. Live data properties are data objects that can change during the lifecycle of the APL document.

For more details about live data, see Extension live data.

DataBinding

The data store DataBinding live data object represents an object or array in the data store at a specific namespace and key, within the region provided for your skill.

The properties of the DataBinding depend on the structure of the object or array in the data store. To access the data, use the dataBindingName for the object configured in the extension settings.

For an example, see Example: Configure dataBindings and access data.

Commands

The data store extension adds new extension commands.

To run a data store command, set the type property for the command to AssignedName:CommandName, where AssignedName is the name you assigned the extension in the extensions property. For example, if you assign the extension the name DataStore, you can run the WatchObject command with DataStore:WatchObject.

GetObject

The GetObject command retrieves data store object. The command is asynchronous. After you run this command, the OnObjectReceived handler returns the requested object.

The following table shows the properties of this command.

Property Type Default Description

namespace

String

Required

Name of namespace within the region for your skill.

key

String

Required

Name of key in the provided namespace.

token

String

""

Optional token you provide. The OnObjectReceived event handler includes this token when it returns the requested object.

The following example runs the GetObject command when the widget initially inflates. The OnObjectReceived handler then uses a SetValue command to set the value of the location bind variable, which then displays in the Text component. This example doesn't use the live data DataBinding property, so if you run a data store command such as PUT_OBJECT to update the data store, the value displayed in the widget doesn't change.


WatchObject

The WatchObject command configures the document to watch a specified data store object for modification. When the object changes, the OnObjectChanged event handler runs. Use this command and handler to run other APL commands in response to changes in the data store.

When you run WatchObject, the command invokes the OnObjectChanged handler and sets the document to watch for changes to the data store object. Future changes to the data store object invoke OnObjectChanged.

The following table shows the properties of this command.

Property Type Default Description

namespace

String

Required

Name of namespace within the region for your skill.

key

String

Required

Name of key in the provided namespace.

If the specified object doesn't exist or is deleted, the data property for OnObjectChanged returns null.

The following example shows a WatchObject command that runs when the document displays. The OnObjectChanged handler runs the SetValue command.


Later, if your skill uses the Data Store REST API to update the data store object at the namespace LocationWeather and the key weather, the OnObjectChanged handler runs again. This triggers the SetValue command to update the temperature bind variable.

UnwatchObject

The UnwatchObject configures the document to stop watching a specified data store object that was the target of the WatchObject command. After UnwatchObject runs, the OnObjectChanged handler no longer runs in response to changes to the data store object.

The UnwatchObject command doesn't return a result.

The following table shows the properties of this command.

Property Type Default Description

namespace

String

Required

Name of namespace within the region for your skill.

key

String

Required

Name of key in the provided namespace.

The following example shows a TouchWrapper that runs the UnwatchObject command when the user taps the button.

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "DataStore",
      "uri": "alexaext:datastore:10"
    }
  ],
  "settings": {
    "DataStore": {
      "dataBindings": [
        {
          "namespace": "LocationWeather",
          "key": "weather",
          "dataBindingName": "DS_Weather"
        }
      ]
    }
  },
  "mainTemplate": {
    "item": {
      "type": "TouchWrapper",
      "item": {
        "type": "Text",
        "text": "Stop watching object from DataStore"
      },
      "onPress": {
        "type": "DataStore:UnwatchObject",
        "namespace": "LocationWeather",
        "key": "weather"
      }
    }
  }
}

UpdateArrayBindingRange

The UpdateArrayBindingRange command modifies the range of elements to load into the live data DataBinding array.

The following table shows the properties of this command.

Property Type Default Description

dataBindingName

String

Required

Name of a DataBinding array. Use the extension settings to configure a DataBinding with ARRAY for the dataType.

startIndex

Number

Required

Specifies the starting index for a range of items from the data store array. The live data array identified by dataBindingName is updated with a sub-array of elements from the data store array starting with the specified index.

endIndex

Number

Required

Specifies the ending index for a range of items from the data store array. The live data array identified by dataBindingName is updated with a sub-array of elements from the data store array ending with the specified index.

The UpdateArrayBindingRange applies when the dataBindingName refers to an ARRAY. If the dataBindingName refers to an OBJECT, the command doesn't run.

Event handlers

The data store extension adds new extension event handlers. To respond to events generated by the data store extension, add the handler to the top-level properties in your APL document. For the handler name, use AssignedName:EventHandlerName, where AssignedName is the name you assigned the extension in the extensions property and EventHandlerName is the name of the handler.

For example, assuming you named the extension DataStore, you would use DataStore:OnObjectChanged to respond to events from the OnObjectChanged handler.

OnObjectChanged

Invoked in the following situations:

  • When the WatchObject runs.
  • When the data store object configured with the WatchObject command changes.

The following table shows the properties that the OnObjectChanged handler adds to the event context.

Name Type Default Description

namespace

String

Required

The namespace for the data store object that changed.

key

String

Required

The keyfor the data store object that changed.

data

Object

Required

The updated value of the data store object that changed. Returns null in the following situations:

  • The object specified by the WatchObject command doesn't exist.
  • The object specified by the WatchObject command is deleted from the data store.

The OnObjectChanged handler generates an event with the following form.

{
  "namespace": "LocationWeather",
  "key": "weather",
  "data": {
    "location": "Pune, MH",
    "details": {
      "temperature": "27 °C",
      "precipitation": "7%",
      "humidity": "51%",
      "wind": "5 km/h"
    }
  },
  "event": {
    "source": {
      "type": "Document",
      "handler": "DataStore:OnObjectChanged",
      "id": null,
      "uid": null,
      "value": null
    }
  }
}

The following example shows an APL document that runs the SetValue command when a watched object updates.

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "DataStore",
      "uri": "alexaext:datastore:10"
    }
  ],
  "settings": {
    "DataStore": {
      "dataBindings": [
        {
          "namespace": "LocationWeather",
          "key": "weather",
          "dataBindingName": "DS_Weather"
        }
      ]
    }
  },
  "DataStore:OnObjectChanged": [
    {
      "type": "SetValue",
      "componentId": "txtTemperature",
      "property": "temperature",
      "value": "${event.data.details.temperature}"
    }
  ],
  "mainTemplate": {
    "item": {
      "type": "Text",
      "id": "txtTemperature",
      "bind": [
        {
          "name": "temperature",
          "value": "30 °C"
        }
      ],
      "text": "The temperature at ${DS_Weather.location} is: ${temperature}"
    }
  }
}

OnObjectReceived

Invoked as a response to the GetObject command. The event context provides the requested object.

The following table shows the properties that the OnObjectReceived handler adds to the event context.

Name Type Default Description

namespace

String

Required

The namespace for the requested data store object.

key

String

Required

The keyfor the requested data store object.

data

Object

Required

The value of the requested data store object. Returns null when the requested object doesn't exist.

token

String

""

The optional token provided in the GetObject command.

The OnObjectReceived handler generates an event with the following form.

{
  "namespace": "LocationWeather",
  "key": "weather",
  "data": {
    "location": "Pune, MH",
    "details": {
      "temperature": "27 °C",
      "precipitation": "7%",
      "humidity": "51%",
      "wind": "5 km/h"
    }
  },
  "token": "thisIsADummyToken",
  "event": {
    "source": {
      "type": "Document",
      "handler": "DataStore:OnObjectReceived",
      "id": null,
      "uid": null,
      "value": null
    }
  }
}

The following example shows an APL document that retrieves an object with GetObject, and then runs the SetValue command with data from the retrieved object.

{
  "type": "APL",
  "version": "2024.1",
  "extensions": [
    {
      "name": "DataStore",
      "uri": "alexaext:datastore:10"
    }
  ],
  "settings": {
    "DataStore": {
      "dataBindings": []
    }
  },
  "onMount": {
    "type": "DataStore:GetObject",
    "namespace": "LocationWeather",
    "key": "weather",
    "token": "thisIsADummyToken"
  },
  "DataStore:OnObjectReceived": [
    {
      "type": "SetValue",
      "when": "${event.token == 'thisIsADummyToken'}"
      "componentId": "txtContent",
      "property": "text",
      "value": "The temperature at ${event.data.location} is: ${event.data.details.temperature}"
    }
  ],
  "mainTemplate": {
    "items": [{
      "type": "Text",
      "id": "txtContent",
      "bind": [
        {
          "name": "dsContent",
          "value": "dummyValue"
        }
      ],
      "text": "Waiting for content from DataStore"
    }]
  }
}

Rules for data binding with the data store

When you bind a property in your APL document to an object in the data store, make sure that you adhere to the following rules:

Don't bind non-dynamic properties to the data store

Not all properties on an APL component are dynamic. A dynamic property on an APL component can re-evaluate during the lifetime of the APL document. A non-dynamic property evaluates one time, when the document initially inflates.

If you bind a data store property to a non-dynamic property and then update the content of the data store, the non-dynamic property won't reflect the change.

For details about which base component properties are dynamic, see the table of properties in APL Base Component Properties. The "Dynamic" column indicates whether the property is dynamic. For details about which component-specific properties are dynamic, see the topic for that component. The properties table in each component topic also has a "Dynamic" column.

Don't bind the "when" property to the data store

You use the when property on a component to determine whether to inflate and show the component. However, the when property isn't dynamic. The runtime evaluates when one time, when the document initially inflates. Therefore, the expression in when doesn't update if you later update the data store.

Instead, to display or hide a component based on a property in the data store, use the component display property.

In the following examples, assume that you configured the data store with the dataBindingName set to MyDataStore. The object stored at this location has a property called shouldDisplayText that can be true or false.

The following example shows a Text component that attempts to use when with the shouldDisplayText property in the data store. When the document inflates, ${MyDataStore.shouldDisplayText} evaluates to false so the component doesn't display. Later, you update this object in the data store and change the shouldDisplayText property to true. However, because when isn't dynamic, the component still doesn't display.

Incorrect: Using 'when' to hide or show a component based on a data store property

{
  "when": "${MyDataStore.shouldDisplayText}",
  "type": "Text",
  "text": "This is a sample text."
}

The following example corrects this problem with the display property. When the document initially inflates, ${MyDataStore.shouldDisplayText} is false. The component sets display to none and doesn't show the component. Later, you update the object in the data store and change the shouldDisplayText property to true. Because the display property is dynamic, it re-evaluates and updates to normal. The component becomes visible.

Correct: Using a dynamic property to hide or show a component based on a data store property

{
  "type": "Text",
  "text": "This is a sample text.",
  "display": "${MyDataStore.shouldDisplayText ? 'normal' : 'none'}"
}

Don't use an array nested in an OBJECT for data array inflation

You can assign an array to the data property on a multi-child component, such as a Sequence. The component then uses the data array inflation method. This means that the components in items inflate one time for each value in the array.

When working with the data store, you can't use an array nested within an OBJECT for data array inflation. Instead, you must configure a DataBinding object with the dataType property set to ARRAY, and then bind the component data property to the data binding object.

Incorrect: Binding the 'data' property to a property in an OBJECT

The following example shows an object that contains a text field (headerTitle) and a property containing an array (arrayOfItems).

{
  "headerTitle": "This is the title",
  "arrayOfItems": [
    {
      "displayName": "item 1"
    },
    {
      "displayName": "item 2"
    },
    {
      "displayName": "item 3"
    }
  ]
}

You can configure an OBJECT data binding for this object.

{
  "settings": {
    "DataStore": {
      "dataBindings": [
        {
          "namespace": "ObjectAndArrayExample",
          "key": "mainWidgetData",
          "dataBindingName": "dsWidgetData",
          "dataType": "OBJECT"
        }
      ]
    }
  }
}

In this example, you can bind a component property to the ${dsWidgetData.headerTitle} property of the object. However, binding data to ${dsWidgetData.arrayOfItems} doesn't work.

To correct this problem and use data array inflation with the data store, configure a DataBinding object with the dataType property set to ARRAY, and then bind the component data property to the data binding object. When you update the data store, set the object at the namespace and key to the array of data you want to show.

Correct: Binding the 'data' property to an ARRAY

The following example shows the array arrayOfItems, now stored as an array and not nested within an OBJECT.

[
  {
    "displayName": "item 1"
  },
  {
    "displayName": "item 2"
  },
  {
    "displayName": "item 3"
  }
]

Configure the DataBinding object as an array.

{
  "settings": {
    "DataStore": {
      "dataBindings": [
        {
          "namespace": "ObjectAndArrayExample",
          "key": "arrayOfItems",
          "dataBindingName": "dsArrayOfItems",
          "dataType": "ARRAY"
        }
      ]
    }
  }
}

In the Sequence, bind the data property to dsArrayOfItems, and then use data to access the array in the Sequence.

{
  "type": "Sequence",
  "height": "100%",
  "width": "100%",
  "padding": "@spacingSmall",
  "data": "${dsArrayOfItems}",
  "items": [
    {
      "type": "Text",
      "text": "${data.displayName}"
    }
  ]
}

To bind properties to both arrays and objects, define multiple DataBinding objects. The following example defines two DataBinding objects, one as an OBJECT and one as an ARRAY.

{
  "settings": {
    "DataStore": {
      "dataBindings": [
        {
          "namespace": "ObjectAndArrayExample",
          "key": "mainWidgetData",
          "dataBindingName": "dsWidgetData",
          "dataType": "OBJECT"
        },
        {
          "namespace": "ObjectAndArrayExample",
          "key": "arrayOfItems",
          "dataBindingName": "dsArrayOfItems",
          "dataType": "ARRAY"
        }
      ]
    }
  }
}

The following example shows an APL document that uses both an OBJECT and an ARRAY in the data store.


The following two PUT_OBJECT commands update both the object and the array in the data store.

[
  {
    "type": "PUT_OBJECT",
    "namespace": "ObjectAndArrayExample",
    "key": "mainWidgetData",
    "content": {
      "headerTitle": "This is the header title"
    }
  },
  {
    "type": "PUT_OBJECT",
    "namespace": "ObjectAndArrayExample",
    "key": "arrayOfItems",
    "content": [
      {
        "displayName": "item 1"
      },
      {
        "displayName": "item 2"
      },
      {
        "displayName": "item 3"
      }
    ]
  }
]

Was this page helpful?

Last updated: Dec 06, 2023