Transferring from Call Flow to Voicemail

mharriskee

Silver Partner
Joined
Sep 19, 2025
Messages
1
Reaction score
0

Transferring a Parked Caller to a Specific Extension's Voicemail from a Call Flow​


Environment: 3CX V20 (Linux), Professional Annual, 8 SC. Roughly 38 extensions need this feature.

What I'm building​


A call-screening / "announce caller" feature for when the receptionist is unavailable. A caller who reaches an attorney is asked to say their name; the attorney's phone then rings and announces "You have a call from [name] — press 1 to accept, or 2 to send to voicemail." Press 1 connects them; press 2 should send the caller to that attorney's voicemail.


I built this with the Call Flow Designer rather than the built-in Announce Caller (Rebound) feature, because Rebound requires a dummy extension per user, and 38 dummies would blow past the fair-use extension cap on 8 SC.


Current architecture (the parts that work)​


Two CFD apps that hand off to each other:


  • Screening app (runs on the inbound caller's leg): greets the caller, captures the spoken name via Google STT, writes the name to a text file keyed by the target attorney's extension, then parks the caller (Transfer to *09). Its Disconnect Handler then issues a Make Call with origin = the attorney's extension and destination = the announce app.
  • Announce app(runs on the attorney's leg): reads the name file, announces it via TTS, and presents an Accept/Decline menu.
    • Press 1 → Transfer to *19 (pulls the caller out of parking) → the two are bridged. This works perfectly.
    • Press 2 → intended to send the caller to the attorney's voicemail.

(Two separate CFD projects can't share variables, so the caller's name is passed via a text file named by the attorney's extension. That part works fine.)


The problem​


Pressing 2 doesn't do what I need. Because the announce app runs on the attorney's call leg, its Transfer (attorneyExt + "Transfer to Extension Voicemail") moves the attorney into the attorney's own mailbox — while the caller stays parked. What I actually need is for the parked caller to be dropped into that attorney's voicemail.


What I've already found​


From older forum threads, it appears an IVR/CFD cannot control a shared parking space, and the only native lever is the parking-orbit timeout destination. I'm not sure that's still true in V20 U9, and a single global timeout destination doesn't give me a per-attorney mailbox anyway. Other threads suggest it "should be possible with the Call Control API." So I'm trying to choose the best path and would appreciate guidance on either.


Path A — Shared Parking / CFD only​


  1. In V20 (U9), is there any CFD-native way to send a specific parked call to a specific extension's voicemail, triggered by the answering party pressing a key? (Older threads say no — is that still the case?)
  2. If the parking-orbit timeout destination is the only native option, can it be made per-extension/per-attorney, or is it a single destination per orbit?
  3. Is there a supported alternative topology that avoids this trap — e.g., keeping call control on the caller's leg (no parking), so one flow can both announce to the attorney and, on decline, transfer the caller to the attorney's mailbox? If so, how do you announce to the called party and capture their DTMF while still retaining control of the caller's leg in CFD?

Path B — Call Control API​


  1. With the V20 Call Control API, what's the correct method/overload to transfer an active call (by call ID) directly to a specific extension's voicemail — i.e., land in the mailbox, not just ring the extension?
  2. Given community reports that parking and retrieving parked calls via the API is unreliable, is the recommended design to have an API app own both legs (answer the attorney, play the prompt, capture the 1/2, then either bridge or send the caller to voicemail) and skip shared parking entirely?
  3. The .NET assembly API needs an on-box agent. Is the REST API (ccapi) mature enough as of U9 to do this end-to-end, and can it run externally (off the PBX)?
  4. Are there OMSamples or community examples close to this "screen → announce → accept / decline-to-voicemail" pattern I could start from?

Bottom line​


For a ~38-user production deployment (reliability matters, no in-house dev team), which approach would you recommend? Is a custom Call Control service overkill for this one feature, or is there a cleaner native pattern I'm missing?


I've attached a couple of screenshots detailing the call flows. Happy to share a sanitized export or screenshots of the flows if that helps. Thanks in advance.
 

Attachments

  • Screenshot 2026-06-02 172327.png
    Screenshot 2026-06-02 172327.png
    23.1 KB · Views: 3
  • Screenshot 2026-06-02 172233.png
    Screenshot 2026-06-02 172233.png
    26.1 KB · Views: 2
You can park a call from a CFD to a parking extension by using a standard Transfer to "*00", for example. To retrieve the parked call through a CFD, use a second Transfer block and transfer the call to "*10". This will connect the two calls.

If you want to route the caller to a mailbox after an audio prompt, you can use a MakeCall element to create a new call from the CFD. This call can then be transferred to another CFD, which transfers the call to the mailbox of the desired extension.

In this scenario, you would typically use two or three CFDs:
  1. First CFD: The customer records an audio message, and the call is transferred to a parking slot.
  2. Second CFD: Triggered via a MakeCall from the extension in the Disconnect Handler of the first CFD. Here, the customer can choose whether to connect to the parked call or leave a voicemail.
  3. Third CFD: Used only for mailbox routing.
If the customer chooses to connect, use a Transfer element to retrieve the parked call.

If the customer chooses voicemail, use the Disconnect Handler to start another MakeCall from the parking slot to a third CFD. This CFD should simply transfer the call to the target mailbox, since MakeCall elements cannot connect directly to mailboxes.
 
  • Like
Reactions: fxbastler
You can park a call from a CFD to a parking extension by using a standard Transfer to "*00", for example. To retrieve the parked call through a CFD, use a second Transfer block and transfer the call to "*10". This will connect the two calls.
This uses parking orbits which can't guarantee which call is retrieved if there are more than 1 parked.

Also, AFAIK, since v20 this doesn't work anymore due to how the calls are routed internally.
 
It works, and it also works in the current U9 build. I use this approach every day in CFD projects.

If multiple calls are parked in the same parking slot, they will be unparked one after another in the order they were parked.

You can transfer calls to different parking slots, and you can also retrieve information about the call from the ActiveConnection property using a C# element.
 

Members Online Now

No members online now.

Forum statistics

Threads
111,831
Messages
589,277
Members
164,660
Latest member
RJenkinsROCK