Outgoing call from pjsip endpoint loses/missing callerid in iax2 channel AMI messages

Initial NewChannel AMI message:

Asterisk: Newchannel Callback: <AMIMessage AccountCode=‘’ CallerIDName=‘10’ CallerIDNum=‘10’ Channel=‘PJSIP/10-00000003’ ChannelState=‘4’ ChannelStateDesc=‘Ring’ ConnectedLineName=‘’ ConnectedLineNum=‘’ Context=‘handset_sip_i004’ Event=‘Newchannel’ Exten=‘86132569658’ Language=‘en’ Linkedid='id-8U39MCIX-1772570017.3’ Priority=‘1’ Privilege=‘call,all’ SystemName=‘id-8U39MCIX’ Uniqueid='id-8U39MCIX-1772570017.3’, body=0>

At the end the hangup callback:

Hangup Callback: <AMIMessage AccountCode=‘’ CallerIDName=‘’ CallerIDNum=‘’ Cause=‘16’ Cause-txt='Normal Clearing’ Channel=‘PJSIP/10-00000003’ ChannelState=‘6’ ChannelStateDesc=‘Up’ ConnectedLineName='<unknown>’ ConnectedLineNum=‘’ Context=‘handset_sip_i004’ Event=‘Hangup’ Exten='86132569658’ Language=‘en’ Linkedid=‘id-8U39MCIX-1772570017.3’ Priority=‘2’ Privilege=‘call,all’ SystemName=‘id-8U39MCIX’ Uniqueid=‘id-8U39MCIX-1772570017.3’, body=0>

On Asterisk version 18.26.4.

my extensions.conf:

[globals]                                                                                                                                                                             
                                                                                                                                                                                      
[incoming]                                                                                                                                                                            
exten => _XX,1,Goto(extensions,${EXTEN},1)                                                                                                                                            
exten => _XXX,1,Goto(extensions,${EXTEN},1)                                                                                                                                           
exten => _XXXX,1,Goto(extensions,${EXTEN},1)                                                                                                                                          
                                                                                                                                                                                      
[outgoing]                                                                                                                                                                            
                                                                                                                                                                                      
[extensions]                                                                                                                                                                          
include => outgoing                                                                                                                                                                   
                                                                                                                                                                                      
exten => *00,1,Answer()                                                                                                                                                               
same => n,Echo()                                                                                                                                                                      
same => n,Hangup()                                                                                                                                                                    
                                                                                                                                                                                      
exten => *10,1,Answer()                                                                                                                                                               
same => n,Playback(local/ext-${MY_EXTENSION})                                                                                                                                         
                                                                                                                                                                                      
exten => *11,1,Answer()                                                                                                                                                               
same => n,Record(local/ext-${MY_EXTENSION}.wav,4,30,k)                                                                                                                                
                                                                                                                                                                                      
[messages]                                                                                                                                                                            
exten => s,1,NoOp({Message ==> To: ${MESSAGE(to)} , From: ${MESSAGE(from)} , Body: ${MESSAGE(body)})                                                                                  
same => n,Hangup()

[hangup]
exten => s,1,NoOp()
same => n,Set(HANGUPCAUSE_STRING=${HANGUPCAUSE_KEYS()})
same => n(hu_begin),NoOp()
same => n,GotoIf($[${LEN(${HANGUPCAUSE_STRING})}=0]?hu_exit)
same => n,Set(ARRAY(item)=${HANGUPCAUSE_STRING})
same => n,Set(HANGUPCAUSE_STRING=${HANGUPCAUSE_STRING:${LEN(${item})}})
same => n,Verbose(0, Got Channel ID ${item} with Technology Cause Code ${HANGUPCAUSE(${item},tech)}, Asterisk Cause Code ${HANGUPCAUSE(${item},ast)})
same => n,GotoIf($[${LEN(${HANGUPCAUSE_STRING})}=0]?hu_exit)

I’m want the callerid from the incoming call to be either in the callerid or connectedline field of the iax2 channel messages, but it’s not

The CallerID disappearing between the initial NewChannel and the Hangup event is a known behavior when crossing protocol boundaries (PJSIP to IAX2). The issue is that Dial() creates a new channel for the outbound IAX2 leg, and the caller ID on *that* channel depends on how you set it in your dialplan before dialing.

The fix depends on where you want the CallerID to show up.

**If you want the PJSIP caller’s ID on the outbound IAX2 channel:**

Set it explicitly before the Dial in your outgoing context:

```

[outgoing]

exten => _X.,1,NoOp(Outbound call from ${CALLERID(all)})

same => n,Set(CALLERID(num)=${CALLERID(num)})

same => n,Set(CALLERID(name)=${CALLERID(name)})

same => n,Dial(IAX2/trunk/${EXTEN})

same => n,Hangup()

```

This looks redundant but it forces the caller ID values onto the channel before Dial() creates the outbound leg. Without it, the IAX2 channel inherits whatever the IAX2 trunk config specifies (which might be nothing).

**If you want it in ConnectedLine instead:**

ConnectedLine is the “other end” identity. For the IAX2 channel’s AMI events to show the connected party, you need to set it after the call connects:

```

[outgoing]

exten => _X.,1,NoOp(Outbound via IAX2)

same => n,Set(CONNECTEDLINE(num,i)=${CALLERID(num)})

same => n,Set(CONNECTEDLINE(name,i)=${CALLERID(name)})

same => n,Dial(IAX2/trunk/${EXTEN})

same => n,Hangup()

```

The `,i` inhibits the connected line update from propagating back to the calling channel, which prevents a loop.

**Why it’s blank at Hangup specifically:**

AMI Hangup events report the channel state at teardown time. By that point, the protocol bridge between PJSIP and IAX2 has been torn down and the channel variables get cleared. This is normal — you can’t rely on Hangup events for caller ID. Instead, subscribe to the `Newchannel` and `DialBegin`/`DialEnd` events to capture the CallerID while the channel is still live.

For reliable post-call data, use CEL (Channel Event Logging) or CDR records:

```

[general]

enable=yes

unanswered=yes

congestion=yes

[csv]

usegmtime=yes

loguniqueid=yes

loguserfield=yes

```

CDR will have the correct CallerID in the `src` field regardless of what AMI shows at hangup time.

**IAX2 trunk config check:**

Also verify your `iax.conf` trunk definition isn’t overriding the caller ID:

```

[trunk]

type=friend

host=remote.host

callerid= ; leave blank to inherit from channel

```

If `callerid=` is set to something in your IAX2 peer config, it will override whatever the dialplan sets.

1 Like

Thank you for the response!

I was able to find a workaround of using other values from other messages, but this is very useful to know.