Phone Numbers (DIDs)
Bring your own number or provision a managed business number, and bind numbers to agents.
DIDs (Direct Inward Dialing numbers) are the phone numbers your agents call from and answer on. There are two ways to get one:
- Bring your own (BYO) — register a number you already own with a telephony provider (e.g. Plivo).
- Managed business number — buy a new Indian business number directly through our carrier partner, entirely via the API or dashboard. No provider account needed.
List numbers
Returns every connected number — BYO (mode: "byo") and managed
(mode: "managed").
const dids = await voice.dids.get();dids = client.dids()Bring your own number
Register a number you already own using your provider credentials.
const did = await voice.dids.create({
didNumber: "+918045551234",
provider: "plivo",
bearerToken: "your_provider_auth_token",
isDefault: true,
clientId: "AC123",
});did = client.create_did(
did_number="+918045551234",
provider="plivo",
bearer_token="your_provider_auth_token",
is_default=True,
client_id="AC123",
)Parameters
| Field | Type | Required | Description |
|---|---|---|---|
didNumber / did_number | string | Yes | The phone number to bind, in E.164 format. |
provider | string | Yes | Telephony provider the number is registered with (e.g. plivo). |
bearerToken / bearer_token | string | Yes | Your provider auth token for this number. |
isDefault / is_default | boolean | Yes | Whether this is the default outbound/inbound number. |
clientId / client_id | string | No | Provider account / client identifier. |
Managed business numbers
Get a brand-new Indian business number without owning any telephony accounts. The journey has four steps:
- Pick a number from the catalog (mobile, toll-free, or landline).
- Submit KYC — identity verification required by Indian telecom regulations before a number can go live.
- Verify Aadhaar via DigiLocker — the applicant consents on the Indian
government's DigiLocker service; poll the job until it reaches
kyc_verified. - Choose the answering agent and activate — we purchase the number, assign it to your workspace, and configure inbound routing so your chosen agent picks up.
The whole flow is driven by a provisioning job: every step returns the job
with a status and a ready-to-render steps checklist. The dashboard walks
you through this same flow if you'd rather not integrate it yourself.
In Node.js the whole flow is available as typed SDK methods under
voice.dids.managed*. In Python, use any HTTP library with your
X-API-Key header. Full request/response schemas are in the
API reference.
1. Browse the catalog
GET /v1/dids/managed/catalog?type=mobile|toll_free|landline
const catalog = await voice.dids.managedCatalog("mobile");
// { data: [{ didId: 48213, didNumber: "+911408620000", monthlyRate: 199, type: "mobile" }] }import os, requests
headers = {"X-API-Key": os.environ["BRANOFY_VOICE_API_KEY"]}
base = "https://api.branofy.cloud/v1"
catalog = requests.get(
f"{base}/dids/managed/catalog",
params={"type": "mobile"},
headers=headers,
).json()2. Select a number
POST /v1/dids/managed/select reserves the number and creates the
provisioning job. Keep the returned job id — every later step uses it.
const job = await voice.dids.managedSelect({
didId: 48213,
didType: "mobile",
});job = requests.post(
f"{base}/dids/managed/select",
json={"didId": 48213, "didType": "mobile"},
headers=headers,
).json()
job_id = job["id"]3. Submit KYC
POST /v1/dids/managed/:jobId/kyc. Indian telecom regulations require KYC
(Know Your Customer) verification before a business number can take calls.
Verify as an individual or a business:
| Field | Type | Required | Description |
|---|---|---|---|
accountType | string | Yes | individual or business. |
fullName | string | Yes | Legal name of the applicant. |
email | string | Yes | Contact email. |
phone | string | Yes | Contact phone number. |
billingAddress | string | Yes | Full billing address. |
panNumber | string | Yes | PAN card number. |
panHolderName | string | Yes | Name exactly as printed on the PAN card. |
businessName | string | Business only | Registered business name. |
gstNumber | string | Business only | GST registration number. |
await voice.dids.managedSubmitKyc(job.id, {
accountType: "individual",
fullName: "Priya Sharma",
email: "priya@acme.in",
phone: "+919876543210",
billingAddress: "221B MG Road, Bengaluru, KA 560001",
panNumber: "ABCDE1234F",
panHolderName: "Priya Sharma",
});requests.post(
f"{base}/dids/managed/{job_id}/kyc",
json={
"accountType": "individual",
"fullName": "Priya Sharma",
"email": "priya@acme.in",
"phone": "+919876543210",
"billingAddress": "221B MG Road, Bengaluru, KA 560001",
"panNumber": "ABCDE1234F",
"panHolderName": "Priya Sharma",
},
headers=headers,
).json()4. Verify Aadhaar via DigiLocker
POST /v1/dids/managed/:jobId/kyc/aadhaar/init returns an
aadhaarRedirectUrl. Send the applicant there to complete verification on
DigiLocker, then poll the job — KYC state refreshes automatically on each
poll, so the status advances to kyc_verified on its own.
const withRedirect = await voice.dids.managedInitAadhaar(job.id);
// Send the applicant to withRedirect.aadhaarRedirectUrl
// Poll until KYC is verified
const current = await voice.dids.managedJob(job.id);with_redirect = requests.post(
f"{base}/dids/managed/{job_id}/kyc/aadhaar/init",
json={},
headers=headers,
).json()
# Send the applicant to with_redirect["aadhaarRedirectUrl"]
# Poll until KYC is verified
current = requests.get(
f"{base}/dids/managed/{job_id}", headers=headers,
).json()5. Choose the answering agent and activate
Once the job is kyc_verified, POST /v1/dids/managed/:jobId/finalize with
the agent that should answer inbound calls. We purchase the number, assign it
to your workspace, and configure inbound routing — the job finishes at
active with the provisioned number in job.did.
const done = await voice.dids.managedFinalize(job.id, {
agentId: "agt_8skd92ja",
});
console.log(done.status); // "active"
console.log(done.did?.didNumber); // "+911408620000"done = requests.post(
f"{base}/dids/managed/{job_id}/finalize",
json={"agentId": "agt_8skd92ja"},
headers=headers,
).json()
print(done["status"]) # "active"Job statuses
| Status | Meaning |
|---|---|
number_locked | Number reserved — submit KYC next. |
kyc_pending | KYC details received, awaiting verification. |
kyc_aadhaar_pending | Waiting for the applicant to finish DigiLocker. |
kyc_verified | KYC approved — call finalize. |
purchased → mapped → routed → webhook_configured | Intermediate finalize stages. |
active | Number is live and taking inbound calls. |
Every job response also carries a steps checklist (Number reserved,
KYC verified, Number purchased & assigned, Inbound routing configured,
Status webhook configured, Ready for inbound calls) with per-step
completed / current / pending states, plus a lastError string if a
stage failed.