What AMI is for
The Asterisk Manager Interface is a TCP socket that lets external software control Asterisk and watch what it is doing. It is the mechanism behind click-to-call buttons, wallboards, CRM screen pops and most third-party integrations.
It works in two directions at once, and that duality is the core of the design:
- Actions are commands you send in — originate a call, hang one up, add a queue member.
- Events are notifications Asterisk pushes out — a channel started ringing, a call was answered, an agent logged in.
Understanding that split makes the permission model obvious, because it maps directly onto it.
Permissions: read is events, write is actions
Manager users are configured in manager.conf, and each is granted permissions from a finite set of classes. The critical thing to internalise:
- read controls which classes of event a client receives.
- write controls which classes of action a client may send.
Each class may be granted read, write, or both. The available classes include system, call, agent, command, originate, reporting, log, verbose, config, cdr, dialplan, dtmf, message and user.
Two deserve particular caution:
- system — general system information plus the ability to run management commands such as Shutdown, Restart and Reload.
- command — the ability to execute CLI commands. Granting this is effectively granting the Asterisk console.
A user account consists of permitted hosts, a secret, and its granted permissions.
A least-privilege account
Most integrations need far less than the examples floating around the internet suggest. A click-to-call service needs to originate calls and see call events — nothing more:
[clicktocall]
secret = a-long-random-secret
deny = 0.0.0.0/0.0.0.0
permit = 10.0.5.20/255.255.255.255
read = call
write = originateNote the deny/permit pattern: deny everything, then permit the single host that needs access. This is the right default, and CIDR notation makes it precise.
Compare that with the configuration people commonly copy:
read = system,call,log,verbose,command,agent,user,originate
write = system,call,log,verbose,command,agent,user,originateThat grants command and system — CLI execution and the ability to restart the PBX — to whatever application happens to be connecting. If that application is compromised, so is the phone system. Grant what the integration needs and nothing else.
Enabling it
[general]
enabled = yes
port = 5038
bindaddr = 127.0.0.1Bind to localhost wherever you can. If the consuming application runs on the same server, there is no reason for the AMI port to be reachable from anywhere else. Where it must be remote, restrict by IP and consider tunnelling over SSH or a VPN rather than exposing 5038.
Reload and confirm:
asterisk -rx "manager reload"
asterisk -rx "manager show users"A worked session
AMI is a plain-text line protocol: key-value pairs, one per line, with a blank line terminating each message. You can drive it by hand, which makes testing easy:
telnet localhost 5038Log in:
Action: Login
Username: clicktocall
Secret: a-long-random-secret
Place a call — the agent's phone rings first, then connects to the customer:
Action: Originate
Channel: PJSIP/1001
Context: from-internal
Exten: 5551234
Priority: 1
CallerID: Sales <5550100>
Timeout: 30000
Async: true
Variable: CRM_TICKET=48210
Two details that matter in production. Timeout is in milliseconds — passing 30 gives you thirty milliseconds and instant failure. And Async: true makes the origination return immediately rather than blocking the connection for the whole ring duration, with the outcome delivered later as an OriginateResponse event. Any user-facing integration needs this; without it a web request hangs until the call is answered or times out.
Close cleanly:
Action: Logoff
Consuming events
Once logged in with read permissions, Asterisk streams events for the classes you are granted. A wallboard or CRM listens for Newchannel, Dial, Bridge, Hangup and queue events, correlating them by Uniqueid — the same identifier that appears in your CDRs, which is what lets you tie a live event to a stored record.
Two practical warnings. AMI is chatty: a busy system emits a great many events, and a client that parses everything will waste significant CPU. Filter to the classes you actually need. And events are not a reliable delivery channel — if your client disconnects, events emitted during the gap are gone. Do not build billing or anything requiring completeness on AMI events; use CDR or CEL for that and treat AMI as the real-time view.
When to use ARI instead
AMI is well suited to observing calls and issuing coarse commands. It is a poor fit for building a call flow, because it was never designed to hold a call and make decisions about it.
ARI (the Asterisk REST Interface) is the modern answer for that: a REST API plus a WebSocket event stream, where your application takes control of a channel and drives it directly. If you are writing an IVR, a voicebot, or anything that needs to manipulate a call in progress, start with ARI. Use AMI for monitoring, click-to-call and simple automation.
Frequently asked questions
What is the difference between read and write permissions?
Read controls which classes of event you receive; write controls which classes of action you may send. They are granted per class and independently.
Which permissions are dangerous?
command allows CLI execution and system allows shutdown, restart and reload. Between them they amount to full control of the PBX — grant neither unless the integration genuinely requires it.
Why does my application hang when originating a call?
You are originating synchronously. Set Async: true so the action returns immediately and the result arrives later via OriginateResponse.
Should I use AMI or ARI?
AMI for monitoring, click-to-call and simple automation. ARI for building call flows, IVRs and anything that manipulates a call while it is in progress.