Numbers
Calls reach your SIP server only for numbers attached to your trunk, and your PBX can only call out from those numbers. This page covers finding numbers you can attach, attaching them and detaching them.
Requires an API key, or the session of the account owner or a manager. See Authentication.
A number is on one trunk or one SFVoPI app at a time. Attaching a number that is on another trunk or an SFVoPI app fails with an error. We never move a number from one trunk or app to another for you. See One number, one owner.
Replace 101 with your trunk ID and +91XXXXXXXXXX with your own numbers.
Get available numbers
List the numbers you can attach to a trunk. A number is listed when it:
- is a Superfone number on your account,
- is in service,
- is not linked to an SFVoPI app, and
- is not attached to any trunk.
HTTP request
GET /sf-trunks/available-numbers
Code examples
- cURL
- JavaScript
- TypeScript
- Python
curl https://prod-api.superfone.co.in/superfone/sf-trunks/available-numbers \
-H "X-API-Key: your_api_key_here"
const response = await fetch('https://prod-api.superfone.co.in/superfone/sf-trunks/available-numbers', {
headers: {
'X-API-Key': 'your_api_key_here'
}
});
const result = await response.json();
console.log(result.data.numbers);
interface AvailableNumber {
id: number;
voip_number: string;
provider: string;
status: string;
}
const response = await fetch('https://prod-api.superfone.co.in/superfone/sf-trunks/available-numbers', {
headers: {
'X-API-Key': 'your_api_key_here'
}
});
const result: ApiResponse<{ numbers: AvailableNumber[] }> = await response.json();
console.log(result.data.numbers.map(number => number.voip_number));
import requests
url = 'https://prod-api.superfone.co.in/superfone/sf-trunks/available-numbers'
headers = {
'X-API-Key': 'your_api_key_here'
}
response = requests.get(url, headers=headers)
result = response.json()
print(result['data']['numbers'])
Success response
Status Code: 200 OK
{
"data": {
"numbers": [
{
"id": 5001,
"voip_number": "+91XXXXXXXXXX",
"provider": "carrier_a",
"status": "paid"
},
{
"id": 5002,
"voip_number": "+91YYYYYYYYYY",
"provider": "carrier_b",
"status": "trial_active"
}
]
},
"message": "success"
}
Response fields
| Field | Type | Description |
|---|---|---|
data.numbers | array | Numbers you can attach, sorted by number. Empty if there are none |
data.numbers[].id | number | The number's ID. The other SF Trunk endpoints take the number itself, not this ID |
data.numbers[].voip_number | string | The number in E.164 format. Send this value when you attach |
data.numbers[].provider | string | Internal carrier identifier. Treat it as opaque. Values may change without notice |
data.numbers[].status | string | The number's service state, paid or trial_active. Numbers that are not in service are not listed |
Error responses
| Status Code | Message | When It Occurs |
|---|---|---|
401 | UnAuthorized, Please Provide Valid API Key | The API key is not valid |
401 | UnAuthorized, Please Login | No valid session |
403 | Only owners and managers can perform this action | You are signed in with a session, but not as the owner or a manager of the account |
Attach numbers
Attach one or more of your numbers to a trunk. All the numbers on a trunk share its capacity limits.
HTTP request
POST /sf-trunks/:id/numbers
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The trunk ID |
Request body
| Field | Type | Required | Default | Description | Validation |
|---|---|---|---|---|---|
voip_numbers | string[] | Yes | - | Numbers to attach, in E.164 format, for example +91XXXXXXXXXX | At least one number. A number listed twice is attached once |
The request is all or nothing. If any number fails a check, the request fails and none of the numbers are attached. The error message names the numbers that failed. Remove or fix them and send the request again.
Attaching is idempotent. A number that is already attached to this trunk stays attached and is not added again, and the request does not fail because of it. You can safely retry a request, for example after a timeout. Either way, data.numbers in the response lists every number on the trunk.
Code examples
- cURL
- JavaScript
- TypeScript
- Python
curl -X POST https://prod-api.superfone.co.in/superfone/sf-trunks/101/numbers \
-H "X-API-Key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"voip_numbers":["+91XXXXXXXXXX","+91YYYYYYYYYY"]}'
const trunkId = 101;
const response = await fetch(`https://prod-api.superfone.co.in/superfone/sf-trunks/${trunkId}/numbers`, {
method: 'POST',
headers: {
'X-API-Key': 'your_api_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
voip_numbers: ['+91XXXXXXXXXX', '+91YYYYYYYYYY']
})
});
const result = await response.json();
console.log(result.data.numbers);
interface AttachNumbersRequest {
voip_numbers: string[];
}
const trunkId = 101;
const response = await fetch(`https://prod-api.superfone.co.in/superfone/sf-trunks/${trunkId}/numbers`, {
method: 'POST',
headers: {
'X-API-Key': 'your_api_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
voip_numbers: ['+91XXXXXXXXXX', '+91YYYYYYYYYY']
} as AttachNumbersRequest)
});
const result: ApiResponse<{ numbers: string[] }> = await response.json();
console.log(result.data.numbers);
import requests
trunk_id = 101
url = f'https://prod-api.superfone.co.in/superfone/sf-trunks/{trunk_id}/numbers'
headers = {
'X-API-Key': 'your_api_key_here',
'Content-Type': 'application/json'
}
payload = {
'voip_numbers': ['+91XXXXXXXXXX', '+91YYYYYYYYYY']
}
response = requests.post(url, headers=headers, json=payload)
result = response.json()
print(result['data']['numbers'])
Success response
Status Code: 200 OK
{
"data": {
"numbers": ["+91XXXXXXXXXX", "+91YYYYYYYYYY"]
},
"message": "success"
}
| Field | Type | Description |
|---|---|---|
data.numbers | string[] | Every number now attached to the trunk, in the order they were attached. This includes numbers attached by earlier requests, not only the ones you just sent |
Errors when attaching
| Status Code | Message | When It Occurs |
|---|---|---|
400 | Required | voip_numbers is missing |
400 | Array must contain at least 1 element(s) | voip_numbers is empty |
400 | Invalid voip_number: <number> | A number is not a valid phone number. Write it in E.164 format, for example +91XXXXXXXXXX |
400 | Number(s) not allocated to this org: <numbers> | A number is not a Superfone number on your account |
400 | Invalid SF trunk id | id is not a positive whole number |
401 | UnAuthorized, Please Provide Valid API Key | The API key is not valid |
401 | UnAuthorized, Please Login | No valid session |
403 | Only owners and managers can perform this action | You are signed in with a session, but not as the owner or a manager of the account |
404 | SF trunk not found | No trunk with this ID on your account |
409 | Number(s) already linked to a VoPI app: <numbers> | A number is linked to an SFVoPI app. Unlink it from the app first |
409 | Number(s) linked to an SFVoPI app (inactive); unlink them from the app first: <numbers> | A number has an inactive SFVoPI app link. Unlink it from the app first |
409 | Number(s) already attached to another SF trunk: <numbers> | A number is attached to another trunk. Detach it from that trunk first |
409 | Number(s) not in a serviceable state: <numbers> | A number is not in service, for example on hold or refunded. Email hello@superfone.in |
When numbers in one request fail different checks, the response reports one check at a time. Fix the numbers it names and send the request again.
Example error response
{
"message": "Number(s) already attached to another SF trunk: +91XXXXXXXXXX"
}
Detach a number
Detach one number from a trunk. The number goes back to working like any other Superfone number, and you can attach it to a trunk again.
HTTP request
DELETE /sf-trunks/:id/numbers/:number
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The trunk ID |
number | string | Yes | The number to detach, in E.164 format, for example +91XXXXXXXXXX. URL-encode the + as %2B |
No request body required.
Code examples
- cURL
- JavaScript
- TypeScript
- Python
curl -X DELETE https://prod-api.superfone.co.in/superfone/sf-trunks/101/numbers/%2B91XXXXXXXXXX \
-H "X-API-Key: your_api_key_here"
const trunkId = 101;
const number = encodeURIComponent('+91XXXXXXXXXX');
const response = await fetch(`https://prod-api.superfone.co.in/superfone/sf-trunks/${trunkId}/numbers/${number}`, {
method: 'DELETE',
headers: {
'X-API-Key': 'your_api_key_here'
}
});
const result = await response.json();
console.log(result.data.detached);
const trunkId = 101;
const number = encodeURIComponent('+91XXXXXXXXXX');
const response = await fetch(`https://prod-api.superfone.co.in/superfone/sf-trunks/${trunkId}/numbers/${number}`, {
method: 'DELETE',
headers: {
'X-API-Key': 'your_api_key_here'
}
});
const result: ApiResponse<{ detached: boolean }> = await response.json();
console.log(result.data.detached);
import requests
from urllib.parse import quote
trunk_id = 101
number = quote('+91XXXXXXXXXX', safe='')
url = f'https://prod-api.superfone.co.in/superfone/sf-trunks/{trunk_id}/numbers/{number}'
headers = {
'X-API-Key': 'your_api_key_here'
}
response = requests.delete(url, headers=headers)
result = response.json()
print(result['data']['detached'])
Success response
Status Code: 200 OK
{
"data": {
"detached": true
},
"message": "success"
}
| Field | Type | Description |
|---|---|---|
data.detached | boolean | Always true on success |
Error responses
| Status Code | Message | When It Occurs |
|---|---|---|
400 | Invalid voip_number: <number> | The number in the path is not a valid phone number |
400 | Invalid SF trunk id | id is not a positive whole number |
401 | UnAuthorized, Please Provide Valid API Key | The API key is not valid |
401 | UnAuthorized, Please Login | No valid session |
403 | Only owners and managers can perform this action | You are signed in with a session, but not as the owner or a manager of the account |
404 | SF trunk not found | No trunk with this ID on your account |
404 | Number is not attached to this SF trunk | The number is not attached to this trunk |
URL encoding
Phone numbers start with +. Encode it in the path:
| Original | URL-Encoded |
|---|---|
+91XXXXXXXXXX | %2B91XXXXXXXXXX |
- JavaScript/TypeScript:
encodeURIComponent('+91XXXXXXXXXX') - Python:
urllib.parse.quote('+91XXXXXXXXXX', safe='')
One number, one owner
A number has exactly one owner at a time: one trunk or one SFVoPI app.
- Attaching a number that is linked to an SFVoPI app, even through an inactive link, or attached to another trunk, fails with
409and names the number. - Attaching a number that is already on this trunk is not treated as a conflict. It stays attached. See Attach numbers.
- Linking a trunk number to an SFVoPI app fails the same way, with
409andVoIP number is already attached to an SF trunk: <number>. - We never move a number for you. To move one, detach it from its trunk or unlink it from its app, then attach it where you want it.
- Deleting a trunk detaches all its numbers.
Next Steps
- Inbound calls: what your SIP server receives for an attached number
- Outbound calls: use an attached number as the caller ID
- Troubleshooting: errors when attaching a number