Introduction
A dispatch rule controls how callers are added as SIP participants in rooms. When an inbound call reaches your SIP trunking provider and is connected to LiveKit, the SIP service authenticates the inbound trunk (if applicable) and looks for a matching dispatch rule. It then uses the rule to dispatch SIP participants to rooms.
The dispatch rule can also include room configuration options that specify which agents to dispatch to the room. Agent dispatch is a separate feature that handles how agents are dispatched to rooms. To learn more, see Agent dispatch.
To create a dispatch rule with the SIP service, use the CreateSIPDispatchRule
API. It returns a SIPDispatchRuleInfo
object that describes the dispatch rule.
By default, a dispatch rule matches all your trunks and makes a caller's phone number visible to others in the room. You can modify these defaults using dispatch rule options. For a full list of available options, see the CreateSIPDispatchRule
API reference.
To learn more about, see the following:
- SIP overview: General concepts and features.
- SIP API: API endpoints and types.
Caller dispatch rule (individual)
An SIPDispatchRuleIndividual
rule creates a new room for each caller. The name of the created room is the phone number of the caller plus a random suffix. You can optionally add a specific prefix to the room name by using the roomPrefix
option.
The following examples dispatch callers into individual rooms prefixed with call-
, and dispatches an agent named inbound-agent
to newly created rooms:
{"dispatch_rule":{"rule": {"dispatchRuleIndividual": {"roomPrefix": "call-"}},"name": "My dispatch rule","roomConfig": {"agents": [{"agentName": "inbound-agent","metadata": "job dispatch metadata"}]}}}
const rule: SipDispatchRuleIndividual = {roomPrefix: "call-",type: 'individual',};const options: CreateSipDispatchRuleOptions = {name: 'My dispatch rule',roomConfig: new RoomConfiguration({agents: [new RoomAgentDispatch({agentName: "inbound-agent",metadata: 'dispatch metadata',}),],}),};const dispatchRule = await sipClient.createSipDispatchRule(rule, options);console.log("created dispatch rule", dispatchRule);
from livekit import apilkapi = api.LiveKitAPI()# Create a dispatch rule to place each caller in a separate roomrule = api.SIPDispatchRule(dispatch_rule_individual = api.SIPDispatchRuleIndividual(room_prefix = 'call-',))request = api.CreateSIPDispatchRuleRequest(dispatch_rule = api.SIPDispatchRuleInfo(rule = rule,name = 'My dispatch rule',trunk_ids = [],room_config=api.RoomConfiguration(agents=[api.RoomAgentDispatch(agent_name="inbound-agent",metadata="job dispatch metadata",)])))dispatch = await lkapi.sip.create_sip_dispatch_rule(request)print("created dispatch", dispatch)await lkapi.aclose()
require 'livekit'sip_service = LiveKit::SIPServiceClient.new(ENV['LIVEKIT_URL'],api_key: ENV['LIVEKIT_API_KEY'],api_secret: ENV['LIVEKIT_API_SECRET'])rule = LiveKit::Proto::SIPDispatchRule.new(dispatch_rule_direct: LiveKit::Proto::SIPDispatchRuleIndividual.new(room_prefix: "call-",))resp = sip_service.create_sip_dispatch_rule(rule,name: "My dispatch rule",room_config: LiveKit::Proto::RoomConfiguration.new(agents: [LiveKit::Proto::RoomAgentDispatch.new(agent_name: "inbound-agent",metadata: "job dispatch metadata",)]))puts resp.data
func main() {rule := &livekit.SIPDispatchRule{Rule: &livekit.SIPDispatchRule_DispatchRuleIndividual{DispatchRuleIndividual: &livekit.SIPDispatchRuleIndividual{RoomPrefix: "call-",},},}request := &livekit.CreateSIPDispatchRuleRequest{DispatchRule: &livekit.SIPDispatchRuleInfo{Name: "My dispatch rule",Rule: rule,RoomConfig: &livekit.RoomConfiguration{Agents: []*livekit.RoomAgentDispatch{{AgentName: "inbound-agent",Metadata: "job dispatch metadata",},},},},}sipClient := lksdk.NewSIPClient(os.Getenv("LIVEKIT_URL"),os.Getenv("LIVEKIT_API_KEY"),os.Getenv("LIVEKIT_API_SECRET"))// Execute the requestdispatchRule, err := sipClient.CreateSIPDispatchRule(context.Background(), request)if err != nil {fmt.Println(err)} else {fmt.Println(dispatchRule)}}
Sign in to the LiveKit Cloud dashboard.
Select Telephony → Configuration.
Select Create new → Dispatch rule.
Select the JSON editor tab.
NoteYou can also use the Dispatch rule details tab to create a dispatch rule. However, the JSON editor allows you to configure all available parameters.
Copy and paste the following JSON:
{"rule": {"dispatchRuleIndividual": {"roomPrefix": "call-"}},"name": "My dispatch rule","roomConfig": {"agents": [{"agentName": "inbound-agent","metadata": "job dispatch metadata"}]}}Select Create.
When you omit the trunk_ids
field, the dispatch rule matches calls from all inbound trunks.
Direct dispatch rule
A direct dispatch rule places all callers into a specified room. You can optionally protect room access by adding a pin in the pin
field:
In the following examples, all calls are immediately connected to room open-room
on LiveKit.
Create a file named
dispatch-rule.json
and add the following:{"dispatch_rule":{"rule": {"dispatchRuleDirect": {"roomName": "open-room"}},"name": "My dispatch rule"}}Create the dispatch rule using
lk
:lk sip dispatch create dispatch-rule.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);// Name of the room to attach the call toconst roomName = 'open-room';const dispatchRuleOptions = {name: 'My dispatch rule',};// Dispatch all callers to the same roomconst ruleType = {roomName: roomName,type: 'direct',};const dispatchRule = await sipClient.createSipDispatchRule(ruleType,dispatchRuleOptions);console.log(dispatchRule);
import asynciofrom livekit import apiasync def main():livekit_api = api.LiveKitAPI()# Create a dispatch rule to place all callers in the same roomrule = api.SIPDispatchRule(dispatch_rule_direct = api.SIPDispatchRuleDirect(room_name = 'open-room',))request = api.CreateSIPDispatchRuleRequest(dispatch_rule = api.SIPDispatchRuleInfo(rule = rule,name = 'My dispatch rule',))try:dispatchRule = await livekit_api.sip.create_sip_dispatch_rule(request)print(f"Successfully created {dispatchRule}")except api.twirp_client.TwirpError as e:print(f"{e.code} error: {e.message}")await livekit_api.aclose()asyncio.run(main())
require 'livekit'name = "My dispatch rule"room_name = "open-room"sip_service = LiveKit::SIPServiceClient.new(ENV['LIVEKIT_URL'],api_key: ENV['LIVEKIT_API_KEY'],api_secret: ENV['LIVEKIT_API_SECRET'])rule = LiveKit::Proto::SIPDispatchRule.new(dispatch_rule_direct: LiveKit::Proto::SIPDispatchRuleDirect.new(room_name: room_name,))resp = sip_service.create_sip_dispatch_rule(rule,name: name,)puts resp.data
package mainimport ("context""fmt""os"lksdk "github.com/livekit/server-sdk-go/v2""github.com/livekit/protocol/livekit")func main() {// Specify rule type and optionsrule := &livekit.SIPDispatchRule{Rule: &livekit.SIPDispatchRule_DispatchRuleDirect{DispatchRuleDirect: &livekit.SIPDispatchRuleDirect{RoomName: "open-room",},},}// Create requestrequest := &livekit.CreateSIPDispatchRuleRequest{DispatchRule: &livekit.SIPDispatchRuleInfo{Rule: rule,Name: "My dispatch rule",},}sipClient := lksdk.NewSIPClient(os.Getenv("LIVEKIT_URL"),os.Getenv("LIVEKIT_API_KEY"),os.Getenv("LIVEKIT_API_SECRET"))// Execute the requestdispatchRule, err := sipClient.CreateSIPDispatchRule(context.Background(), request)if err != nil {fmt.Println(err)} else {fmt.Println(dispatchRule)}}
Sign in to the LiveKit Cloud dashboard.
Select Telephony → Configuration.
Select Create new → Dispatch rule.
Select the JSON editor tab.
NoteYou can also use the Dispatch rule details tab for this example by selecting Direct for Rule type.
Copy and paste the following JSON:
{"rule": {"dispatchRuleDirect": {"roomName": "open-room"}},"name": "My dispatch rule"}Select Create.
Pin-protected room
Add a pin
to a room to require callers to enter a pin to connect to a room in LiveKit. The following example requires callers to enter 12345#
on the phone to enter safe-room
:
{"dispatch_rule":{"trunk_ids": [],"rule": {"dispatchRuleDirect": {"roomName": "safe-room","pin": "12345"}},"name": "My dispatch rule"}}
Callee dispatch rule
This creates a dispatch rule that puts callers into rooms based on the called number. The name of the room is the called phone number plus an optional prefix (if roomPrefix
is set). You can optionally add a random suffix for each caller by setting randomize
to true, making a separate room per caller.
{"dispatch_rule":{"rule": {"dispatchRuleCallee": {"roomPrefix": "number-","randomize": false}},"name": "My dispatch rule"}}
Callee dispatch rules can't be created using Node.js.
For an executable example, replace the rule in the Direct dispatch rule example with the following rule:
from livekit import api# Create a dispatch rule to place callers to the same phone number in the same roomrule = api.SIPDispatchRule(dispatch_rule_callee = api.SIPDispatchRuleCallee(room_prefix = 'number-',randomize = False,))
For an executable example, replace the rule in the Direct dispatch rule example with the following rule:
rule = LiveKit::Proto::SIPDispatchRule.new(dispatch_rule_callee: LiveKit::Proto::SIPDispatchRuleCallee.new(room_prefix: 'number-',randomize: false,))
For an executable example, replace the rule in the Direct dispatch rule example with the following rule:
rule := &livekit.SIPDispatchRule{Rule: &livekit.SIPDispatchRule_DispatchRuleCallee{DispatchRuleCallee: &livekit.SIPDispatchRuleCallee{RoomPrefix: "number-",Randomize: false,},},}
Sign in to the LiveKit Cloud dashboard.
Select Telephony → Configuration.
Select Create new → Dispatch rule.
Select the JSON editor tab.
NoteYou can also use the Dispatch rule details tab for this example by selecting Callee for Rule type.
Copy and paste the following JSON:
{"rule": {"dispatchRuleCallee": {"roomPrefix": "number-","randomize": false}},"name": "My dispatch rule"}Select Create.
Setting custom attributes on inbound SIP participants
LiveKit participants have an attributes
field that stores key-value pairs. You can add custom attributes for SIP participants in the dispatch rule. These attributes are inherited by all SIP participants created by the dispatch rule.
To learn more, see SIP participant attributes.
The following examples add two attributes to SIP participants created by this dispatch rule:
{"dispatch_rule":{"attributes": {"<key_name1>": "<value1>","<key_name2>": "<value2>"},"rule": {"dispatchRuleIndividual": {"roomPrefix": "call-"}},"name": "My dispatch rule"}}
For an executable example, replace dispatchRuleOptions
in the Direct dispatch rule example with the following options:
const dispatchRuleOptions = {name: 'My invidividual dispatch rule',attributes: {"<key_name1>": "<value1>","<key_name2>": "<value2>"},};
For an executable example, replace request
in the Direct dispatch rule example with the following options:
request = api.CreateSIPDispatchRuleRequest(dispatch_rule = api.SIPDispatchRuleInfo(rule = rule,name = 'My dispatch rule',attributes = {"<key_name1>": "<value1>","<key_name2>": "<value2>",}))
For an executable example, use the Direct dispatch rule example with the following options:
resp = sip_service.create_sip_dispatch_rule(rule,name: name,attributes: {"<key_name1>" => "<value1>","<key_name2>" => "<value2>",},)
For an executable example, replace request
in the Direct dispatch rule example with the following code:
// Create a requestrequest := &livekit.CreateSIPDispatchRuleRequest{DispatchRule: &livekit.SIPDispatchRuleInfo{Rule: rule,Name: "My dispatch rule",Attributes: map[string]string{"<key_name1>": "<value1>","<key_name2>": "<value2>",},},}
Sign in to the LiveKit Cloud dashboard.
Select Telephony → Configuration.
Select Create new → Dispatch rule.
Select the JSON editor tab.
NoteThe
attributes
parameter is only available in the JSON editor tab.Copy and paste the following text into the editor:
{"name": "My dispatchrule","attributes": {"<key_name1>": "<value1>","<key_name2>": "<value2>"},"rule": {"dispatchRuleIndividual": {"roomPrefix": "call-"}}}Select Create.
Setting custom metadata on inbound SIP participants
LiveKit participants have a metadata
field that can store arbitrary data for your application (typically JSON). It can also be set on SIP participants created by a dispatch rule. Specifically, metadata
set on a dispatch rule will be inherited by all SIP participants created by it.
The following examples add the metadata, {"is_internal": true}
, to all SIP participants created from an inbound call by this dispatch rule:
{"dispatch_rule": {"metadata": "{\"is_internal\": true}","rule": {"dispatchRuleIndividual": {"roomPrefix": "call-"}},"name": "My dispatch rule"}}
For an executable example, replace dispatchRuleOptions
in the Direct dispatch rule example with the following options:
const dispatchRuleOptions = {name: 'My invidividual dispatch rule',metadata: "{\"is_internal\": true}",};
For an executable example, replace request
in the Direct dispatch rule example with the following options:
request = api.CreateSIPDispatchRuleRequest(dispatch_rule = api.SIPDispatchRuleInfo(rule = rule,name = 'My dispatch rule',metadata = "{\"is_internal\": true}",))
For an executable example, use the Direct dispatch rule example with the following options:
resp = sip_service.create_sip_dispatch_rule(rule,name: name,metadata: "{\"is_internal\": true}",)
For an executable example, replace request
in the Direct dispatch rule example with the following options:
// Create a requestrequest := &livekit.CreateSIPDispatchRuleRequest{DispatchRule: &livekit.SIPDispatchRuleInfo{Rule: rule,Name: "My dispatch rule",Metadata: "{\"is_internal\": true}",},}
Sign in to the LiveKit Cloud dashboard.
Select Telephony → Configuration.
Select Create new → Dispatch rule.
Select the JSON editor tab.
NoteThe
metadata
parameter is only available in the JSON editor tab.Copy and paste the following text into the editor:
{"name": "My dispatch rule","metadata": "{\"is_internal\": true}","rule": {"dispatchRuleIndividual": {"roomPrefix": "call-"}}}Select Create.
Update dispatch rule
Use the UpdateSIPDispatchRule
API to update specific fields of a dispatch rule or replace a dispatch rule with a new one.
Update specific fields of a dispatch rule
The UpdateSIPDispatchRuleFields
API allows you to update specific fields of a dispatch rule without affecting other fields.
Create a file named dispatch-rule.json
with the following content:
{"name": "My updated dispatch rule","rule": {"dispatchRuleCallee": {"roomPrefix": "number-","randomize": false,"pin": "1234"}}}
Update the dispatch rule using lk
. You can update the trunks
parameter to a comma-separated string of trunks IDs if the rule matches specific trunks.
lk sip dispatch update --id <dispatch-rule-id> \--trunks "[]" \dispatch-rule.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);const updatedRuleFields = {name: 'My updated dispatch rule',trunkIds: ["<trunk-id1>", "<trunk-id2>"],hidePhoneNumber: true,metadata: "{\"is_internal\": false}",}const rule = await sipClient.updateSipDispatchRuleFields (ruleId,updatedRuleFields,);return rule;
import asynciofrom livekit import apiasync def main():"""Use the update_sip_dispatch_rule_fields method to update specific fields of a dispatch rule."""rule_id = '<dispatch-rule-id>'livekit_api = api.LiveKitAPI()dispatchRule = Nonetry:dispatchRule = await livekit_api.sip.update_sip_dispatch_rule_fields(rule_id=rule_id,metadata = "{\"is_internal\": false}",attributes={"<updated_key1>": "<updated_value1>","<updated_key2>": "<updated_value2>",})print(f"Successfully updated {dispatchRule}")except api.twirp_client.TwirpError as e:print(f"{e.code} error: {e.message}")await livekit_api.aclose()return dispatchRuleasyncio.run(main())
The update API is not yet available in the Ruby SDK.
package mainimport ("context""fmt""os""github.com/livekit/protocol/livekit"lksdk "github.com/livekit/server-sdk-go/v2")func main() {rule_id := "<dispatch-rule-id>"// Update dispatch rulename2 := "My updated dispatch rule"request := &livekit.UpdateSIPDispatchRuleRequest{SipDispatchRuleId: rule_id,Action: &livekit.UpdateSIPDispatchRuleRequest_Update{Update: &livekit.SIPDispatchRuleUpdate{Name: &name2,TrunkIds: &livekit.ListUpdate{Set: []string{"<trunk-id1>", "<trunk-id2>"},},},},}sipClient := lksdk.NewSIPClient(os.Getenv("LIVEKIT_URL"),os.Getenv("LIVEKIT_API_KEY"),os.Getenv("LIVEKIT_API_SECRET"))updated, err := sipClient.UpdateSIPDispatchRule(context.Background(), request)if err != nil {fmt.Println(err)} else {fmt.Println(updated)}}
Update and replace functions are the same in the LiveKit Cloud dashboard. For an example, see the replace dispatch rule section.
Replace dispatch rule
The UpdateSIPDispatchRule
API allows you to replace an existing dispatch rule with a new one using the same dispatch rule ID.
The instructions for replacing a dispatch rule are the same as for updating a dispatch rule.
import { SipClient } from 'livekit-server-sdk';const sipClient = new SipClient(process.env.LIVEKIT_URL,process.env.LIVEKIT_API_KEY,process.env.LIVEKIT_API_SECRET);async function replaceDispatchRule(ruleId) {const updatedRuleOptions = {name: 'My replaced dispatch rule',trunkIds: ["<trunk-id1>", "<trunk-id2>"],hidePhoneNumber: false,metadata: "{\"is_internal\": true}",rule: {rule: {case: "dispatchRuleIndividual", value: individualRuleType},}};const updatedRule = await sipClient.updateSipDispatchRule(ruleId,updatedRuleOptions,);return updatedRule;}await replaceDispatchRule('<dispatch-rule-id>');
import asynciofrom livekit import apiasync def main():"""Use the update_sip_dispatch_rule function to replace a dispatch rule."""livekit_api = api.LiveKitAPI()# Dispatch rule ID of rule to replace.rule_id = '<dispatch-rule-id>'# Dispatch rule type.rule = api.SIPDispatchRule(dispatch_rule_direct = api.SIPDispatchRuleDirect(room_name = "caller-room",pin = '1212'))ruleInfo = api.SIPDispatchRuleInfo(rule = rule,name = 'My replaced dispatch rule',trunk_ids = ["<trunk-id1>", "<trunk-id2>"],hide_phone_number = True,metadata = "{\"is_internal\": false}",attributes = {"<replaced_key_name1>": "<replaced_value1>","<replaced_key_name2>": "<replaced_value2>",},)dispatchRule = Nonetry:dispatchRule = await livekit_api.sip.update_sip_dispatch_rule(rule_id,ruleInfo)print(f"Successfully replaced {dispatchRule}")except api.twirp_client.TwirpError as e:print(f"{e.code} error: {e.message}")await livekit_api.aclose()return dispatchRuleasyncio.run(main())
The update API is not yet available in the Ruby SDK.
package mainimport ("context""fmt""os""github.com/livekit/protocol/livekit"lksdk "github.com/livekit/server-sdk-go/v2")func main() {rule_id := "<dispatch-rule-id>"// Replace dispatch rulerule := &livekit.SIPDispatchRuleInfo{Name: "My replaced dispatch rule",TrunkIds: []string{"<trunk-id1>", "<trunk-id2>"},Rule: &livekit.SIPDispatchRule{Rule: &livekit.SIPDispatchRule_DispatchRuleDirect{DispatchRuleDirect: &livekit.SIPDispatchRuleDirect{RoomName: "my-room",},},},}request := &livekit.UpdateSIPDispatchRuleRequest{SipDispatchRuleId: rule_id,Action: &livekit.UpdateSIPDispatchRuleRequest_Replace{Replace: rule,},}sipClient := lksdk.NewSIPClient(os.Getenv("LIVEKIT_URL"),os.Getenv("LIVEKIT_API_KEY"),os.Getenv("LIVEKIT_API_SECRET"))updated, err := sipClient.UpdateSIPDispatchRule(context.Background(), request)if err != nil {fmt.Println(err)} else {fmt.Println(updated)}}
Sign in to the LiveKit Cloud dashboard.
Select Telephony → Configuration.
Navigate to the Dispatch rules section and find the dispatch rule you want to update.
Select the more (⋮) menu → select Edit.
Select the JSON editor tab and copy and paste the following text into the editor:
{"name": "My replaced dispatch rule","rule": {"dispatchRuleIndividual": {"roomPrefix": "caller-room"}},"trunkIds": ["<trunk-id1>", "<trunk-id2>"],"hidePhoneNumber": false,"metadata": "{\"is_internal\": true}","attributes": {"<replaced_key_name1>": "<replaced_value1>","<replaced_key_name2>": "<replaced_value2>",}}Select Update.
List dispatch rules
Use the ListSIPDispatchRule
API to list all dispatch rules.
lk sip dispatch list
import { SipClient } from 'livekit-server-sdk';const sipClient = new SipClient(process.env.LIVEKIT_URL,process.env.LIVEKIT_API_KEY,process.env.LIVEKIT_API_SECRET);const rules = await sipClient.listSipDispatchRule();console.log(rules);
import asynciofrom livekit import apiasync def main():livekit_api = api.LiveKitAPI()rules = await livekit_api.sip.list_sip_dispatch_rule(api.ListSIPDispatchRuleRequest())print(f"{rules}")await livekit_api.aclose()asyncio.run(main())
require 'livekit'sip_service = LiveKit::SIPServiceClient.new(ENV['LIVEKIT_URL'],api_key: ENV['LIVEKIT_API_KEY'],api_secret: ENV['LIVEKIT_API_SECRET'])resp = sip_service.list_sip_dispatch_rule()puts resp.data
package mainimport ("context""fmt""os"lksdk "github.com/livekit/server-sdk-go/v2""github.com/livekit/protocol/livekit")func main() {sipClient := lksdk.NewSIPClient(os.Getenv("LIVEKIT_URL"),os.Getenv("LIVEKIT_API_KEY"),os.Getenv("LIVEKIT_API_SECRET"))// List dispatch rulesdispatchRules, err := sipClient.ListSIPDispatchRule(context.Background(), &livekit.ListSIPDispatchRuleRequest{})if err != nil {fmt.Println(err)} else {fmt.Println(dispatchRules)}}
- Sign in to the LiveKit Cloud dashboard.
- Select Telephony → Configuration.
- The Dispatch rules section lists all dispatch rules.