Guides

Inbound and numbers

Get a phone number, bring your own, link an agent to answer it, and verify recipient numbers.

A phone number does two jobs: it is the caller ID of outbound calls, and, once linked to an agent, the number people dial to reach that agent.

In the dashboard: Deploy → My Numbers. Verified recipient numbers are under Settings → Verified Numbers. Changing numbers needs the admin role or an API key.

Note: What these endpoints do depends on how the operator runs telephony. In mock mode (the default) search, buy and release are simulated: the numbers are made up and nothing is rented from a carrier. In live mode they call Twilio or Plivo with your provider keys or the platform's.

bash
curl "https://api.sevennadi.si/phone-numbers/search?country=IN&pattern=80" \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef"
json
[
  {"region": "KA", "friendly_name": "+91801234567", "locality": "Bengaluru",
   "phone_number": "+91801234567", "provider": "plivo", "price": 6.0}
]

country is US or IN; anything else is 400 country must be US or IN. pattern filters by digits. provider defaults to twilio for the US and plivo for India.

Buy

bash
curl -X POST https://api.sevennadi.si/phone-numbers/buy \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"country": "IN", "phone_number": "+91801234567"}'

The first month's rental is debited from your wallet as a number_rental ledger entry, and the response describes the new number (id, phone_number, price, telephony_provider, telephony_sid). Errors:

StatusMessage
400country (US or IN) and phone_number are required
400This phone number is already in use
400Insufficient wallet balance to buy this number
400No twilio credentials: add TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN via POST /providers (live mode, no keys)

Rental is charged again each month by the daily billing job.

Import a number you already own

If you already have a number at Exotel, Twilio or Plivo, register it. Nothing is bought or charged.

bash
curl -X POST https://api.sevennadi.si/phone-numbers/import \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+918012345678", "telephony_provider": "exotel", "name": "Collections line"}'

Response, 201:

json
{"id": "9a8b7c6d5e4f40312a1b0c9d8e7f6a5b", "phone_number": "+918012345678", "agent_id": null,
 "telephony_provider": "exotel", "rented": false, "price": "$0.0",
 "created_at": "2026-10-13T10:02:11Z", "updated_at": "2026-10-13T10:02:11Z",
 "humanized_created_at": "just now", "humanized_updated_at": "just now", "renewal_at": "12th Nov, 2026"}

telephony_provider must be exotel, twilio or plivo. A number that is already registered on the platform is refused with This phone number is already registered. Importing does not prove you own the number; the provider decides whether calls from it go through.

List and release

GET /phone-numbers/all lists your numbers with the agent each is linked to. Numbers on a SIP trunk are listed with their trunk instead; see SIP trunks.

DELETE /phone-numbers/{phone_number_id} removes a number. A rented number is also released at the provider in live mode.

json
{"message": "The phone number has been removed from your account", "state": "deleted"}

Answer inbound calls with an agent

bash
curl -X POST https://api.sevennadi.si/inbound/setup \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "3c90c3cc-0d44-4b50-8822-8dd25736052a", "phone_number_id": "9a8b7c6d5e4f40312a1b0c9d8e7f6a5b"}'
json
{"url": "https://api.sevennadi.si/inbound_call?agent_id=3c90c3cc-0d44-4b50-8822-8dd25736052a",
 "phone_number": "+918012345678", "id": "9a8b7c6d5e4f40312a1b0c9d8e7f6a5b"}

url is the webhook the telephony provider must call when the number rings. For a number you imported from Twilio or Plivo, set it as the number's voice webhook in the provider's console yourself. Exotel works differently; see Exotel.

A number linked to another agent is refused with This number is already linked to another agent; set allow_multiple to link it anyway. POST /inbound/unlink with {"phone_number_id": "..."} removes the link.

What happens when someone calls

  1. The provider requests the inbound URL with the dialled and calling numbers.
  2. The platform checks that the number is yours and linked to that agent. If not: 404 No agent is linked to this number.
  3. It creates an execution with call_type: "inbound".
  4. For an agent on the own engine, it answers with instructions to stream the call's audio to the engine. For an agent on the mock engine it runs a simulated call and answers with the execution id.

To accept only known callers, set task_config.disallow_unknown_numbers: true and list them in task_config.whitelist_phone_numbers. Others get 403 Caller not allowed.

Verified recipient numbers

An account can be limited to calling numbers it has proven it controls. This is the account setting restrict_to_verified_numbers, read and changed with GET /user/settings and PATCH /user/settings.

Verify a number with a one-time code:

bash
curl -X POST https://api.sevennadi.si/phone-numbers/verified \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+919876500123"}'

The code is six digits, valid for ten minutes, and sent by SMS. Confirm it:

bash
curl -X POST https://api.sevennadi.si/phone-numbers/verified/confirm \
  -H "Authorization: Bearer vk-0123456789abcdef0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+919876500123", "otp": "123456"}'

Limits: one code per 30 seconds per number, ten requests an hour per account, and five wrong codes before you must request a new one. GET /phone-numbers/verified/all lists numbers with status pending or verified. With the restriction on, POST /call and POST /batches answer 403 for unverified numbers.

With the development message provider, no SMS is sent and the code comes back in the response as mock_otp. See Verified numbers reference.

Limitations

  • Search and buy cover US and IN only.
  • In mock mode a "bought" number cannot receive real calls.
  • A number is not released automatically when the wallet cannot pay its monthly rental.
  • With live telephony the inbound webhook verifies the provider's request signature: X-Twilio-Signature for Twilio, X-Plivo-Signature-V3 with its nonce for Plivo, made with your own auth token (a provider key) or the operator's. An unsigned or wrongly signed request answers 403 Invalid or missing provider signature. In mock mode nothing is signed and nothing is checked. The Plivo check follows Plivo's published scheme and has not yet been tried against a live Plivo request.
  • The signed address is the public one (PUBLIC_BASE_URL plus the path and query). If the operator's PUBLIC_BASE_URL does not match the address configured at the provider, every inbound call is refused.
  • Verification codes by voice call are not available with a real provider (501), and the real SMS adapters have only been tested against local fakes.
  • restrict_to_verified_numbers can be switched off by any admin of the account; it is not a platform-imposed lock.