GrandEstancia Setup¶
This guide documents the GrandEstancia organization setup on AstraPBX, including reception department configuration, DID assignment, and call routing.
Organization Details¶
| Field | Value |
|---|---|
| Org ID | ba50c665-7ab4-4f04-a301-eccc395dc42b |
| Name | GrandEstancia |
| Context Prefix | org_mnd5khym_ |
| API Key | <GE_API_KEY> |
Users¶
| Username | Extension | Asterisk Endpoint | User ID |
|---|---|---|---|
| Hari | 1001 | org_mnd5khym_1001 | <USER_ID> |
| Surya | 1002 | org_mnd5khym_1002 | bc49cda3-d858-49b8-a2ef-06af2a45c303 |
Reception Department (Queue)¶
The reception "department" is implemented as an Asterisk queue with linear ring strategy.
| Field | Value |
|---|---|
| Queue ID | 4552f60b-cc18-4c47-8bee-2d95b94512d2 |
| Name | reception |
| Number | 5001 |
| Strategy | linear (rings members in order by penalty) |
| Timeout | 15 seconds per member |
| Retry | 3 seconds between retries |
| Recording | Enabled |
Ring Order¶
With linear strategy and penalty-based ordering:
- Hari (ext 1001, penalty 0) — rings first for 15 seconds
- Surya (ext 1002, penalty 1) — rings next if Hari doesn't answer
DID Assignment¶
| Field | Value |
|---|---|
| DID Number | 08065978002 |
| DID ID | 8d7d7db4-9183-4499-a15f-9722fce0e3d0 |
| Trunk | Tata SIP Trunk (peer2peer, via NUC WireGuard) |
| Trunk ID | f0182848-d091-4717-bc95-056d0c3c452c |
| Routing Type | queue |
| Routing Destination | 5001 (reception queue) |
| Recording | Enabled |
Inbound Call Flow¶
graph TD
A[Caller dials 08065978002] --> B[Tata PSTN]
B --> C[NUC Gateway - SIP over NNI]
C --> D[WireGuard Tunnel 10.10.10.2 → 10.10.10.1]
D --> E[Cloud Asterisk]
E --> F[Match DID in org_mnd5khym__incoming context]
F --> G[Route to org_mnd5khym__queue context, ext 5001]
G --> H[Queue: reception - linear strategy]
H --> I[Ring Hari ext 1001 - 15s timeout]
I -->|No answer| J[Ring Surya ext 1002 - 15s timeout]
I -->|Answer| K[Call connected to Hari]
J -->|Answer| L[Call connected to Surya]
J -->|No answer| M[Queue timeout - play unavailable message] API Usage¶
Authentication¶
All API calls use the org API key:
Or use a JWT Bearer token obtained from /api/v1/auth/login.
1. Click-to-Call to Reception Department¶
Originate a call that rings the from extension first, then connects to the reception queue.
curl -X POST 'https://devpbx.astradial.com/api/v1/calls/click-to-call' \
-H 'x-api-key: <GE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"from": "1001",
"to": "5001",
"to_type": "queue",
"caller_id": "1001",
"timeout": 30
}'
Parameters:
| Field | Description |
|---|---|
from | Extension to ring first (the agent initiating) |
from_type | "extension" (default) or "external" |
to | Queue number (5001 for reception) |
to_type | Must be "queue" for department routing |
caller_id | Caller ID shown to the queue members |
timeout | Seconds to wait for from to answer |
2. Click-to-Call External Number and Connect to Reception¶
Call an external phone number and when they answer, connect them to the reception queue:
curl -X POST 'https://devpbx.astradial.com/api/v1/calls/click-to-call' \
-H 'x-api-key: <GE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"from": "+919944421125",
"from_type": "external",
"to": "5001",
"to_type": "queue",
"caller_id": "08065978002",
"timeout": 30
}'
This will:
- Dial
+919944421125via the Tata outbound trunk - When they answer, connect them to the reception queue (5001)
- Queue rings Hari first (15s), then Surya (15s)
Outbound Calls Working
Outbound calls via the Tata trunk are operational. The caller ID is set to 08065978002 (the org DID) and the NUC converts to E.164 format for Tata.
3. Transfer Active Call to Reception Department¶
Transfer a live call to the reception queue using the channel ID.
curl -X POST 'https://devpbx.astradial.com/api/v1/calls/{channelId}/transfer' \
-H 'x-api-key: <GE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"destination": "5001",
"destination_type": "queue"
}'
Parameters:
| Field | Description |
|---|---|
destination | Queue number (5001 for reception) |
destination_type | "queue", "extension", or "external" |
Getting the Channel ID
To transfer a call, you need the active channel ID. You can get active channels from the call events webhook or by querying active calls.
4. Click-to-Call to Specific Extension¶
Call a specific user directly (bypassing the queue):
curl -X POST 'https://devpbx.astradial.com/api/v1/calls/click-to-call' \
-H 'x-api-key: <GE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"from": "1001",
"to": "1002",
"to_type": "extension",
"caller_id": "1001"
}'
Outbound Calling¶
Outbound calls from Zoiper and phone number forwarding both route through the Tata trunk via the NUC gateway.
| Field | Value |
|---|---|
| Outbound Route | Tata Outbound (_X. pattern, priority 1) |
| Route ID | 75a7da13-92d6-40d6-95c0-74ba959162ac |
| Caller ID | 08065978002 (DID number) |
| Trunk | org_mnd5khym_trunk1774876586092 → NUC 10.10.10.2 |
Outbound Call Flow¶
graph TD
A[User dials number<br/>from Zoiper] --> B[Cloud Asterisk<br/>outbound context]
B --> C[Set CALLERID = 08065978002]
C --> D[PJSIP Dial via trunk<br/>to NUC 10.10.10.2]
D --> E[NUC from-cloud context]
E --> F[Strip leading 0 from CID<br/>Add +91 prefix]
F --> G[Prepend 0 to dialed number<br/>for national format]
G --> H[Dial via Tata endpoint<br/>to 10.79.215.102]
H --> I[Tata PSTN<br/>Call connected] Number Transformation¶
| Stage | Caller ID | Dialed Number |
|---|---|---|
| User dials | 1002 (extension) | 7400464659 |
| Cloud outbound | 08065978002 (DID override) | 7400464659 |
NUC from-cloud | +918065978002 (E.164) | 07400464659 (national) |
Phone Number Forwarding¶
Users can have calls forwarded to an external phone number instead of ringing their SIP endpoint.
| User | Extension | Phone Number | Ring Target |
|---|---|---|---|
| Hari | 1001 | 7400464659 | phone or ext |
Configure via API¶
# Set ring target to phone
curl -X PUT 'https://devpbx.astradial.com/api/v1/users/<USER_ID>' \
-H 'X-API-Key: <GE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"ring_target": "phone", "phone_number": "7400464659"}'
# Redeploy config
curl -X POST 'https://devpbx.astradial.com/api/v1/config/deploy' \
-H 'X-API-Key: <GE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"reload": true}'
Set ring target back to SIP extension¶
curl -X PUT 'https://devpbx.astradial.com/api/v1/users/<USER_ID>' \
-H 'X-API-Key: <GE_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{"ring_target": "ext"}'
Bugs Fixed During Setup¶
DID Queue Routing Not Working (dialplanGenerator.js)¶
When a DID's routing_type was "queue" and routing_destination was set to the queue number (e.g., "5001"), the dialplan generator only searched by queue ID, causing a mismatch. The generated dialplan would play "number-not-in-service" instead of routing to the queue.
Fix: Updated dialplanGenerator.js to match queues by both ID and number:
// Before
const queue = org.queues.find(q => q.id === did.routing_destination);
// After
const queue = org.queues.find(q => q.id === did.routing_destination || q.number === did.routing_destination);
Same fix applied for IVR routing.
DID E.164 Number Format Mismatch¶
Tata sends inbound calls with E.164 format (+918065978002) but the DID was stored as 08065978002. The dialplan generator only created patterns for the stored number and + prefix of the stored number — it didn't generate E.164 variants.
Symptom: Cloud Asterisk log showed:
Call (UDP:10.10.10.2:5060) to extension '+918065978002' rejected because extension not found in context 'org_mnd5khym__incoming'
Fix: Updated dialplanGenerator.js generateDidRouting() to also generate E.164 patterns for Indian numbers starting with 0:
// For Indian numbers starting with 0, also match +91 version
// e.g., 08065978002 -> also match +918065978002 and 918065978002
if (cleanNumber.startsWith('0')) {
const e164Number = `91${cleanNumber.substring(1)}`;
// Add patterns for e164Number and +e164Number
}
Outbound + Prefix Not Matching Dialplan¶
Click-to-call with from: "+919944421125" failed because the outbound dialplan pattern _X. only matches digits, not +.
Symptom: Asterisk log showed:
Fix: Added a + prefix handler in dialplanGenerator.js generateOutboundContext():
Tata Trunk Returns 403 on Outbound Calls (FIXED)¶
Outbound calls via the Tata trunk returned 403 Forbidden - 6034 from Tata's SBC.
Root cause: Two issues:
- No caller ID on outbound route —
caller_id_overridewasnull, so Asterisk sentanonymousor the internal extension number. Tata rejects anonymous calls. - NUC double-prefixed caller ID — The NUC's
from-cloudcontext didSet(CALLERID(num)=+91${CALLERID(num)}), turning08065978002into+9108065978002(invalid).
Fix:
- Set
caller_id_override: "08065978002"on the outbound route via API - Fixed NUC
/etc/asterisk/extensions.conf:Set(CALLERID(num)=+91${CALLERID(num):1})— strips the leading0before adding+91
Status: Fixed and working. Outbound calls and phone forwarding both operational.
Codec Translation Error: ulaw to opus (FIXED)¶
Internal calls and phone forwarding failed with Unable to find a codec translation path: (ulaw) -> (opus).
Root cause: User PJSIP endpoints allowed opus but Asterisk only had res_format_attr_opus.so (format description), not codec_opus.so (actual transcoder). Local channels for outbound routing couldn't bridge opus↔ulaw.
Fix: Removed opus from user endpoint allow list in userProvisioningService.js:
Queue Members Showing "Invalid" State (queueService.js)¶
After fixing DID routing, inbound calls reached the queue but failed with "Unable to join queue" because all members showed (Invalid) status.
Root cause: Two issues in queueService.js:
-
Wrong member format — Static queue members in
queues.confuse the formatinterface,penalty,membername,state_interface(4 fields). The generator was producing 5 fields with apausedvalue:PJSIP/endpoint,penalty,paused,"Name",PJSIP/endpoint. Asterisk parsed0(paused) as the member name and rejected the rest. -
Invalid keyword
monitor-join— The queue config includedmonitor-join=yeswhich is not a valid Asterisk queue keyword, producing warnings during reload.
Fix:
// Before (wrong - 5 fields with paused)
return `PJSIP/${endpoint},${penalty},${paused},"${memberName}",PJSIP/${endpoint}`;
// After (correct - 4 fields, no paused)
return `PJSIP/${endpoint},${penalty},"${memberName}",PJSIP/${endpoint}`;
Removed monitor-join=yes from recording section (only monitor-format and monitor-type are valid).
Missing linear Queue Strategy in Database¶
The Queue model defined linear as a valid strategy, but the database ENUM didn't include it. Fixed by altering the column:
ALTER TABLE queues MODIFY COLUMN strategy
ENUM('ringall','roundrobin','leastrecent','fewestcalls','random','rrmemory','linear')
NOT NULL DEFAULT 'ringall';
Date¶
Setup completed: 2026-03-30 Outbound calling & phone forwarding fixed: 2026-03-31