Node.js ARI Client -- Channel Events

Integrations Asterisk 18+ -- Last reviewed 2026-03-29 ari nodejs stasis integrations javascript Found this useful? Upvote it. ×

Node.js ARI Client: Channel Events

A minimal Node.js application that connects to the Asterisk REST Interface, listens for channel events, and controls the call lifecycle: ring the channel, answer after 2 seconds, play silence, then hang up after 4 seconds.

Requirements

package.json

}

channel-state.js

'use strict';

var ari = require('ari-client');
var util = require('util');
var timers = {};

ari.connect('http://localhost:8088', 'asterisk', 'asterisk', clientLoaded);

function clientLoaded(err, client) {
    if (err) { throw err; }

    function stasisStart(event, channel) {
        console.log(util.format(
            'Channel %s has entered the application', channel.name));

        // Ring the channel immediately
        channel.ring(function(err) { if (err) throw err; });

        // Answer after 2 seconds
        var timer = setTimeout(function() {
            console.log(util.format('Answering channel %s', channel.name));
            channel.answer(function(err) { if (err) throw err; });
            channel.startSilence(function(err) { if (err) throw err; });

            // Hang up after 4 more seconds
            timers[channel.id] = setTimeout(function() {
                console.log(util.format('Hanging up channel %s', channel.name));
                channel.hangup(function(err) { if (err) throw err; });
            }, 4000);
        }, 2000);
        timers[channel.id] = timer;
    }

    function stasisEnd(event, channel) {
        console.log(util.format(
            'Channel %s just left our application', channel.name));
        var timer = timers[channel.id];
        if (timer) {
            clearTimeout(timer);
            delete timers[channel.id];
        }
    }

    function channelStateChange(event, channel) {
        console.log(util.format(
            'Channel %s is now: %s', channel.name, channel.state));
    }

    client.on('StasisStart', stasisStart);
    client.on('StasisEnd', stasisEnd);
    client.on('ChannelStateChange', channelStateChange);

    client.start('channel-state');
}

Dialplan

[from-trunk]
exten => 1000,1,NoOp(Sending to ARI channel-state app)
 same =>      n,Stasis(channel-state)
 same =>      n,Hangup()

How it works

  1. ari.connect(): Establishes a WebSocket connection to Asterisk's ARI endpoint. The three arguments after the URL are the ARI username and password from ari.conf.
  2. StasisStart: Fires when a channel enters the Stasis() dialplan application. This is the entry point for your application logic. The channel object provides methods like ring(), answer(), hangup(), play(), and startSilence().
  3. StasisEnd: Fires when the channel leaves Stasis (hung up, or Stasis() exits). Clean up timers and resources here to avoid memory leaks.
  4. ChannelStateChange: Fires on state transitions (Ring, Up, Down, etc.). Useful for logging and for driving UI updates in real-time applications.
  5. client.start('channel-state'): Subscribes to events for the named Stasis application. The name must match the argument passed to Stasis() in the dialplan.
  6. Timer cleanup: The timers map tracks pending setTimeout handles per channel ID. On StasisEnd, any pending timer is cleared so the app doesn't attempt to operate on a channel that no longer exists.

Tips

User Notes

No notes yet. Be the first to contribute a tip or example.

Contribute a note

Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.

Moderated before publishing. Email never shown.

Related Snippets