RustPBX API Integration Guide
June 13, 2026 ยท View on GitHub
RustPBX provides a comprehensive set of HTTP APIs and Webhooks designed to make it a fully programmable Software Defined PBX (SD-PBX). This guide details how to integrate your external business logic (CRM, ERP, AI assistants, billing systems) with RustPBX.
๐๏ธ Architecture Overview
RustPBX interacts with external systems in two ways:
- Inbound API (REST): Your system calls RustPBX to manage resources (extensions, trunks) or control active calls.
- Outbound Webhooks: RustPBX calls your system to make routing decisions, report events, or authenticate users.
| Mechanism | Direction | Type | Use Case |
|---|---|---|---|
| Console API | Inbound | REST | CRUD extensions, download recordings, system config |
| Active Call Control | Inbound | REST | Live hangup, transfer, mute, force-accept |
| AMI API | Inbound | REST | Health checks, hot-reload, raw dialog inspection |
| HTTP Router | Outbound | Webhook | Dynamic call routing (per-INVITE decision) |
| User Backend | Outbound | Webhook | External SIP authentication (OAuth/LDAP proxy) |
| Locator Webhook | Outbound | Webhook | Real-time registration/unregistration events |
| Call Record Push | Outbound | Webhook | Push CDR JSON + Audio files to external server |
๐ก 1. Outbound Webhooks (RustPBX โ Your Server)
1.1 HTTP Router (Dynamic Call Routing)
The most powerful extension point. Instead of static routing rules, RustPBX asks your API "Receive call from A to B, what should I do?".
- Trigger: Every incoming SIP INVITE.
- Config:
[proxy.http_router] url = "https://your-api.com/pbx/route" fallback_to_static = true # If your API fails, use internal routes timeout_ms = 5000 [proxy.http_router.headers] X-API-Key = "secret-token"
Request (POST):
{
"call_id": "ab39-551-229",
"from": "<sip:1001@pbx.com>",
"to": "<sip:200@pbx.com>",
"source_addr": "1.2.3.4:5060",
"direction": "inbound", // inbound | outbound | internal
"method": "INVITE",
"uri": "sip:200@pbx.com",
"headers": {
"User-Agent": "Yealink T54W",
"X-Client-ID": "998877"
},
"body": "v=0\r\n..." // Full SDP body
}
Response:
{
"action": "forward", // Actions: forward | reject | abort | spam | not_handled
"targets": [
"sip:1001@192.168.1.50:5060", // Target 1 (Extension)
"sip:1002@192.168.1.51:5060" // Target 2 (Mobile App)
],
"strategy": "parallel", // parallel (Ring All) | sequential (Failover)
"record": true, // Enable recording for this call
"timeout": 30, // Ring timeout in seconds
"media_proxy": "auto", // auto | always | none | nat
"headers": { // Inject custom SIP headers into the INVITE sent to B
"X-Call-Reason": "support-ticket-123"
}
}
1.2 User Backend (SIP Authentication)
Delegate SIP registration password checking to your external DB or API.
- Trigger: SIP REGISTER or INVITE with auth.
- Config:
[[proxy.user_backends]] type = "http" url = "https://your-api.com/pbx/auth" username_field = "u" realm_field = "r"
Request (GET): https://your-api.com/pbx/auth?u=1001&r=pbx.com
Response (200 OK):
{
"id": 1001,
"username": "1001",
"password": "hashed_password_or_plaintext", // HA1 hash preferred
"display_name": "John Doe",
"email": "john@pbx.com",
"allow_guest_calls": false
}
Response (403 Forbidden):
{ "reason": "invalid_password", "message": "Account locked" }
1.3 Locator Webhook (Presence Events)
Real-time notification when devices come online or go offline.
- Config:
[proxy.locator_webhook] url = "https://your-api.com/pbx/events" events = ["registered", "unregistered", "offline"]
Payload:
{
"event": "registered",
"timestamp": 1708201234,
"location": {
"aor": "sip:1001@pbx.com",
"destination": "1.2.3.4:12345",
"transport": "TLS",
"user_agent": "MicroSIP/3.21.3",
"expires": 3600
}
}
1.4 CDR Event Push and Recording Upload
Push call details immediately after a call ends. Recording media upload is configured separately.
- Config:
[recording] enabled = true auto_start = true type = "http" path = "./config/recorders" url = "https://your-api.com/pbx/recording" [callrecord] type = "http" url = "https://your-api.com/pbx/cdr" # Maximum concurrent post-call CDR save/upload/hook tasks. Default: 64, minimum: 1. max_concurrent = 64 # Accepted for compatibility, but ignored. Use [recording] for media upload. with_media = true
CDR format: multipart/form-data
- Field
calllog.json: The full CDR JSON (see next section).
Recording format: multipart/form-data
- File field
recording: The recorded WAV file. - Fields
call_idandtrack_id: Recording metadata.
๐ 2. Inbound REST API (You โ RustPBX)
Base URL: http://<rustpbx-ip>:8080/console
Authentication: Session cookie (login via /console/login) or API Token (future).
2.1 Active Call Control
Manage calls that are currently in progress.
List Active Calls:
GET /console/calls/active
Control a Call:
POST /console/calls/active/{call_id}/commands
Payloads:
- Hangup:
{ "action": "hangup", "reason": "admin_kick" } - Blind Transfer:
{ "action": "transfer", "target": "sip:1002@pbx.com" } - Mute/Unmute:
{ "action": "mute", "track_id": "audio-0" } // use 'unmute' to reverse - Force Answer (for ringing channels):
{ "action": "accept", "sdp": "v=0..." // Server-generated SDP answer }
2.2 System Management (CRUD)
| Resource | Endpoint | Methods | Description |
|---|---|---|---|
| Extensions | /console/extensions | GET, POST, PUT, DELETE | Manage SIP users |
| Trunks | /console/sip-trunk | GET, POST, PUT, DELETE | Manage upstream carriers |
| Routes | /console/routing | GET, POST, PUT, DELETE | Manage dial plan rules |
| CDRs | /console/call-records | GET, POST (Search) | Query history |
| Recording | /console/call-records/{id}/recording | GET | Stream audio file |
| SIP Flow | /console/call-records/{id}/sip-flow | GET | Get PCAP-like ladder diagram JSON |
2.3 AMI (Admin Interface)
Low-level system operations. Protected by IP whitelist ([ami].allows in config).
Base URL: http://<rustpbx-ip>:8080/ami/v1
- Health:
GET /health- System vital stats (uptime, active calls, load). - Reload:
POST /reload/trunks,/reload/routes,/reload/acl- Hot reload config without restart. - Shutdown:
POST /shutdown- Graceful shutdown (stops accepting new calls, waits for active ones). - Dialogs:
GET /dialogs- Raw dump of internal SIP dialog states (for debugging). - SipFlow signaling:
GET /sipflow/flow/{call_id}- Query SIP ladder data. - SipFlow media:
GET /sipflow/media/{call_id}- Export call media as WAV.
SipFlow endpoints support optional time range query parameters:
start: range start timeend: range end time
Accepted formats:
- RFC3339 datetime, e.g.
2026-04-16T10:00:00+08:00 - Unix timestamp (seconds), e.g.
1713232800
Example:
GET /ami/v1/sipflow/flow/abc123?start=2026-04-16T10:00:00%2B08:00&end=2026-04-16T10:30:00%2B08:00
GET /ami/v1/sipflow/media/abc123?start=1713232800&end=1713234600
๐ ๏ธ Integration Workflows
Scenario A: CRM Click-to-Dial
- User clicks phone number in CRM.
- CRM backend sends
POST /api/v1/commands(Future feature) OR uses AMI to originate call. - Current workaround: CRM sends SIP REFER to RustPBX or uses a dedicated "Click-to-Dial" SIP extension that the web-app registers as.
Scenario B: AI Voice Assistant
- Inbound call hits RustPBX.
- HTTP Router sends INVITE details to AI backend.
- AI Backend returns
{"action": "forward", "targets": ["sip:ai-bot-service@internal"]}. - RustPBX routes audio to the AI bot via SIP/RTP.
Scenario C: Billing System
- User Backend authenticates user, checking balance > 0.
- Call proceeds.
- On hangup, CDR Push sends via HTTP POST to Billing System.
- Billing system calculates duration * rate and deducts balance.
Scenario D: Compliance Recording
Two recording backends are available โ a traditional local file recorder ([recording]) and sipflow ([sipflow]). When both are configured, sipflow takes precedence for media capture and upload, avoiding duplicate local WAV files.
Option 1: SipFlow recording (recommended)
SipFlow captures raw RTP packets and SIP messages, then generates WAV / JSONL on export. No local WAV file is written.
[recording]
enabled = true
auto_start = true
[sipflow]
type = "local"
root = "./config/sipflow"
[sipflow.upload]
type = "s3"
vendor = "aliyun"
bucket = "my-bucket"
region = "oss-cn-hangzhou"
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
root = "recordings"
media = true
signaling = true
When sipflow backend is present, [recording] enables media anchoring only; media capture and upload are handled by sipflow. The WAV is generated on-demand from stored RTP packets via GET /sipflow/media/{call_id} and uploaded to the sipflow S3/HTTP target. Signaling is uploaded as JSONL to the same target.
Option 2: Local file recorder (legacy)
[recording]
enabled = true
auto_start = true
# No [sipflow] section โ falls back to local .wav file
All calls are recorded locally to ./config/recorders/, then asynchronously uploaded via [callrecord] S3 config.