Organization Onboarding Guide¶
This guide is for account managers setting up a new organization on AstraPBX. It covers the full onboarding process from creating the org to enabling outbound calling, with the Why, How, and What for each step.
Use GrandEstancia as the reference implementation.
Prerequisites¶
Before starting, ensure you have:
- [ ] SSH access to the cloud server (
89.116.31.109) - [ ] API access to
https://devpbx.astradial.com/docs(Swagger UI) - [ ] Customer's DID number(s) from the SIP trunk provider
- [ ] List of users with their names, extensions, and roles
- [ ] Department/queue structure (who answers which calls, in what order)
Step 1: Create the Organization¶
Why: Every customer is an isolated tenant. The organization defines the boundary for users, DIDs, routes, queues, and dialplan contexts. All Asterisk configuration is generated per-org.
What: An org gets a unique ID, API key, and context prefix that scopes all its Asterisk resources.
How:
curl -X POST 'https://devpbx.astradial.com/api/v1/orgs' \
-H 'Content-Type: application/json' \
-d '{
"name": "CustomerName",
"plan": "business"
}'
Save the response — you'll need these values for every subsequent step:
| Field | Example | Used For |
|---|---|---|
id | ba50c665-... | All API calls referencing the org |
api_key | org_1938b72... | X-API-Key header for authentication |
context_prefix | org_mnd5khym_ | Asterisk dialplan/PJSIP naming |
Step 2: Create Users¶
Why: Each user gets a PJSIP endpoint (SIP phone registration), an extension number, and optionally an external phone number for call forwarding.
What: Users are the people who answer calls. Each user has:
- Extension — internal number (e.g., 1001)
- Role —
admin,supervisor,agent, oruser - Asterisk endpoint — auto-generated PJSIP config for SIP phone registration
- Phone number (optional) — external number for forwarding
- Ring target —
ext(SIP phone) orphone(external number)
How:
curl -X POST 'https://devpbx.astradial.com/api/v1/users' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{
"username": "Hari",
"email": "hari@customer.com",
"extension": "1001",
"full_name": "Hari Kumar",
"role": "admin",
"password": "securepassword",
"phone_number": "7400464659"
}'
The response includes sip_password and asterisk_endpoint — give these to the user for Zoiper/softphone setup.
Assign Phone Number and Ring Target¶
To route calls to an external phone number instead of the SIP extension:
curl -X PUT 'https://devpbx.astradial.com/api/v1/users/{userId}' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{
"phone_number": "7400464659",
"ring_target": "phone"
}'
ring_target | Behavior |
|---|---|
ext (default) | Rings the user's SIP endpoint (Zoiper/softphone) |
phone | Dials the external phone_number via the outbound trunk |
Ring Target Requires Outbound Route
ring_target: "phone" uses the org's outbound route to reach the external number. Make sure Step 5 (outbound route) is completed first.
Step 3: Create a SIP Trunk¶
Why: The trunk connects AstraPBX to the PSTN. For Tata NNI trunks, the NUC gateway receives calls on the physical SIP interface and forwards them to the cloud via WireGuard.
What: A trunk defines the PJSIP peer that Asterisk uses to send/receive calls to/from the SIP provider.
How:
curl -X POST 'https://devpbx.astradial.com/api/v1/trunks' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{
"name": "Tata SIP Trunk",
"host": "10.10.10.2",
"port": 5060,
"transport": "udp",
"trunk_type": "peer2peer",
"max_channels": 10
}'
Tata Trunk via NUC
For Tata NNI trunks, the host is always 10.10.10.2 (NUC WireGuard IP). The NUC handles the physical SIP connection to Tata's SBC and forwards via the tunnel.
Step 4: Assign DID Numbers¶
Why: DID (Direct Inward Dialing) numbers are the public phone numbers customers call. Each DID is routed to a specific destination — an extension, queue (department), or IVR.
What: A DID maps an incoming phone number to a routing destination inside the org.
How:
curl -X POST 'https://devpbx.astradial.com/api/v1/dids' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{
"number": "08065978002",
"trunk_id": "{trunk_id}",
"description": "Main reception line",
"routing_type": "queue",
"routing_destination": "5001",
"recording_enabled": true
}'
routing_type | routing_destination | Description |
|---|---|---|
extension | 1001 | Direct to a user's extension |
queue | 5001 | Route to a department queue |
ivr | {ivr_id} | Route to an IVR menu |
Step 5: Create Departments (Queues)¶
Why: Departments distribute incoming calls across a team. When a caller reaches the reception queue, it rings team members in sequence until someone answers.
What: A queue defines ring strategy, timeout, and member priority.
How:
curl -X POST 'https://devpbx.astradial.com/api/v1/queues' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{
"name": "reception",
"number": "5001",
"strategy": "linear",
"timeout": 15,
"retry": 3,
"max_wait_time": 120,
"recording_enabled": true
}'
Add Members to Queue¶
curl -X POST 'https://devpbx.astradial.com/api/v1/queues/{queueId}/members' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{
"user_id": "{userId}",
"penalty": 0
}'
| Strategy | Behavior |
|---|---|
linear | Rings members in penalty order (0 first, then 1, etc.) |
ringall | Rings all members simultaneously |
roundrobin | Rotates through members |
leastrecent | Rings the member who has been idle longest |
fewestcalls | Rings the member with fewest completed calls |
Penalty = Ring Priority
Lower penalty = rings first. Set penalty 0 for primary agent, 1 for backup, etc.
Step 6: Configure Outbound Route¶
Why: Outbound routes allow users to make external calls from their softphones and enable ring_target: "phone" forwarding. Without an outbound route, no calls can leave the system.
What: An outbound route maps dialed number patterns to a trunk and sets the caller ID for outgoing calls.
How:
curl -X POST 'https://devpbx.astradial.com/api/v1/outbound-routes' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{
"name": "Tata Outbound",
"trunk_id": "{trunk_id}",
"dial_pattern": "_X.",
"caller_id_override": "08065978002",
"caller_id_name_override": "CustomerName",
"recording_enabled": true,
"priority": 1
}'
Caller ID is Required
caller_id_override must be set to the org's DID number. Without it, the Tata trunk sends anonymous caller ID and returns 403 Forbidden. See Troubleshooting: Tata 403 on Outbound.
Number Format for Tata Trunk¶
| What User Dials | What Reaches NUC | NUC Transforms To | Sent to Tata |
|---|---|---|---|
7400464659 | 7400464659 | 07400464659 | National format |
+917400464659 | 917400464659 | 0917400464659 | Stripped +, prepend 0 |
The cloud outbound context strips + prefix. The NUC prepends 0 for national dialing format and converts caller ID to E.164 (+918065978002).
Step 7: Deploy Configuration¶
Why: All the API changes update the database. To take effect in Asterisk, the configuration must be deployed (generates .conf files) and reloaded.
How:
curl -X POST 'https://devpbx.astradial.com/api/v1/config/deploy' \
-H 'X-API-Key: org_XXXX' \
-H 'Content-Type: application/json' \
-d '{"reload": true}'
This generates three files and reloads Asterisk:
| File | Contains |
|---|---|
pjsip_{orgname}.conf | User endpoints, trunk endpoint, AOR, identify |
ext_{orgname}.conf | Dialplan: internal, incoming, outbound, queue contexts |
queues_{orgname}.conf | Queue definitions and static members |
No Downtime
"reload": true uses core reload which applies changes without dropping active calls.
Step 8: Verify Setup¶
Checklist¶
- [ ] Users registered — Check in Zoiper or via API:
GET /api/v1/users - [ ] Inbound calls work — Call the DID from an external phone, verify it reaches the queue
- [ ] Queue rings correctly — Verify ring order matches penalty assignments
- [ ] Outbound calls work — Dial an external number from Zoiper
- [ ] Phone forwarding works — Set
ring_target: "phone"and call the user's extension - [ ] Recording works — Check
/var/spool/asterisk/monitor/for.wavfiles after a call
Useful API Endpoints¶
# List all users
GET /api/v1/users
# List queues and members
GET /api/v1/queues
# List DIDs
GET /api/v1/dids
# List outbound routes
GET /api/v1/outbound-routes
# Check active calls
GET /api/v1/calls/active
# View call history
GET /api/v1/call-records
Complete Call Flow¶
graph TD
A[External Caller] -->|Dials DID 08065978002| B[Tata PSTN]
B --> C[NUC Gateway<br/>10.54.225.90 NNI]
C -->|WireGuard Tunnel| D[Cloud Asterisk<br/>10.10.10.1]
D --> E{DID Routing}
E -->|routing_type: queue| F[Queue 5001<br/>Reception]
E -->|routing_type: extension| G[Direct to Extension]
E -->|routing_type: ivr| H[IVR Menu]
F --> I{ring_target?}
I -->|ext| J[Ring PJSIP Endpoint<br/>Zoiper/Softphone]
I -->|phone| K[Ring External Phone<br/>via Outbound Route]
K --> L[Cloud Outbound Context]
L -->|CALLERID = DID| M[NUC Gateway]
M -->|0 + number, +91 CID| N[Tata PSTN → Phone] GrandEstancia Reference¶
GrandEstancia was the first org onboarded. Use it as a reference:
| Resource | Value |
|---|---|
| Org ID | ba50c665-7ab4-4f04-a301-eccc395dc42b |
| API Key | <GE_API_KEY> |
| DID | 08065978002 |
| Reception Queue | 5001 (linear, Hari → Surya) |
| AI Bot | ext 1003, AudioSocket + Pipecat |
| Swagger UI | https://devpbx.astradial.com/docs |
See GrandEstancia Setup for the full implementation details.