Callytics – open-source self-hosted call center with visual IVR builder, built on Asterisk ARI

Hey everyone,

I’ve been building Callytics — a self-hosted, open-source programmable telephony platform that runs on Asterisk under the hood but hides all the dialplan complexity behind a visual flow builder and a developer-friendly API layer.

The core idea: you get Asterisk’s power without writing a single line of dialplan. Everything is built on ARI + Stasis, so call flows execute as real application logic, not dialplan macros.

What it does right now:

  • Visual drag-and-drop IVR builder (React Flow canvas)

  • Inbound call routing — menus, queues, transfers, hunt groups, voicemail, callbacks, business hours

  • SIP trunk management and extension provisioning

  • Live call dashboard with real-time queue state

  • SIP packet capture with ladder diagrams built in — useful when debugging registrations and audio issues

  • Call recordings, CDR export, diagnostics

  • Webhook nodes — fire structured payloads to any endpoint after any node in the flow

  • WireGuard-based relay for remote phones behind NAT

  • One-command install on Linux via Docker

Stack: Asterisk 20 (built from source), ARI + Stasis (Node.js), NestJS backend, React frontend, PostgreSQL, Redis.

I’ve been running it on real SIP trunks with Linphone and Zoiper as softphones. The relay and audio path are solid.

Would genuinely love feedback from people running Asterisk in production — especially around edge cases, trunk compatibility, and anything the flow builder can’t express that dialplan currently handles for you.

GitHub: https://github.com/rayanweragala/callytics

Asterisk dialplan is a real, albeit specialised, programming language. Also Asterisk dialplan hasn’t had macros since version 21, and the first attempt to deprecate them was about 1.8.

Actually two of them … or is it three now?

Thanks for the correction — you’re right on both counts, I’ll be more precise. Appreciate it!

How do you set the hours in the ‘Business_Hours’ block? It just says ‘Not Configured’ when I try and use it.