Account codes via trunks

Hi guys,

I have a problem and am hoping someone can nudge me in the right direction.

I have a couple of freepbx boxes and I wanted to put an A2 box in front of them to do call rating and LCR. I got everything up and running, and can send calls to the A2 box (wholesale setup) without any problem by assigning an account code at the trunk (one account code for all the calls coming from the box).

However to make this setup really work the way I want it to I need the accountcode assigned at the extension level to be passed over the trunk to the A2 machine.

I have heard a couple people say prefix the dialed number with the account code and then strip it out at the far end, but I have no idea how to do this nicely within the freepbx framework (Its freepbx on both ends).

I’m sure for a dial plan guru it’s pretty easy and therefore I’m posting here.

I would deeply appreciate any suggestions or examples.


I’d like to try and help, and I think I could help with prefixing and stripping out digits if I knew better what you need to attchive

What is an A2 box?


Hi Thanks Dave!

An A2 box is a box with freepbx and A2 billing installed. A2 billing uses account codes to authenticate and help rate traffic, ie you could generate reports via account code.

So here’s the setup:


Asterisk 1.4.42 (old I know)
PIAF 2.8 (old I know)

A2 box
freepbx 2.8
A2 billing 1.9.4

Anyway SIP trunk from PBX to A2. Account code is specified at the extension level on the PBX machine, but does not get passed through the trunk to the A2 box resulting in A2billing not knowing how to authenticate or rate the call.

I can however specify in the peer settings of the trunk an account code, but of course the same account code is then used for every extension calling from the box which impacts the call rating functionality.

So I somehow have to figure out how the account code is set on the PBX side, and somehow pass it to the A2 side and set it again.

OK So if you could make the phone dial its own extension number after the 9 for an outside line (if you use one) followed by the number to dial then you would be on your way?



Every extension has an extension number, and an optional account code field. The account code field populates a channel variable (I think) called ACCOUNTCODE. So if I where to make a regular call the account code would be store din the local CDR. Unfortunately as soon as the call is sent out over the trunk it removes some of the channel variables and sends the call. Therefore the call shows up at the far end with only basic info (CID, calling number, etc).

What I need to do is a) find out how and where the accountcode variable is set, b) somehow transmit the accountcode info with the call to the far end, c) have the far end set that variable with the info it got from PBX.

That is above my pay grade and is my dilemma.

I am sure that someone will be able to answer this long before I find the answer but I’ll go and have a look to see if I can work it out. I have’nt used account codes but I just set on for one of my extensions and made a call but I can’t see it in the CDR. do you know if there is something else that has to be set?

For it to show up in the CDR I think you also have to set AMAFLAGS to yes in one of the conf files. Also you would need to view the native cdr.

Thanks for trying, I appreciate it! I’ll let you know what I find out, I’ve been searching for a couple of days.

Ok this is going to be long winded, but I solved it. Someone gave me a hint when they said to insert into the sip header as a custom header. I already insert P-Asserted Identity so I had a little experience in this.

First you have to add a pre-dial hook in extensions_custom, here is mine:


exten => s,1,GotoIf($["${custom}" = “SIP/ssi2”]?A2)
exten => s,n,MacroExit()
exten => s,n(A2),Noop(A2 Account Code Added)
exten => s,n,SIPAddHeader(X-Accountcode:${CDR(accountcode)})
exten => s,n,MacroExit()

In this example my trunk name to the A2 box is “ssi2”. So the macro idientifies the trunk and then inserts the account code into a custom sip header: X-Accountcode.

On the A2 machine the call is received under the context from-internal. To make things fir into freepbx, I picked a macro that would normally be called, in this case [macro-user-caller-id]. I copied it into freepbx_extensions_overides, with the first two lines modified to insert my account code info:

include => macro-user-callerid-custom
exten => s,1,Set(CDR(accountcode)=${SIP_HEADER(X-Accountcode)})
exten => s,n,Noop(********* Account code: ${CDR(accountcode))
exten => s,n,Set(AMPUSER=${IF($[“foo${AMPUSER}” = “foo”]?${CALLERID(number)}:${AMPUSER})})
exten => s,n,GotoIf($["${CHANNEL:0:5}" = “Local”]?report)
exten => s,n,ExecIf($["${REALCALLERIDNUM:1:2}" = “”]?Set(REALCALLERIDNUM=${CALLERID(number)}))
exten => s,n,Set(AMPUSER=${DB(DEVICE/${REALCALLERIDNUM}/user)})
exten => s,n,Set(AMPUSERCIDNAME=${DB(AMPUSER/${AMPUSER}/cidname)})
exten => s,n,GotoIf($[“x${AMPUSERCIDNAME:1:2}” = “x”]?report)
exten => s,n,Set(AMPUSERCID=${IF($["${DB_EXISTS(AMPUSER/${AMPUSER}/cidnum)}" = “1”]?${DB_RESULT}:${AMPUSER})})
exten => s,n,Set(CALLERID(all)="${AMPUSERCIDNAME}" <${AMPUSERCID}>)
exten => s,n,ExecIf($["${DB(AMPUSER/${AMPUSER}/language)}" != “”]?Set(CHANNEL(language)=${DB(AMPUSER/${AMPUSER}/language)}))
exten => s,n(report),GotoIf($[ “${ARG1}” = “SKIPTTL” ]?continue)
exten => s,n(report2),Set(__TTL=${IF($[“foo${TTL}” = “foo”]?64:$[ ${TTL} - 1 ])})
exten => s,n,GotoIf($[ ${TTL} > 0 ]?continue)
exten => s,n,Wait(${RINGTIMER})
exten => s,n,Answer
exten => s,n,Wait(2)
exten => s,n,Playback(im-sorry&an-error-has-occured&with&call-forwarding)
exten => s,n,Macro(hangupcall,)
exten => s,n,Congestion(20)
exten => s,n(continue),Set(CALLERID(number)=${CALLERID(number):0:40})
exten => s,n,Set(CALLERID(name)=${CALLERID(name):0:40})
exten => s,n,Noop(Using CallerID ${CALLERID(all)})
exten => h,1,Macro(hangupcall,)

; end of [macro-user-callerid]

Viola! the accountcode variable is now set from the extension that call ed from the remote machine. A2 billing now automatically knows what to do with it, rates, and routes it accordingly.


xecuting [[email protected]:1] Set(“SIP/SSI2-00000014”, “CDR(accountcode)=1046910106”) in new stack
– Executing [[email protected]:2] NoOp(“SIP/SSI2-00000014”, “********* Account code: 1046910106”) in new stack

I hope that might help someone else out. You could essentially send any variable you wanted, not just the account code.


Great job Mike. This is a perfect example of the power of Open Source.

We get so many questions on how to do this or that because users view this as an integrated product and not a series of tools. The possibilities are only limited by your imagination, knowledge or pocket book!

Glad you got what you needed working.


I have A2billing and Freepbx in the same box and freepbx_extensions_overrides read before extensions.conf, so how can I handle that?


Sorry, I’m not sure what your trying to do.

My problem was getting the account code to another machine. If your running on the same machine you shouldn’t have that problem. You just need to set up a trunk that talks to A2 billing as far as I know.

This tutorial is dates but its what I used to give me some clues on how to install A2 with freepbx:

Hi thanks Mike.

I have Elastix 2.3.0, everything works well and the system is generally very flexible.

I’m looking for a billing solution to setup a monthly subscription and online payment for my customers without pins (using FreePBX extensions account code).
But my issues are I have to use Follow-me option, I don’t have any online extensions, my subscribes have an ATA with sip-trunk to my Elastix, and my outbound trunks are custom trunks.

Macemace - Do not hijack threads with a new question.