Given that Provisions and Virtual Parameters are executed in a sandbox environment, it is not possible to interact with external sources or execute any action that requires OS, file system, or network access. Extensions exist to bridge that gap.

Extensions are fully-privileged Node.js modules and as such have access to standard Node libraries and 3rd party packages. Functions exposed by the extension can be called from Provision scripts using the ext() function. A typical use case for extensions is fetching credentials from a database to have that pushed to the device during provisioning.

By default, the extension JS code must be placed under config/ext directory. You may need to create that directory if it doesn’t already exist.

The example extension below fetches data from an external REST API and returns that to the caller:

// This is an example GenieACS extension to get the current latitude/longitude
// of the International Space Station. Why, you ask? Because why not.
// To install, copy this file to config/ext/iss.js.

"use strict";

const http = require("http");

let cache = null;
let cacheExpire = 0;

function latlong(args, callback) {
  if (Date.now() < cacheExpire) return callback(null, cache);

    .get("http://api.open-notify.org/iss-now.json", (res) => {
      if (res.statusCode !== 200)
        return callback(
          new Error(`Request failed (status code: ${res.statusCode})`)

      let rawData = "";
      res.on("data", (chunk) => (rawData += chunk));

      res.on("end", () => {
        let pos = JSON.parse(rawData)["iss_position"];
        cache = [+pos["latitude"], +pos["longitude"]];
        cacheExpire = Date.now() + 10000;
        callback(null, cache);
    .on("error", (err) => {

exports.latlong = latlong;

To call this extension from a Provision or a Virtual Parameter script:

// The arguments "arg1" and "arg2" are passed to the latlong. Though they are
// unused in this particular example.
const res = ext("ext-sample", "latlong", "arg1", "arg2");