Skip to content

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)
  • Roleadmin, supervisor, agent, or user
  • Asterisk endpoint — auto-generated PJSIP config for SIP phone registration
  • Phone number (optional) — external number for forwarding
  • Ring targetext (SIP phone) or phone (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 .wav files 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.