Skip to main content

Billing — Telephony

Intro

The Telephony module uses Asterisk AMI to capture events, store them in a database, and provide search, uploads, stats, and operator-load analytics.
image.png

Calls

image.png
Calls page shows a searchable, filterable view of inbound/outbound Asterisk calls with status, operator, duration, ring/hold times, and recording/AI actions.

  • Top filters: caller (“Phone from”), callee (“Phone to”), date, presets (“All calls”), plus toggles to show/hide Ring, Hold, Record/AI, Status. Click Show to apply.

  • Status column: green ANSWERED, yellow NO ANSWER red FAILED.

  • Date: when the call happened.

  • Phone: external number.

  • Subscriber: matched customer (name/ID) if found.

  • Operator: agent/extension (e.g., 201). If extension linked to user - will displayed user data.

  • Duration / Hold / Ring: total talk time, time on hold, and pre-answer ringing.

  • Record/AI column: quick actions—play, download, and AI summary (disabled if no recording/no answer/failed).

Statistics

image.pngCalls → Statistics: pick a period/step, then see donut charts for IN vs OUT, Answered vs No Answer, by Operator, and by Queue/Group.

image.png“Number of calls per hour + SIP” — a stacked bar chart showing hourly call counts, by SIP/extension (legend: e.g., 501, 203, 201), so you can spot peak hours and which SIP/operator handled the load; the Detail toggle reveals the underlying table.

Community modules

There are two community templates (collectors) available in PHP and Python. You can download and configure them yourself or request baseline help from the developers.
Given environment differences (Asterisk versions, dialplan contexts, local conventions), we recommend adapting the module to your future needs.

⚠️ Disclaimer: The modules below are provided as examples. The authors are not responsible for the correctness of writing/displaying data in your system.

  • PHP — sample collector

  • Python — sample collector

Tested on: FreePBX 17.0.21 (Asterisk 20.7)
Recommended setting: asterisk_type: 1

Python collector — installation (example)

Download into your home directory:

curl -H "Authorization: token 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" \
     -L https://api.github.com/repos/Kadadg/ami_listener_grusher/tarball/main \
     -o ami_listener_grusher.tar.gz
     
mkdir -p ~/ami_listener_grusher
tar -xzf ami_listener_grusher.tar.gz --strip-components=1 -C ~/ami_listener_grusher

Enter the directory and run installer:

cd ~/ami_listener_grusher
chmod +x scripts/install.sh
./scripts/install.sh

The installer performs:

  • User-level systemd service creation

  • Logging setup

  • Log rotation

Edit config after install:

sudo nano ami_listener_grusher/config.yaml

Control the service:

service ami-listener stop
service ami-listener start
service ami-listener status

By default, we assume you mount the Asterisk recordings folder into html/records on your web server.

  1. Install sshfs and generate a dedicated SSH key:

    sudo apt update && sudo apt install -y sshfs 
    ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_custom
    ssh-copy-id -i ~/.ssh/id_rsa_custom.pub root@asterisk
  2. Verify key-based SSH works:

    ssh -i ~/.ssh/id_rsa_custom root@asterisk -v

Alternative (no mount):

  • Set record_type: none

  • Provide your external recordings URL:


    record_url: https://asterisk.example.ua/records

 

PHP collector

Building your own module

You may base your solution on the provided code, or write your own AMI event handler tailored to your needs.

To send an AMI event to the app (connector with JSON parameters), for example from your AMI listener:

sudo -u www-data /usr/bin/php /var/www/html/artisan grusher:asterisk_get \
'{"type":"call_new","uniq_id":"1750777894.14312"}'

Main integration file (contains the list of accepted parameters per type):
html/plugins/gviabcua/asterisk/console/Asterisk.php

The flow is essentially:

Receive AMI event → Send event to DB by "uniq_id"

Minimum required types for a correct lifecycle:

call_new → call_end_permanent

Available types (methods):

  • call_new

  • call_to_operator

  • call_to_operator_custom

  • call_answer

  • call_end

  • call_end_permanent

  • send_file_rec_url

  • del_invalid_call