SIP Trunks API
SIP trunks connect your agents to phone networks. Configure inbound trunks to receive calls from your SIP infrastructure, or outbound trunks to route agent calls through a specific carrier.
Base URL: https://kalem.me/api/v1/trunks
The Trunk Object
{
"id": 1,
"name": "Main Inbound Trunk",
"direction": "inbound",
"auth_type": "ip",
"sip_uri": "sip:10.0.0.1@kalem.me",
"host": "10.0.0.1",
"port": 5060,
"username": "kalem_trunk",
"outbound_server": null,
"registered": false,
"created_at": "2025-01-10T08:00:00+00:00",
"updated_at": "2025-01-10T08:00:00+00:00"
}
Note: The trunk password is never included in API responses for security reasons.
List Trunks
GET
/api/v1/trunks
Query Parameters
| Parameter | Type | Description |
|---|---|---|
direction | string | Filter: inbound or outbound |
search | string | Search by trunk name |
per_page | integer | Results per page (default: 15, max: 100) |
Example Request
curl -X GET "https://kalem.me/api/v1/trunks?direction=inbound" \
-H "Authorization: Bearer YOUR_API_TOKEN"
const response = await fetch(
'https://kalem.me/api/v1/trunks?direction=inbound',
{ headers: { 'Authorization': 'Bearer YOUR_API_TOKEN' } }
);
const data = await response.json();
import requests
response = requests.get(
'https://kalem.me/api/v1/trunks',
params={'direction': 'inbound'},
headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)
data = response.json()
$response = Http::withToken('YOUR_API_TOKEN')
->get('https://kalem.me/api/v1/trunks', [
'direction' => 'inbound',
]);
$data = $response->json();
Create Trunk
POST
/api/v1/trunks
Request Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Required | Descriptive name for the trunk |
direction | string | Required | inbound or outbound |
auth_type | string | Required | ip (IP-based) or digest (username/password) |
host | string | Conditional | Required for inbound IP auth. IP address or hostname of the source PBX |
port | integer | Optional | SIP port (default: 5060) |
username | string | Conditional | Required for digest auth |
password | string | Conditional | Required for digest auth (min 8 characters) |
outbound_server | string | Conditional | Required for outbound trunks. SIP server address for routing calls |
Example: Inbound Trunk with IP Auth
curl -X POST https://kalem.me/api/v1/trunks \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Office PBX",
"direction": "inbound",
"auth_type": "ip",
"host": "203.0.113.50",
"port": 5060
}'
const response = await fetch('https://kalem.me/api/v1/trunks', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Office PBX',
direction: 'inbound',
auth_type: 'ip',
host: '203.0.113.50',
port: 5060,
}),
});
const data = await response.json();
import requests
response = requests.post(
'https://kalem.me/api/v1/trunks',
json={
'name': 'Office PBX',
'direction': 'inbound',
'auth_type': 'ip',
'host': '203.0.113.50',
'port': 5060,
},
headers={'Authorization': 'Bearer YOUR_API_TOKEN'}
)
data = response.json()
$response = Http::withToken('YOUR_API_TOKEN')
->post('https://kalem.me/api/v1/trunks', [
'name' => 'Office PBX',
'direction' => 'inbound',
'auth_type' => 'ip',
'host' => '203.0.113.50',
'port' => 5060,
]);
$data = $response->json();
Example: Outbound Trunk with Digest Auth
curl -X POST https://kalem.me/api/v1/trunks \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Carrier Outbound",
"direction": "outbound",
"auth_type": "digest",
"username": "my_sip_user",
"password": "secureP@ssw0rd",
"outbound_server": "sip.carrier.com"
}'
Get Trunk
GET
/api/v1/trunks/{id}
curl -X GET https://kalem.me/api/v1/trunks/1 \
-H "Authorization: Bearer YOUR_API_TOKEN"
Update Trunk
PUT
/api/v1/trunks/{id}
curl -X PUT https://kalem.me/api/v1/trunks/1 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Renamed Trunk",
"port": 5080
}'
Delete Trunk
DELETE
/api/v1/trunks/{id}
curl -X DELETE https://kalem.me/api/v1/trunks/1 \
-H "Authorization: Bearer YOUR_API_TOKEN"
Cannot delete: A trunk that has phone numbers assigned to it. Unassign or delete the numbers first.
Error Response (Numbers Assigned)
// HTTP 409 Conflict
{
"message": "Cannot delete trunk with assigned numbers. Remove numbers first."
}