Add custom SIP header to PJSIP trunk

We have provisioned the new FreePBX 13 Server and 40+ extensions. I have two trunks that are pjsip and all extensions are configured in pjsip.

Our provider does not accept the *67 anonymous caller on their trunk due to billing purposes and has suggested I setup a PAI Header to set the flag.

We have two outbound routes - one should be used when a caller prefixes *67 which is set to override the extension CID with hidden. This is not working.

Has anyone been successful in getting this to work and if so how, where would I look? Where would I get started?
There is no clear instructions anywhere that I have looked. I have seen people mentioning to include in the extensions_custom.conf and use [macro-dialout-trunk-predial-hook] but I do not know what to specify here so that it works?

Your help please!

Mod - thread title changed to assist future searchers

This is the type of thing we do in paid support. To get you pointed in the right direction:

  1. you want to enable noop tracing in Advanced Settings. This will populate a channel variable with the outbound route name

  2. you want to add a block of dialplan to extensions_custom.conf with the macro you noted, check the value of ${OUTBOUND_ROUTE_NAME} and if it matches the privacy route you want to run the line:

    exten => s,n,Set(PJSIP_HEADER(add,Privacy=id)

**edit, this will not work. I forgot that adding PJSIP headers is a major PITA.

I have read that PJSIP can be quite annoying!

Would it be worth changing back to CHAN_SIP? considering we have two trunks and 40 + extensions?

OR would you recommend I get some paid support? What costs am I looking at?

Edit: the following no longer works…

Second attempt …

  1. Create a new trunk with the same settings as your existing trunk. Do not populate the registration string. This trunk will be dedicated to private outbound.

  2. Override the trunk dial options and use this instead: Ttb(custom-privacy-header^s^1)

  3. In extensions_custom.conf add lines like this:

    exten => s,1,Set(PJSIP_HEADER(add,Privacy)=id)
    exten => s,n,Return

Use this trunk for your private outbound route then reload the dialplan. Might work, didn’t test

Ok so here’s what I’ve done

Copied one of my existing trunks - the registration setting is set to none
Override the trunk dial options to use what you mention
Added the below to extensions_custom.conf
exten => s,1,Set(PJSIP_HEADER(add,Privacy)=id)
exten => s,n,Return

I then assigned this to my Anonymous Outbound route, with dial pattern *67 and override extension to hidden set?

Tested dialing my mobile from softphone prefixed with *67 and the call failed

The broad strokes look correct, you will have to examine the full log to determine the cause of the failure.

Thanks, that worked!

Now how do I make that work for users when they prefix the dialed numbers with *67?

1 Like

That’s the easy part, add *67 as a prefix to all the dial patterns on the privacy route.

Thanks so much - that’s all working now

1 Like

EDIT: See Maple’s post below for a much better and cleaner way to do this.

I realize this is an old topic, but I found it by searching for something very close to the title of the thread, so I imagine others are finding it too. The reason this isn’t working now is the line I quoted above. It probably worked when this thread was started, but in current releases of FreePBX 14 it doesn’t. That’s because by default, FreePBX sends these options in a trunk Dial string:


If you override the default options to Ttb(custom-privacy-header^s^1) you would think that’s what FreePBX would use, but noooo… what it really sends as part of the Dial options is


Yes, that’s two b options, and it appears that Asterisk will only accept one and that it takes the last one (which you will see if you watch the CLI). The problem is that FreePBX is going to this context:

include => func-apply-sipheaders-custom
exten => s,1,Noop(Applying SIP Headers to channel)
exten => s,n,ExecIf($["${HASH(SIPHEADERS,Alert-Info)}" = "unset"]?Set(Rheader=1))
exten => s,n,While($["${SET(sipkey=${SHIFT(SIPHEADERKEYS)})}" != ""])
exten => s,n,Set(sipheader=${HASH(SIPHEADERS,${sipkey})})
exten => s,n,SIPAddHeader(${sipkey}: ${sipheader})
exten => s,n,Set(PJSIP_HEADER(add,${sipkey})=${sipheader})
exten => s,n,EndWhile
exten => s,n,ExecIf($["${Rheader}" = "1"]?SIPRemoveHeader(Alert-Info:))
exten => s,n,ExecIf($["${Rheader}" = "1"]?Set(PJSIP_HEADER(remove,Alert-Info)=))
exten => s,n,Return()

;–== end of [func-apply-sipheaders] ==–;`

Since it has the include => func-apply-sipheaders-custom I tried adding that context in extensions_custom.conf but for some reason FreePBX cheerfully ignores it (I will never understand why those non-working includes are there). So the only solution I could figure out is to copy that entire context to extensions_override_freepbx.conf and make modifications there. So at the top of that file you might change it to look like this:

include => func-apply-sipheaders-custom
exten => s,1,Noop(Applying SIP Headers to channel)
exten => s,n,Set(PJSIP_HEADER(add,Privacy)=id)

Or if you want to only use it on a specific trunk, this may work (replace trunkname with the real trunk name)…

exten => s,n,ExecIf($["${CUT(DIALEDPEERNUMBER,@,2)}" = "trunkname-PJSIP"]?Set(PJSIP_HEADER(add,Privacy)=id))

I really have no idea what that [func-apply-sipheaders] context is doing, or if there is a better way to do this. I would be very happy if there were a better or easier way, because I really don’t like using extensions_override_freepbx.conf because you have no idea when the the code you have modified might be changed in a new release of FreePBX. But I don’t see any other hooks to insert this into the outgoing channel.

1 Like

Actually, there is a much easier way. I found it here:

How to use a custom SIP header to pass the DID (or other data) between two Asterisk servers that jointly handle extensions

So instead of the original example

exten => s,n,Set(PJSIP_HEADER(add,Privacy=id)


exten => s,n,Set(HASH(__SIPHEADERS,Privacy)=id)

The article sort of explains why this works.


That’s definitely far better than what I’d posted. I see now that if you search extensions_additional.conf for instances of SIPHEADERS or Set(HASH(__SIPHEADERS, you can get a somewhat better idea of how it is used. Seems to primarily be there to set an Alert-Info header. I don’t know why anyone might want to do that, but I’m sure someone did or it wouldn’t be there.