johnrivera7/filament-issabel-click-to-call

Filament plugin for Issabel PBX click-to-call via Asterisk AMI — originate from tables, forms, and a credentials UI.

Maintainers

Package info

github.com/Johnrivera7/filament-issabel-click-to-call

pkg:composer/johnrivera7/filament-issabel-click-to-call

Transparency log

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-08-24 18:25 UTC

This package is auto-updated.

Last update: 2026-08-24 23:40:32 UTC


README

Issabel Click-to-Call Filament plugin

FILAMENT 4.x FILAMENT 5.x

Latest Version on Packagist License

Filament plugin for Issabel PBX click-to-call via Asterisk AMI: ring the agent extension first, then dial the customer number from tables or forms.

Open source (MIT). Works with Issabel and other Asterisk/FreePBX deployments that expose AMI on port 5038.

Requirements

Stack Versions
PHP 8.2+
Laravel 11.28+ / 12+ / 13+
Filament 4.x or 5.x
Issabel AMI enabled; agent softphone registered on extension

How click-to-call works

  1. User clicks Llamar / Call in Filament.
  2. Laravel connects to Issabel AMI (TCP 5038).
  3. Sends Originate: channel PJSIP/{anexo} → when answered, dials destination in from-internal.
  4. Agent answers on their softphone/IP phone; Issabel connects the customer.

Filament does not carry audio — the PBX does.

Agent phone display (required Issabel dialplan)

Issabel/FreePBX stores a CNAM per extension (e.g. Mariela Lopez on 2150). If you originate directly to SIP/2150, the agent phone shows the extension identity, not the customer number — AMI CallerID variables alone cannot override this on stock Issabel.

We added strategy custom_agent: originate to Local/{anexo}@filament-click-to-call, set display from CTC_DEST in dialplan, then dial outbound via from-internal/{destino}.

Why we need [filament-click-to-call] on the PBX

Approach Agent display Outbound dial
Direct SIP/anexo + AMI CallerID Extension CNAM (wrong) May work
Force CALLERID(num) = cell in AMI Cell on display Often bad-number / wrong route
custom_agent + custom context Cell on display Normal outbound route

One-time setup on Issabel

Add to /etc/asterisk/extensions_custom.conf:

[filament-click-to-call]
exten => _X.,1,NoOp(Filament click-to-call anexo ${EXTEN} destino ${CTC_DEST})
 same => n,Set(CALLERID(name)=${IF($["${CTC_NAME}"=""]?${CTC_DEST}:${CTC_NAME})})
 same => n,Set(CALLERID(num)=${IF($["${CTC_NUM}"=""]?${CTC_DEST}:${CTC_NUM})})
 same => n,Set(CALLERID(name-pres)=allowed_not_screened)
 same => n,Set(CALLERID(num-pres)=allowed_not_screened)
 same => n,Dial(SIP/${EXTEN},30,m)
 same => n,Hangup()

Use PJSIP instead of SIP in Dial() if your extensions are PJSIP. Then:

asterisk -rx "dialplan reload"

Publish the snippet from Laravel:

php artisan vendor:publish --tag=filament-issabel-click-to-call-dialplan

Full Spanish guide: docs/ISSABEL_VISOR_DESTINO.md

.env for correct display

ISSABEL_PBX_ORIGINATE_STRATEGY=custom_agent
ISSABEL_PBX_AGENT_DIAL_CONTEXT=filament-click-to-call
ISSABEL_PBX_CALLER_ID_DISPLAY=destination

Fallback without PBX dialplan (display stays extension CNAM):

ISSABEL_PBX_ORIGINATE_STRATEGY=application_dial

Where to create AMI credentials (Issabel)

Option A — Issabel web UI

  1. Log in to Issabel as admin.
  2. Open Settings → Advanced Settings → Asterisk Manager Users (wording may vary by Issabel version).
  3. Add user e.g. kitinicio_originate with a strong secret.
  4. Restrict permit to the private IP of your Laravel server only (not 0.0.0.0/0).
  5. Grant at least write = originate (and minimal read permissions).
  6. Apply config / reload Asterisk.

Option B — /etc/asterisk/manager.conf

[kitinicio_originate]
secret = YOUR_STRONG_SECRET
deny=0.0.0.0/0.0.0.0
permit=172.16.10.20/255.255.255.255
read = system,call,log,verbose,command,agent,user,config,dtmf,reporting,cdr,dialplan
write = originate

Then: asterisk -rx "manager reload" (or restart Asterisk from Issabel).

.env in Laravel

ISSABEL_CLICK_TO_CALL_ENABLED=true
ISSABEL_PBX_HOST=172.16.10.50
ISSABEL_PBX_AMI_PORT=5038
ISSABEL_PBX_AMI_USER=kitinicio_originate
ISSABEL_PBX_AMI_SECRET=YOUR_STRONG_SECRET
ISSABEL_PBX_CHANNEL_DRIVER=PJSIP
ISSABEL_PBX_DIAL_CONTEXT=from-internal
ISSABEL_PBX_ORIGINATE_STRATEGY=custom_agent
ISSABEL_PBX_AGENT_DIAL_CONTEXT=filament-click-to-call
ISSABEL_PBX_CALLER_ID_DISPLAY=destination

Network / Huawei Cloud

You do not need to expose port 5038 to the public internet.

Scenario Recommendation
Laravel + Issabel same VPC / LAN Security group: inbound TCP 5038 only from Laravel VM private IP → Issabel private IP
Laravel outside, Issabel inside VPN or private peering; avoid public AMI
Public AMI Not recommended — AMI has full call control

Issabel AMI listens on 5038/TCP by default. Open it only between app server and PBX.

Does Issabel have an API?

Yes, partially:

API Use for click-to-call?
Issabel REST /pbxapi/ Admin (extensions, ring groups). No CDR/originate in core API.
Community PBXAPI v2 Optional HTTP CDR + originate if installed on Issabel
AMI (this plugin) Recommended for originate — native Asterisk, no extra modules

This plugin uses AMI because it is stable, works on stock Issabel, and matches legacy cobranza integrations.

Installation

composer require johnrivera7/filament-issabel-click-to-call:^1.0
php artisan vendor:publish --tag=filament-issabel-click-to-call-config

Register in your PanelProvider:

use JohnRivera7\FilamentIssabelClickToCall\FilamentIssabelClickToCallPlugin;

->plugin(
    FilamentIssabelClickToCallPlugin::make()
        ->navigationGroup('Telefonía')
)

Filament action (table / form)

use JohnRivera7\FilamentIssabelClickToCall\Actions\ClickToCallAction;

ClickToCallAction::make(
    phoneResolver: fn (array $record) => $record['celular'],
    extensionResolver: fn () => auth()->user()->cobranzaEjecutivo?->anexo_pbx,
)

Wire extension per user from your ejecutivo mantenedor (anexo_pbx column in your app).

Multi-tenant credentials

use JohnRivera7\FilamentIssabelClickToCall\Support\IssabelAmiCredentials;

FilamentIssabelClickToCallPlugin::make()
    ->credentialsUsing(fn (): IssabelAmiCredentials => IssabelAmiCredentials::fromArray(/* DB */))
    ->persistCredentialsUsing(function (IssabelAmiCredentials $c): void {
        /* save to DB */
    })

Programmatic

use JohnRivera7\FilamentIssabelClickToCall\FilamentIssabelClickToCallPlugin;

FilamentIssabelClickToCallPlugin::get()->clickToCall()->call(
    extension: '2151',
    phone: '957592274',
);

Agent requirements

Each cobranza agent needs:

  • Issabel extension (anexo) assigned in your mantenedor
  • Softphone (Zoiper, MicroSIP, etc.) or IP phone registered to Issabel

Without a registered endpoint, Originate will fail or ring nowhere.

License

MIT © John Rivera. Issabel® is a trademark of its respective owners; this plugin is not affiliated with Issabel LLC.

Links