Call Control
Make a Call
RustPBX supports two call methods: SIP and WebRTC, distinguished by path when connecting to RustPBX:
/call/sip: Establish calls using SIP protocol, RTP transmits audio./call/webrtc: Establish calls directly using SDP Offer.
Use the Invite command to initiate a call. When the call is successfully established, you will receive an Answer event, otherwise you will receive a Reject event.
Both calling and answering use CallOption, except for setting the callee address, other parameters are the same, mainly used to configure the following functions:
- TTS: Text-to-speech
- ASR: Speech recognition
- VAD: Voice activity detection
- Recording: Recording
- denoise: Noise reduction
SIP Call
SIP calls need to set the caller (caller) and callee (callee) SIP addresses in CallOption, example:
{
"command": "invite",
"option": {
"caller": "sip:6001@192.168.1.100",
"callee": "sip:6002@192.168.1.100"
}
}
The caller address can be set to the UserAgent's SIP address, default is sip:{localIP}:13050.
The UserAgent's SIP address can be configured in config.toml:
[ua]
addr = "0.0.0.0"
udp_port = 13050 # Avoid using 5060
UserAgent is equivalent to a phone, so it has its own SIP address.
WebRTC Call
WebRTC calls need to set the SDP Offer of the call target in the option.offer field, example:
{
"command": "invite",
"option": {
"offer": "v=0\r\no=- 123456789 2 IN IP4 127.0.0.1\r\n..."
}
}
Answer/Reject
Answering is slightly more complex than calling, requiring Webhook configuration to receive incoming call notifications. There are the following steps:
- Configure Webhook
- When there is an incoming call, RustPBX will send a request to the Webhook address
- WebHook service connects to RustPBX based on the
dialogIdin the request - Send
Acceptcommand to answer, orRejectcommand to reject
Configure Webhook
Configure the Webhook address in config.toml:
[ua.handler]
type = "webhook"
url = "http://localhost:8090/webhook"
method = "POST"
Receive Notification
When there is an incoming call, RustPBX will send a POST request to the Webhook address, example:
{
"event": "invite",
"dialogId": "9zUPiixVNO-xRTf4NqCV-dv9qE2iB",
"caller": "sip:6001@192.168.139.103",
"callee": "sip:192.168.3.197",
"createdAt": "2025-10-23T06:33:26.623706+00:00"
}
The dialogId format is: {call_id}-{tag1}-{tag2}, where tag1 is the lexicographically larger one of from_tag and to_tag, and tag2 is the smaller one.
Connect to RustPBX
Use dialogId as the value of the id parameter to establish a WebSocket connection
'ws://localhost:8080/call/sip?id=9zUPiixVNO-xRTf4NqCV-dv9qE2iB'
Answer/Reject
Then send the Accept (answer) / Reject (reject) command:
Example Code:
There is webhook example code in RustPBX Go SDK, which can be referenced:
func serveWebhook(parent context.Context, option CreateClientOption, addr, prefix string) {
server := gin.Default()
server.POST(prefix, func(c *gin.Context) {
var form IncomingCall
if err := c.ShouldBindJSON(&form); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
client := createClient(parent, option, form.DialogID)
go func() {
ctx, cancel := context.WithCancel(parent)
defer cancel()
err := client.Connect("sip")
if err != nil {
option.Logger.Errorf("Failed to connect to server: %v", err)
}
defer client.Shutdown()
client.Accept(option.CallOption)
time.Sleep(300 * time.Millisecond)
client.TTS(option.Greeting, "", "", true, false, nil, nil, false)
<-ctx.Done()
}()
c.JSON(200, gin.H{"message": "OK"})
})
server.Run(addr)
}
See RustPBX Go SDK for more information.
Transfer
Use the Refer command during a call to transfer the call to another number, used for "transfer to human" scenarios.
Transfer Flow:
- Call is already established, send
Refercommand - RustPBX calls the transfer target
- After the target answers, RustPBX forwards audio between both ends
Hangup
After the call is established, use the Hangup command to hang up the call. Example:
{
"command": "hangup",
"reason": "Normal clearing"
}
Events
Throughout the process from call establishment to end, multiple events will be triggered, as shown:
TrackStart
Create RTP/WebRTC Track
Ringing
Ringing event, the other party has received the call but hasn't answered yet.
Answer
Call established, the other party has answered.
Reject
The other party rejected, or other 4xx errors.
Request failure response code list: Request Failure 4xx
Hangup
After the call is established, the other party hangs up.
TrackEnd
RTP/WebRTC Track ended.
TTS/Play commands also create corresponding Tracks, and will also trigger TrackStart and TrackEnd events. Can be distinguished by TrackId.
See: TTS/Play.
Other Events
ASR and VAD functions will trigger corresponding events, including:
- AsrDelta: Intermediate recognition result, content may change.
- AsrFinal: Final recognition result, content is stable.
- Speaking: Voice activity detection, voice input detected.
- Silence: Voice activity detection, no voice input for a period of time.
For details, see: ASR and VAD.
📄️ CallOption Parameters
Detailed introduction to CallOption parameters