Setup WebRTC Phone in Asterisk / FreePBX and Resolve Call Not Coming
Complete practical guide to set up a WebRTC browser phone on Asterisk and FreePBX, fix the case where presence NOTIFY arrives but the call does not ring, and correctly configure Max Contacts, Remove Existing, DTLS-SRTP, ICE, NAT, and multi-browser ringing.
Setup WebRTC Phone in Asterisk / FreePBX and Fix “Call Not Coming” 🚀
This guide walks through the real production setup and debugging path for a browser-based WebRTC phone using Asterisk and FreePBX. It is written around a very specific issue that confuses many teams: the extension looks registered, presence updates arrive, but the browser phone does not ring on an incoming call.
The most important clue in this case was: NOTIFY was coming, but INVITE was not. That means Asterisk knew the extension state, but it was not actually choosing the browser contact as a real incoming call destination.
🔍 Core diagnosis in one line:
if your browser receives NOTIFY but does not receive INVITE,
the PBX knows the extension exists — but it is not truly delivering the call to that browser contact.
Presence says “Ringing” or “On the phone”, but the browser never receives a true incoming call.
NOTIFY means state update. INVITE means actual ringing. Only INVITE proves call delivery.
The extension may look registered, but Asterisk is not retaining or selecting the browser contacts correctly.
Use Max Contacts > 1, set Remove Existing = No, re-register all browsers, then verify live INVITEs.
📅 Date context: This article is based on the exact troubleshooting path reviewed on 2026-03-14, using extension 10000001, PJSIP, browser WebRTC registration, FreePBX extension screens, and Asterisk contact-selection analysis.
📚 What this guide covers
The article below is intentionally split into collapsible sections so it stays easy to read on both desktop and mobile. Tap the section header or the triangle arrow to expand each part.
Section 1
The real meaning of “NOTIFY comes but call does not come”
This is the core concept behind the whole problem.
▶
The real meaning of “NOTIFY comes but call does not come”
This is the single most important concept in the entire issue.
A browser can receive SIP traffic and still not receive the actual call.
In this case, the system was sending presence updates such as Event: presence with values like
Ringing or on-the-phone.
❌ Presence NOTIFY is not the call.
It only tells subscribers that the extension state changed.
It does not prove that Asterisk sent a real incoming INVITE to the browser contact.
NOTIFY sip:browser-contact@... SIP/2.0
Event: presence
...
<note>Ringing</note>
<rpid:on-the-phone />
A real browser ring only happens when Asterisk sends an actual SIP invite to the registered contact:
INVITE sip:random-contact-id@client-ip:port;transport=ws SIP/2.0
NOTIFY means the PBX is broadcasting extension state or presence information.
INVITE means the PBX is actually trying to deliver the incoming call to a real contact.
200 OK means the endpoint accepted or answered, but it still does not guarantee every media scenario is correct.
NOTIFY, the PBX knows the extension state.
If you do not see INVITE going to the browser contact,
then the PBX is not actually delivering the incoming call there.
Section 2
What we confirmed in this exact debugging case
The setup was mostly right — but one contact-handling detail was critical.
▶
What we confirmed in this exact debugging case
Dial target is correct
The extension was configured with Dial = PJSIP/10000001, which is the correct target
for ringing contacts attached to the extension endpoint/AOR.
Most WebRTC options were already enabled
ICE, AVPF, RTCP mux, DTLS-SRTP, Rewrite Contact, Force rport, RTP Symmetric, and WebRTC defaults were already present.
Contact retention was the real issue
For multiple browsers to ring, Asterisk must keep multiple valid contacts under the same AOR. If contacts are replaced or dropped, only one browser rings — or none.
🧭 Main conclusion:
Find Me / Follow Me is not what makes multiple browser phones ring on one PJSIP extension.
If extension 10000001 has several valid contacts under its AOR, then
PJSIP/10000001 can already fork the call to those contacts.
Follow Me is separate routing logic. It is not the main mechanism for multiple browser registrations.
So the problem was not “extension missing” or “WebRTC completely broken.”
That created a false sense of success, even though Asterisk was not truly delivering the call there.
“When the incoming call arrives, which contacts does Asterisk actually invite?”
Section 3
Asterisk first: what to check before changing more FreePBX settings
Always prove the backend truth before guessing from the GUI.
▶
Asterisk first: what to check before changing more FreePBX settings
Always debug this from the Asterisk side first. FreePBX generates configuration, but Asterisk decides: which contacts exist, which are valid, and who receives the INVITE.
INVITE to those contacts at call time🖥️ Run these commands first
asterisk -rx "pjsip show endpoint 10000001"
asterisk -rx "pjsip show aor 10000001"
asterisk -rx "pjsip show contacts"
asterisk -rx "pjsip show auth 10000001"
asterisk -rx "pjsip show registrations"
You should also inspect the generated config on disk:
grep -Rin "10000001" /etc/asterisk/pjsip*.conf
⚠️ Do not keep guessing in the GUI first.
If pjsip show aor 10000001 does not show multiple contacts,
no wording in FreePBX will change that backend reality.
Section 4
How multi-browser ringing actually works
This is where many teams mix up registration, presence, and real call forking.
▶
How multi-browser ringing actually works
When several browser phones register using the same extension credentials, Asterisk can store them as multiple contacts under the extension’s AOR. If the AOR allows enough contacts and does not replace older ones, dialing the endpoint can fork the call to those registered browsers.
; Conceptual behavior
endpoint 10000001 -> linked to AOR 10000001
AOR 10000001 -> stores multiple dynamic contacts
Dial(PJSIP/10000001)
1️⃣ max_contacts
Must be greater than 1 if more than one browser should remain active.
2️⃣ remove_existing
Must not keep evicting older contacts when new registrations appear.
3️⃣ Stable registration
Contacts must remain reachable and valid when the incoming call arrives.
4️⃣ Real delivery
Asterisk must actually send INVITE to each contact.
🚨 Key trap in this case:
the browser may still show registered,
presence NOTIFY may still arrive,
and the extension may look alive —
but Asterisk may have only one surviving call-eligible contact,
or may not be selecting the browser contact for the call at all.
Section 5
The exact failure case: Max Contacts and Remove Existing behavior
One of the most common reasons browser phones stop ringing correctly.
▶
The exact failure case: Max Contacts and Remove Existing behavior
This is one of the most common reasons WebRTC browser calls do not reach all open browser phones — and it matches the issue pattern discussed here exactly.
max_contacts = 1Only one active contact is allowed, so only one browser can remain as a valid incoming-call target. If you expect several tabs, browsers, or devices to ring together, this is too restrictive.
remove_existing = yesNew registrations can replace older contacts. That means users may think older browsers are still “connected,” while Asterisk has already pushed them out of call eligibility.
If browser sessions reconnect often, contacts can keep changing, expiring, or reordering. When the call actually arrives, the contact you expect may no longer be active.
✅ Operational rule:
if you want all browser phones on the same extension to ring,
the PBX must keep multiple valid contacts alive at the same time.
A strong baseline is:
Max Contacts = 10 and Remove Existing = No.
Section 6
Raw Asterisk WebRTC baseline
Even if FreePBX generates the config, it helps to understand the Asterisk-side logic.
▶
Raw Asterisk WebRTC baseline
A browser SIP client is not the same as a normal UDP SIP phone. It needs WSS signaling, DTLS-SRTP media, and endpoint behavior that is friendly to WebRTC.
📡 Required signaling / transport
- WSS transport for browser signaling
- Working TLS certificate
- WebSocket connectivity without browser certificate errors
🎙️ Required media / NAT behavior
media_encryption=dtlsice_support=yesuse_avpf=yesrtcp_mux=yesrewrite_contact=yesrtp_symmetric=yesforce_rport=yesdirect_media=no
🧱 Conceptual Asterisk PJSIP example
; Example structure only.
; FreePBX will normally generate these values for you.
[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0
allow_reload=yes
[10000001]
type=endpoint
aors=10000001
auth=10000001
transport=transport-wss
webrtc=yes
use_avpf=yes
media_encryption=dtls
dtls_verify=fingerprint
dtls_setup=actpass
ice_support=yes
rtcp_mux=yes
rewrite_contact=yes
rtp_symmetric=yes
force_rport=yes
direct_media=no
context=from-internal
disallow=all
allow=opus,ulaw,alaw
[10000001]
type=auth
auth_type=userpass
username=10000001
password=super-secret
[10000001]
type=aor
max_contacts=10
remove_existing=no
ℹ️ Important: the exact generated FreePBX files may differ, but the underlying logic stays the same: one endpoint, one AOR, multiple contacts, one dial target.
Section 7
Live debugging: the fastest way to prove the problem
Do not stop at “registered.” Prove real call delivery.
▶
Live debugging: the fastest way to prove the problem
Once multiple browsers are registered, do not stop at “it says connected.” Run a live PJSIP trace while placing a real call to the extension.
asterisk -rvvvvv
pjsip set logger on
core set verbose 5
core set debug 5
Now place a test call to extension 10000001.
✅ What you want to see
INVITE sip:contact-a@client1;transport=ws SIP/2.0
INVITE sip:contact-b@client2;transport=ws SIP/2.0
INVITE sip:contact-c@client3;transport=ws SIP/2.0
🚨 If you see NOTIFY but no INVITE to the browser contact, that is the real failure. At that point, the issue is no longer “browser UI.” It is: Asterisk did not choose that contact as a destination for the call.
All browsers are freshly registered, the AOR shows multiple active contacts, and no reconnect churn is happening during the test.
The browser UI says connected, but the AOR shows only one contact or a different contact than the one you expect.
Section 8
FreePBX screen walkthrough for this exact case
Image-first explanation of the real UI path, without repeating the same details in tables again.
▶
FreePBX screen walkthrough for this exact case
The screenshots below are the best way to understand this case visually. Instead of duplicating the same fields in tables and captions, each image here is explained only for what it adds to the diagnosis.
🧠 Reading tip: treat this as a guided UI walkthrough. The screenshots show where the settings live, while the surrounding text explains why they mattered in this failure pattern.
This screen confirms the extension exists as a real PJSIP extension with the expected identity. In this case, that matters because the issue was not “extension missing” or “wrong extension object.”
This shows Follow Me was enabled. That is useful context, but it is also why base endpoint testing needed to be simplified later.
This reinforces that extra routing logic was present. It does not explain the root cause by itself, but it can make troubleshooting noisier if left enabled during testing.
This screen shows that the extension was already largely WebRTC-ready at the media and browser-compatibility level. That is an important clue because it shifts attention away from “basic WebRTC support missing” and toward contact selection and retention.
This is the key image in the entire case.
It shows the extension was dialing through PJSIP/10000001,
had room for multiple contacts,
but also had Remove Existing = Yes.
That combination can still break multi-browser ringing because Asterisk may keep replacing older browser contacts with newer registrations.
This part is not the main cause here, but it helps confirm the extension had broader options configured and was not just a bare-minimum object.
This screen continues the picture that browser-related media security was present. Again, the case was not blocked at the “WebRTC encryption missing” level.
This completes the visual review of the extension.
By this point, the larger pattern is clear:
the extension was already substantially configured for browser WebRTC,
but the incoming-call problem still depended on whether Asterisk retained the right contacts and sent actual INVITEs.
⚠️ Key lesson from the screenshots: a FreePBX extension can look highly WebRTC-ready in the GUI, while the real failure still happens at the Asterisk decision layer: which contacts survive, and which contacts receive the INVITE.
Section 9
The FreePBX settings that matter most in this case
Not a repeated field dump — just the settings that actually changed the outcome.
▶
The FreePBX settings that matter most in this case
Since the screenshots already show the interface, this section focuses only on the settings that really mattered to the diagnosis. The goal here is not to repeat every visible field again, but to isolate the few settings that changed the call outcome.
PJSIP/10000001This was correct and important because it means Asterisk should ring all valid contacts under the endpoint/AOR if they are actually retained.
10This allows multiple browser sessions to exist under the same extension instead of forcing a single surviving contact.
NoThis was the most important functional correction in the case because older browser contacts should not be evicted by newer registrations.
Rewrite Contact, RTP Symmetric, and Force rport enabledThese help Asterisk keep usable signaling and RTP behavior for remote browser endpoints.
These were already aligned with browser expectations and should remain part of the baseline.
Auto may still work, but a browser-only extension often becomes easier to reason about when the transport path is explicit.
✅ Clean baseline:
keep the good WebRTC media settings,
change Remove Existing to No,
keep Max Contacts high enough,
and then verify with Asterisk CLI that multiple contacts truly exist and are actually invited.
Section 10
FreePBX global settings you should also verify
Extension settings alone are not enough for browser WebRTC.
▶
FreePBX global settings you should also verify
Browser WebRTC depends not only on extension settings, but also on PBX-wide transport, TLS, NAT, certificate, and network behavior.
🧰 FreePBX → Asterisk SIP Settings → PJSIP
- WSS transport is enabled and reachable
- TLS certificate is valid for the exact browser domain
- External Address is correct
- Local Networks are correct
- RTP port range is open and routed correctly
🖥️ Browser/WebRTC operational checks
- No browser TLS warning or certificate mismatch
- WebSocket connects successfully over WSS
- Microphone permission is granted
- ICE candidates are being generated correctly
- TURN can be added if direct ICE paths are weak in production networks
📌 Very important: an extension can look perfectly configured while the PBX still advertises the wrong public address or exposes the wrong certificate path. In that case the browser may register, but call delivery, media, or contact usability can still break.
Section 11
About Find Me / Follow Me: useful for routing, not the core fix here
Helpful in some call flows, but not the main solution for this problem.
▶
About Find Me / Follow Me: useful for routing, not the core fix here
In this case, Find Me / Follow Me was enabled and the extension itself was placed in its own follow-me list. That is not the cleanest way to solve multi-browser ringing.
🧪 Recommended testing approach:
disable Find Me / Follow Me while debugging the base endpoint,
or at minimum remove the self-reference from the Follow-Me list.
First prove that PJSIP/10000001 can ring all retained contacts directly.
🎯 Why disable it during testing?
It removes extra dialplan complexity and lets you focus on the real contact-selection issue.
🧩 What confusion does it cause?
Teams may mix up routing logic with contact retention and think Follow Me is the real fix.
✅ What should be proven first?
That the base PJSIP endpoint already forks correctly to multiple active browser contacts.
⚠️ Important:
Follow Me can still be useful in other routing scenarios.
But for this problem —
multiple browser phones on one PJSIP extension should ring —
the first priority is to keep multiple valid contacts under the AOR and verify multiple INVITEs.
Section 12
The fastest fix path for this exact case
A clean action plan from broken state to verified ringing.
▶
The fastest fix path for this exact case
pjsip show aor 10000001 and confirm multiple contacts appear.pjsip set logger on and place a real incoming call.INVITE to each active browser contact.📋 Copy-paste debug commands
# Inspect endpoint and AOR state
asterisk -rx "pjsip show endpoint 10000001"
asterisk -rx "pjsip show aor 10000001"
asterisk -rx "pjsip show contacts"
asterisk -rx "pjsip show auth 10000001"
asterisk -rx "pjsip show registrations"
# Inspect generated PJSIP config
grep -Rin "10000001" /etc/asterisk/pjsip*.conf
# Start live Asterisk logger
asterisk -rvvvvv
pjsip set logger on
core set verbose 5
core set debug 5
🎉 Expected fixed state:
the AOR shows multiple active contacts,
and the incoming call produces multiple INVITEs.
At that point, all open browser phones for extension 10000001 can ring together.
Want to see API-driven CRM + Telecom workflows in action? Try the WhatsApp bot or explore the demos.