The following sections include examples for making an outbound call by creating a LiveKit SIP participant and configuring call settings for dialing out. To create an AI agent to make outbound calls on your behalf, see the Voice AI telephony guide.
Creating a SIP participant
To make outbound calls with SIP Service, create a SIP participant with the CreateSIPParticipant
API. It returns an SIPParticipantInfo
object that describes the participant.
Outbound calling requires at least one Outbound Trunk.
Create a
sip-participant.json
file with the following participant details:{"sip_trunk_id": "<your-trunk-id>","sip_call_to": "<phone-number-to-dial>","room_name": "my-sip-room","participant_identity": "sip-test","participant_name": "Test Caller","krisp_enabled": true,"wait_until_answered": true}Create the SIP Participant using the CLI. After you run this command, the participant makes a call to the
sip_call_to
number configured in your outbound trunk. When you setwait_until_answered
totrue
, the command waits until the callee picks up the call before returning. You can also monitor the call status using the SIP participant attributes. When the callee picks up the call, thesip.callStatus
attribute isactive
.lk sip participant create sip-participant.json
import { SipClient } from 'livekit-server-sdk';const sipClient = new SipClient(process.env.LIVEKIT_URL,process.env.LIVEKIT_API_KEY,process.env.LIVEKIT_API_SECRET);// Outbound trunk to use for the callconst trunkId = '<your-trunk-id>';// Phone number to dialconst phoneNumber = '<phone-number-to-dial>';// Name of the room to attach the call toconst roomName = 'my-sip-room';const sipParticipantOptions = {participantIdentity: 'sip-test',participantName: 'Test Caller',krispEnabled: true,waitUntilAnswered: true};async function main() {try {const participant = await sipClient.createSipParticipant(trunkId,phoneNumber,roomName,sipParticipantOptions);console.log('Participant created:', participant);} catch (error) {console.error('Error creating SIP participant:', error);}}main();
import asynciofrom livekit import apifrom livekit.protocol.sip import CreateSIPParticipantRequest, SIPParticipantInfoasync def main():livekit_api = api.LiveKitAPI()request = CreateSIPParticipantRequest(sip_trunk_id = "<trunk_id>",sip_call_to = "<phone_number>",room_name = "my-sip-room",participant_identity = "sip-test",participant_name = "Test Caller",krisp_enabled = True,wait_until_answered = True)try:participant = await livekit_api.sip.create_sip_participant(request)print(f"Successfully created {participant}")except Exception as e:print(f"Error creating SIP participant: {e}")finally:await livekit_api.aclose()asyncio.run(main())
require 'livekit'trunk_id = "<trunk_id>";number = "<phone_number>";room_name = "my-sip-room";participant_identity = "sip-test";participant_name = "Test Caller";sip_service = LiveKit::SIPServiceClient.new(ENV['LIVEKIT_URL'],api_key: ENV['LIVEKIT_API_KEY'],api_secret: ENV['LIVEKIT_API_SECRET'])resp = sip_service.create_sip_participant(trunk_id,number,room_name,participant_identity: participant_identity,participant_name: participant_name)puts resp.data
package mainimport ("context""fmt""os"lksdk "github.com/livekit/server-sdk-go/v2""github.com/livekit/protocol/livekit")func main() {trunkId := "<trunk_id>";phoneNumber := "<phone_number>";roomName := "my-sip-room";participantIdentity := "sip-test";participantName := "Test Caller";request := &livekit.CreateSIPParticipantRequest {SipTrunkId: trunkId,SipCallTo: phoneNumber,RoomName: roomName,ParticipantIdentity: participantIdentity,ParticipantName: participantName,KrispEnabled: true,WaitUntilAnswered: true,}sipClient := lksdk.NewSIPClient(os.Getenv("LIVEKIT_URL"),os.Getenv("LIVEKIT_API_KEY"),os.Getenv("LIVEKIT_API_SECRET"))// Create trunkparticipant, err := sipClient.CreateSIPParticipant(context.Background(), request)if err != nil {fmt.Println(err)} else {fmt.Println(participant)}}
Once the user picks up, they will be connected to my-sip-room
.
Making a call with extension codes (DTMF)
To make outbound calls with fixed extension codes (DTMF tones), set dtmf
field in CreateSIPParticipant
request:
{"sip_trunk_id": "<your-trunk-id>","sip_call_to": "<phone-number-to-dial>","dtmf": "*123#ww456","room_name": "my-sip-room","participant_identity": "sip-test","participant_name": "Test Caller"}
const sipParticipantOptions = {participantIdentity: 'sip-test',participantName: 'Test Caller',dtmf: '*123#ww456'};
request = CreateSIPParticipantRequest(sip_trunk_id = "<trunk_id>",sip_call_to = "<phone_number>",room_name = "my-sip-room",participant_identity = "sip-test",participant_name = "Test Caller",dtmf = "*123#ww456")
resp = sip_service.create_sip_participant(trunk_id,number,room_name,participant_identity: participant_identity,participant_name: participant_name,dtmf: "*123#ww456")
request := &livekit.CreateSIPParticipantRequest{SipTrunkId: trunkId,SipCallTo: phoneNumber,RoomName: roomName,ParticipantIdentity: participantIdentity,ParticipantName: participantName,Dtmf: "*123#ww456",}
Character w
can be used to delay DTMF by 0.5 sec.
This example will dial a specified number and will send the following DTMF tones:
*123#
- Wait 1 sec
456
Playing dial tone while the call is dialing
SIP participants emit no audio by default while the call connects. This can be changed by setting play_dialtone
field in CreateSIPParticipant
request:
{"sip_trunk_id": "<your-trunk-id>","sip_call_to": "<phone-number-to-dial>","room_name": "my-sip-room","participant_identity": "sip-test","participant_name": "Test Caller","play_dialtone": true}
const sipParticipantOptions = {participantIdentity: 'sip-test',participantName: 'Test Caller',playDialtone: true};
request = CreateSIPParticipantRequest(sip_trunk_id = "<trunk_id>",sip_call_to = "<phone_number>",room_name = "my-sip-room",participant_identity = "sip-test",participant_name = "Test Caller",play_dialtone = True)
resp = sip_service.create_sip_participant(trunk_id,number,room_name,participant_identity: participant_identity,participant_name: participant_name,play_dialtone: true)
request := &livekit.CreateSIPParticipantRequest{SipTrunkId: trunkId,SipCallTo: phoneNumber,RoomName: roomName,ParticipantIdentity: participantIdentity,ParticipantName: participantName,PlayDialtone: true,}
If play_dialtone
is enabled, the SIP Participant plays a dial tone to the room until the phone is picked up.