RustPBX Basics: Call Forwarding — Always, When Busy, When No One Answers
Call forwarding is the most-requested feature after basic calling, and the one with the most edge cases: what counts as “busy”? What if the destination is another extension? What if the carrier rejects the forwarded leg? Here’s how RustPBX handles all of it.
Per-Extension Forwarding
Every extension has three forwarding knobs — mode, destination, and timeout:
| Mode | Fires when |
|---|---|
always | Every incoming call, immediately |
when_busy | The extension rejects with 486 Busy |
when_not_answered | No answer within the timeout (default 30s) |
Set them in the console (Extensions → detail → Forwarding) or via the API:
curl -X PATCH http://<host>:8080/api/extensions/1001 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"call_forwarding_mode": "when_not_answered",
"call_forwarding_destination": "1002",
"call_forwarding_timeout": 25
}'
The destination can be another extension or an external number (routed through your normal outbound rules, so billing and trunk selection apply).
Forwarding to a Busy On-Call Extension: Camp-On
Forwarding to when_busy hands the caller a busy tone — rarely what anyone wanted. For on-call destinations, busy-wait (camp-on) is usually better: the caller waits with hold audio, and the extension is re-dialed until free:
# in the forward route targeting the extension
[busy_wait]
enabled = true
max_wait_secs = 120
retry_interval_secs = 15
hold_audio = "sounds/hold-music.wav"
Non-busy failures and caller hangups exit the wait immediately.
Transfers: Blind, Attended, and Application
Once the call is up, transfers come in three flavors:
- Blind (REFER) — the platform forwards the call; with 0.5’s hardened REFER handling, a B2BUA fallback bridges the legs when plain signaling can’t complete the transfer.
- Attended (consult) — the agent calls the target first, speaks, then completes. Unanswered consults fail cleanly (409) instead of stranding legs.
- Application handoff — if the call is inside an IVR or AI session, an inbound REFER preserves the application state on the new leg instead of dropping the caller back to a menu. An explicit resume event tells the flow where to continue.
Transfer context headers can be forwarded to outbound INVITEs per trunk (header_passthrough) when the far side needs them.
Forwarding to the Outside World
External destinations traverse the normal routing stack: match rules, LCR, trunk selection, billing. That means forwarded legs get recorded, rated, and traced like any other call — with the CDR carrying both the original and forwarded leg in its timeline.
Details: Extension Management and Routing, Trunk & Billing.