Change caller id based on internal vs. external when forwarding

I am attempting to change the outbound cid for calls that are being forwarded. We have some users who prefer to have their cell phones rang after a predetermined amount of time. In the example below 20 seconds after the call is initiated it forwards to their cell phone. The phone system itself is highly backed up with multiple power and network sources so we want the forwarding to take place on the box and not the endpoints which only have about 30 minutes of backup for their POE switches. This works…

exten => 4912,hint,PJSIP/4912
        same => 1,dial(PJSIP/4912&PJSIP/4923,20,i)
;         same => n,Set(_CUSTOM_CID=${CUSTOM_CID}) ; This was used in conjunction with the next entry.
;        same => n,Dial(Local/12223334444@redacted-voip) ; <-- See sub note 1
       same => n,Dial(SIP/twilio0/12223334444,20,i) ; <-- See sub note 2
        same => n,Hangup

Right now if I dial an outside number directly from my handset I get an appropriate caller id being outpulsed by Asterisk. When calls are transferred to a user that originated from outside the building it is passing the original callers CID value. So that works fantastic.

However when I call the users extension from another extension once the 20 second time has elapsed it begins to dial using the dialplan I have setup for 10 digit dialing. And I need the building’s CID value to be passed as the outbound CID value.

exten => _1NXXXXXXXXX,1,NoOp(Caller ID Number: ${CALLERID(num)})
        same => n,NoOp(Caller ID Name: ${CALLERID(name)})
        same => n,Set(outgoing_ident=${DB(OCID/${CALLERID(num)})})
        same => n,Set(CALLERID(num)=${IF($[${DB_EXISTS(OCID/${CALLERID(num)})} = 1 ]?${outgoing_ident}:${CUSTOM_CID})})
        same => n,NoOp(Reformatted Caller ID Number: ${CALLERID(num)})
        same => n,NoOp(Reformatted Caller ID Name: ${CALLERID(name)})
        same => n,Answer()
        same => n,Dial(SIP/twilio0/+${EXTEN})
        same => n,NoOp(DialStatus returned ${DIALSTATUS} and HangupCause returned ${HANGUPCAUSE})
        same => n,Hangup(${HANGUPCAUSE})

I know there has to be a way to accomplish this. This is a very vanilla server setup. Asterisk 15.6.2 built by root @ spk-asterisk on a x86_64 running on Deb 9

The CUSTOM_CID is coming from the endpoint setup in pjsip.conf if anyone is wondering.

Sub Notes:

  1. This works but expects a variable to be passed and I cannot find a way to pass it from the users context. Or rather I can pass it back out but it destroys the inbound callers CID while preserving the internal users outbound CID
  2. This works only for Outside calls to have their CID passed back out when it finally forwards.

I am sure there will be questions as I know I have likely left more to the wandering mind than I have answered. So please feel free to fire away with more questions. (My carrier supports full CID manipulation! I dont plan to misuse that ability I only use it to pass our phone numbers and those of calls that are forwarded out)


  • When I dial extension to extesion I want cid to be that of the internal extensions
  • When I dial an extension from within the building I want that extension to ring the called extension and then after 20 seconds it will forward to that users cell phone and show the CID for the building.
  • When an ouside caller calls in and is forwarded to an extension it will ring show the outside CID and then when it forwards to the cell phone it will still show the callers CID NOT the building CID.

Most providers will not support this, as you are not a network operator and the feature is very useful for vishing, as it allows you to spoof the caller ID of the legitimate organisation that you are pretending to be.

Those that do allow you to set the caller ID will normally require the caller ID to be in a list of numbers which you have proved you control.

Also, at least for SP native attended transfers (and some phones do blind transfers as automated attended transfers), Asterisk doesn’t know that a transfer is in progress, rather than a second line call, or enquiry, at the time it establishes the new outgoing leg. That also means that it cannot know whether the number that will eventually get transferred is internal or external.

My provider DOES allow ANY out pulsed cid I do it all the time for testing I set the outbound cid to something like 5554441111 it works great. And I dont abuse it to make phishing calls or spam people either. That is not my issue.

I can have it either way but not both in the current config: I can have the callers that call our building cid transfer or I can have the calls that I to other extensions get proper CID when forwarded but not both this far. So there has to be a setting within Asterisk to allow this.

I only wish I had the authority to convert the entire system to a FreePBX I could easily make free PBX to do exactly what I wanted to with 100% accuracy.

Not an advertisement here but those who have a real paid account through Twilio are allowed total freedom to assign outbound CID on the fly without listing numbers. Flowroute also allowed this when I had them.

I am sure that there is a better way to do this however I have a solution that works for me at the moment. This is not say that I am not open to other ideas that are cleaner or easier to accomplish than this one. But I will lay it out so that maybe someone else can benefit from it too. :smiley:

User cell phone number = (222)555-1212
Office Location 1 = (222)555-1111
Office Location 2 = (222)555-2222



exten => 1002,hint,PJSIP/1002
        same => 1,dial(PJSIP/1002,20,i)
        same => n,Set(_CUSTOM_CID=${OFFICE1})
        same => n,Dial(Local/5551212@company)
        same => n,Hangup

exten => _NXXXXXX,1,NoOp(Caller ID Number: ${CALLERID(num)})
        same => n,NoOp(Caller ID Name: ${CALLERID(name)})
        same => n,Set(outgoing_ident=${DB(OCID/${CALLERID(num)})})
        same => n,Set(CALLERID(num)=${IF($[${DB_EXISTS(OCID/${CALLERID(num)})} = 1 ]?${outgoing_ident}:${CUSTOM_CID})})
        same => n,NoOp(Reformatted Caller ID Number: ${CALLERID(num)})
        same => n,NoOp(Reformatted Caller ID Name: ${CALLERID(name)})
        same => n,Answer()
        same => n,Dial(SIP/twilio0/+1555${EXTEN})
        same => n,NoOp(DialStatus returned ${DIALSTATUS} and HangupCause returned ${HANGUPCAUSE})
        same => n,Hangup(${HANGUPCAUSE})



                callerid=SOME USER <1002>



I have completely written my dialplan myself. If there is a transit call from the outside to the cellular phone, the original CPN is preserved. If this call is originated from an internal extension and subsequently redirected, you need to check, if the calling extension number is allowed as a caller id for external number. If it is not allowed (for example, if you use short, not PSTN, internal extensions), you need to set the caller id prior to dialing. You may use either a database or a channel custom variable, set for each extension, as has been shown in the previous answer.

For an external caller id I use channel variables defined in configuration. For example,
[phone_endpoint] (!)

then you define individual phone endpoints:

In your dialplan, before you decide to make a redirection outside, run
same => n,Set(CALLERID(num)={IF([{ISNULL({outbound_callerid})}=0]?{outbound_callerid}:{CALLERID(num)})})
same => n,Set(CALLERID(name)={IF([{ISNULL({outbound_callerid})}=0]?{outbound_callerid}:{CALLERID(num)})})

Also, when redirecting from an internal number, you might also need to substitute it for an appropriate PSTN number.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.