Skip to content

Phone numbers

Buy, connect and route phone numbers. Several of these spend money immediately.

GET /telephony/overview/{organisationId}

One call that returns your provider connections, your active phone numbers (with inbound and outbound agents), and, depending on the key’s other scopes, your wallet balance and call rates. Wallet fields are null unless the key also has wallet:read, and rates are null unless it also has billing:read.

Scope: numbers:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/telephony/overview/{organisationId}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"featureEnabled": true,
"dodoEnabled": true,
"paid": true,
"wallet": {
"balance": 42.5,
"currency": "USD",
"hasPaid": true
},
"rates": {
"baseRatePerMinute": 0.05,
"countryProviderRates": {
"IN": {
"plivo": 0.04
}
}
},
"integrations": [
{
"id": "cmf3k2j9x0004abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"provider": "plivo",
"isActive": true,
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"config": {
"label": "Plivo Account",
"connected_at": "2026-09-20T10:15:00.000Z",
"plivo_app_id": "12345678901234567",
"plivo_auth_id": "configured",
"plivo_auth_token": "configured"
}
}
],
"numbers": [
{
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "14155550123",
"friendlyName": "+14155550123",
"status": "ACTIVE",
"routingStatus": "ASSIGNED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": "cmf3k2j9x0003abcd1234efgh",
"agent": {
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
},
"assignedAgents": [
{
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
}
],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_purchase",
"type": "local",
"region": "California"
},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"outboundAgents": [
{
"id": "cmf3k2j9x0006abcd1234efgh",
"name": "Payment reminder"
}
]
}
]
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
429 Rate limited

GET /telephony/numbers/{organisationId}

Lists your organisation’s active phone numbers, newest first, with the agent that answers each one (inbound) and the agents that dial out from it (outbound caller ID). No pagination.

Scope: numbers:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/telephony/numbers/{organisationId}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": [
{
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "14155550123",
"friendlyName": "+14155550123",
"status": "ACTIVE",
"routingStatus": "ASSIGNED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": "cmf3k2j9x0003abcd1234efgh",
"agent": {
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
},
"assignedAgents": [
{
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
}
],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_purchase",
"type": "local",
"region": "California"
},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"outboundAgents": [
{
"id": "cmf3k2j9x0006abcd1234efgh",
"name": "Payment reminder"
}
]
}
]
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
429 Rate limited

POST /telephony/twilio/connect

Connects your own Twilio account and imports every voice number on it (all pages). No wallet funding is needed. Credentials are stored encrypted and never returned. On a reconnect of the same account you may omit accountSid and authToken and the stored ones are reused; a different accountSid needs its own authToken. A reconnect reconciles the account: numbers still there are updated, numbers gone from it are deactivated (only when the whole account was read). Switching to a different Twilio account takes Foan off the previous account’s numbers and retires them, and is refused with 409 while any agent still answers on or dials out from one of them. amd is kept as it was when omitted on a reconnect. With an API key, the numbers:write scope is the permission (only an owner or admin can create keys); a dashboard session must belong to an owner or admin.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
accountSid string no Your Twilio Account SID. Optional when this organisation already has this account connected.
authToken string no Your Twilio Auth Token. Optional when reconnecting the account already connected (same or omitted accountSid).
label string no Display name for the connection. Defaults to the existing label, then “Twilio Account”.
amd boolean no Answering machine detection for calls through this account. When omitted, a reconnect of the same account keeps the current setting; a new account defaults to false.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/twilio/connect" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","accountSid":"YOUR_TWILIO_ACCOUNT_SID","authToken":"YOUR_TWILIO_AUTH_TOKEN","label":"Main Twilio","amd":false}'

Response 201

{
"success": true,
"data": {
"integration": {
"id": "cmf3k2j9x0004abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"provider": "twilio",
"isActive": true,
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"config": {
"label": "Main Twilio",
"amd": false,
"connected_at": "2026-09-24T08:30:00.000Z",
"account_sid": "configured",
"auth_token": "configured"
}
},
"reusedStoredCredentials": false,
"imported": 3,
"updated": 0,
"deactivated": 0
}
}

Errors

Code When
400 Validation failed, Account SID or Auth Token missing (or the stored ones are incomplete), or Twilio rejected the credentials.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, a dashboard user who is not an owner or admin, or Twilio self-serve is not enabled on the platform.
404 Organisation not found.
409 Switching accounts while agents still use numbers on the previous Twilio account, or when another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

POST /telephony/twilio/search

Searches available voice numbers on your connected Twilio account. Tries Local, then Mobile, then TollFree, and returns the first type that has results (up to 20). Read-only at Twilio, but needs a funded wallet and a connected Twilio account.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
country string no Two-letter country code. Defaults to US.
areaCode string no Area code filter.
contains string no Digits or pattern the number should contain.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/twilio/search" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","country":"US","areaCode":"415"}'

Response 200

{
"success": true,
"data": {
"country": "US",
"type": "Local",
"numbers": [
{
"phoneNumber": "+14155550123",
"friendlyName": "(415) 555-0123",
"locality": "San Francisco",
"region": "CA",
"capabilities": {
"voice": true,
"SMS": true,
"MMS": false
}
}
]
}
}

Errors

Code When
400 Validation failed, or the stored Twilio credentials are incomplete.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded.
403 Missing scope, foreign organisation, or Twilio self-serve is not enabled.
404 No Twilio account is connected (“twilio integration not found”).
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/twilio/purchase

Buys the given number immediately on your own connected Twilio account (Twilio bills that account) and points its voice webhook at Foan. There is no confirm step or dry run. Your Foan wallet must be funded above the minimum balance (402 otherwise), but this call does not debit the wallet.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
phoneNumber string yes E.164 number from a Twilio search result.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/twilio/purchase" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","phoneNumber":"+14155550123"}'

Response 201

{
"success": true,
"data": {
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "twilio",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "PNXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"friendlyName": "(415) 555-0123",
"status": "ACTIVE",
"routingStatus": "PURCHASED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": null,
"agent": null,
"assignedAgents": [],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "twilio_purchase",
"capabilities": {
"voice": true
}
},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z"
}
}

Errors

Code When
400 Validation failed, the stored Twilio credentials are incomplete, or Twilio rejected the purchase or credentials.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded or below the minimum available balance (default 1).
403 Missing scope, foreign organisation, or Twilio self-serve is not enabled.
404 No Twilio account is connected.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/exotel/connect

Connects your own Exotel account and imports its incoming numbers. Needs a funded wallet (402 otherwise). Credentials are stored encrypted and never returned. Reconnecting replaces them.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
accountSid string yes Your Exotel account SID.
apiKey string yes Your Exotel API key.
apiToken string yes Your Exotel API token.
appId string yes The Exotel app (flow) ID calls should use.
subdomain string: api.exotel.com, api.in.exotel.com no Exotel API host: api.exotel.com (default) or api.in.exotel.com.
label string no Display name. Defaults to “Exotel Account”.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/exotel/connect" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","accountSid":"YOUR_EXOTEL_ACCOUNT_SID","apiKey":"YOUR_EXOTEL_API_KEY","apiToken":"YOUR_EXOTEL_API_TOKEN","appId":"YOUR_EXOTEL_APP_ID","subdomain":"api.in.exotel.com","label":"Exotel India"}'

Response 201

{
"success": true,
"data": {
"integration": {
"id": "cmf3k2j9x0004abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"provider": "exotel",
"isActive": true,
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"config": {
"label": "Exotel India",
"exotel_app_id": "YOUR_EXOTEL_APP_ID",
"exotel_subdomain": "api.in.exotel.com",
"connected_at": "2026-09-24T08:30:00.000Z",
"exotel_sid": "configured",
"exotel_key": "configured",
"exotel_token": "configured"
}
},
"synced": {
"remoteCount": 2,
"synced": 2,
"skipped": 0
}
}
}

Errors

Code When
400 Validation failed, subdomain not allowed, or Exotel rejected the credentials.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded.
403 Missing scope, foreign organisation, or self-serve telephony is not enabled.
409 Another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited by Foan (about 20/min per key plus a stricter sensitive-route limit), or Exotel’s own rate limit was reached.
502 Could not reach Exotel or it returned an invalid response.
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

POST /telephony/exotel/sync

Re-reads the incoming numbers on your connected Exotel account and creates or updates them in Foan. Needs a funded wallet and an existing Exotel connection.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/exotel/sync" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"synced": {
"remoteCount": 4,
"synced": 3,
"skipped": 1
}
}
}

Errors

Code When
400 Validation failed, stored Exotel credentials incomplete, or Exotel rejected them.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded.
403 Missing scope, foreign organisation, or self-serve telephony is not enabled.
404 No Exotel account is connected.
409 Another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited by Foan, or Exotel’s own rate limit was reached.
502 Could not reach Exotel.
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

POST /telephony/plivo/connect

Connects your own Plivo account and imports every number on it (or only the one you name in phoneNumber). Foan creates or updates a Plivo application on your account and points each imported number at it, so their calls start routing to Foan. A number that already answers through another Plivo application is imported with routingStatus NEEDS_SETUP and left alone at Plivo until you assign it to an agent; a number you name in phoneNumber is moved across straight away. Numbers on Plivo subaccounts are never imported. No wallet funding is needed and Foan bills nothing for these numbers (Plivo bills you). On a reconnect of the same account you may omit authId and authToken and the stored ones are reused. A whole-account connect also deactivates numbers that are no longer on the account. Switching to a different Plivo account takes Foan off the previous account’s numbers and retires them, and is refused with 409 while any agent still uses one. Foan’s own main Plivo account cannot be connected. Credentials are stored encrypted and never returned. With an API key, the numbers:write scope is the permission (only an owner or admin can create keys); a dashboard session must belong to an owner or admin.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
authId string no Your Plivo Auth ID. Optional when this organisation already has this account connected.
authToken string no Your Plivo Auth Token. Optional when reconnecting the account already connected (same or omitted authId).
phoneNumber string no Optional. Import only this number (E.164) from the account; 404 if the account does not have it. Omit to import the whole account.
label string no Display name, also written as the alias of numbers Foan points at its application. Defaults to the existing label, then “Plivo Account”.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/connect" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","authId":"YOUR_AUTH_ID","authToken":"YOUR_AUTH_TOKEN","label":"Support lines"}'

Response 201

{
"success": true,
"data": {
"integration": {
"id": "cmf3k2j9x0004abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"provider": "plivo",
"isActive": true,
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-10-05T09:30:00.000Z",
"config": {
"label": "Support lines",
"connected_at": "2026-10-05T09:30:00.000Z",
"plivo_app_id": "12345678901234567",
"plivo_auth_id": "configured",
"plivo_auth_token": "configured"
}
},
"reusedStoredCredentials": false,
"imported": 2,
"updated": 0,
"needsSetup": 1,
"deactivated": 0,
"numbers": [
{
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "14155550123",
"friendlyName": "Support lines",
"status": "ACTIVE",
"routingStatus": "IMPORTED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": null,
"agent": null,
"assignedAgents": [],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_sync",
"region": "California",
"numberType": "local",
"voiceEnabled": true
},
"createdAt": "2026-10-05T09:30:00.000Z",
"updatedAt": "2026-10-05T09:30:00.000Z",
"outboundAgents": []
},
{
"id": "cmf3k2j9x0007abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550188",
"countryCode": "US",
"providerNumberId": "14155550188",
"friendlyName": "+14155550188",
"status": "ACTIVE",
"routingStatus": "NEEDS_SETUP",
"capabilities": {
"voice": true,
"sms": true
},
"agentId": null,
"agent": null,
"assignedAgents": [],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_sync",
"region": "California",
"numberType": "local",
"voiceEnabled": true
},
"createdAt": "2026-10-05T09:30:00.000Z",
"updatedAt": "2026-10-05T09:30:00.000Z",
"outboundAgents": []
}
],
"number": {
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "14155550123",
"friendlyName": "Support lines",
"status": "ACTIVE",
"routingStatus": "IMPORTED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": null,
"agent": null,
"assignedAgents": [],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_sync",
"region": "California",
"numberType": "local",
"voiceEnabled": true
},
"createdAt": "2026-10-05T09:30:00.000Z",
"updatedAt": "2026-10-05T09:30:00.000Z",
"outboundAgents": []
}
}
}

Errors

Code When
400 Validation failed, Auth ID or Auth Token missing (or the stored ones are incomplete), or Plivo rejected the credentials.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, a dashboard user who is not an owner or admin, or Plivo self-serve is not enabled.
404 The number named in phoneNumber is not on this Plivo account, or the organisation was not found.
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead. Also returned for Foan’s own main Plivo account, for switching accounts while agents still use numbers on the previous one, and when another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

POST /telephony/plivo/search

Searches up to 20 available voice numbers on your connected Plivo account, with Plivo’s monthly rental and whether the market needs a compliance (KYC) approval before purchase. Read-only at Plivo. Needs a funded wallet (402 otherwise) and a connected Plivo account of your own. Plivo bills the rental to your Plivo account; Foan does not charge it.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
country string no Two-letter country code. Defaults to US.
type string: local, mobile, tollfree, national, fixed no Number type: local, mobile, tollfree, national or fixed. Defaults to local in US and CA, fixed elsewhere. Unknown values are ignored.
pattern string no Digits the number should contain; letters, digits, * and ? are kept, anything else is stripped.
region string no Region filter.
city string no City filter.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/search" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","country":"US","type":"local","pattern":"415"}'

Response 200

{
"success": true,
"data": {
"country": "US",
"type": "local",
"complianceRequired": false,
"numbers": [
{
"phoneNumber": "+14155550123",
"providerNumber": "14155550123",
"locality": "San Francisco",
"region": "California",
"type": "local",
"monthlyRentalRate": "0.50000",
"providerMonthlyRentalRate": "0.50000",
"providerMonthlyRentalCurrency": "USD",
"customerMonthlyRentalRate": "0.5000",
"customerMonthlyRentalCurrency": "USD",
"customerMonthlyRentalFxRate": 1,
"setupRate": "0.00000",
"voiceRate": "0.00850",
"restriction": null,
"restrictionText": null,
"complianceRequired": false,
"capabilities": {
"voice": true,
"sms": true,
"mms": false
}
}
]
}
}

Errors

Code When
400 Validation failed, stored Plivo credentials incomplete, or Plivo rejected them.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded.
403 Missing scope, foreign organisation, or Plivo self-serve is not enabled.
404 No Plivo account is connected.
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/plivo/purchase

Buys the number immediately on your own connected Plivo account and points it at Foan. There is no confirm step or dry run. Plivo bills the number and its rental to your Plivo account; Foan records no rental for it and this call does not debit your wallet, but your wallet must be funded above the minimum balance (402 otherwise). The number type and rental are read from Plivo’s inventory, never from the request. Regulated markets (India, restricted numbers, or where Plivo requires it) need an approved compliance application covering that country and number type, checked live with Plivo before buying.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
phoneNumber string yes Number from a Plivo search result (E.164 or digits).
country string no Two-letter country code. Must match the number’s own country or the purchase is refused (503).
type string no Accepted but ignored: the regulatory number type is read from Plivo’s inventory, never from the request.
region string no Stored on the number for display.
city string no Stored on the number for display.
setupRate string no Plivo setup rate from the search result, stored for reference.
restriction string no restriction from the search result. Any value marks the number as regulated.
restrictionText string no restrictionText from the search result.
complianceApplicationId string no Optional Plivo compliance application ID to buy against. Must already be linked to your organisation.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/purchase" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","phoneNumber":"+14155550123","country":"US","region":"California","city":"San Francisco","setupRate":"0.00000","restriction":null,"restrictionText":null}'

Response 201

{
"success": true,
"data": {
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "14155550123",
"friendlyName": "+14155550123",
"status": "ACTIVE",
"routingStatus": "PURCHASED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": null,
"agent": null,
"assignedAgents": [],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_purchase",
"type": "local",
"region": "California",
"city": "San Francisco"
},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z"
}
}

Errors

Code When
400 Validation failed, stored Plivo credentials incomplete, the compliance application is not linked to your organisation, or Plivo rejected the request.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded or below the minimum available balance (default 1).
403 Missing scope, foreign organisation, or Plivo self-serve is not enabled.
404 No Plivo account is connected.
409 No approved compliance application covers this number’s country and type, or the one given was refused or covers another market (the message says what to do next). Also returned when this organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
503 The country or regulatory type could not be confirmed (including a country that does not match the number), or Plivo could not confirm the compliance requirement or approval just now. Nothing was bought; retry later.

POST /telephony/plivo/compliance/requirements

Returns the document types and fields Plivo needs before it will sell a number of the given country, number type and end-user type. Read-only at Plivo. Needs a connected Plivo account; no wallet check.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
country string yes Two-letter country code.
numberType string no local, mobile, tollfree, national or fixed. Defaults to local (fixed becomes local in India).
userType string no End-user type, business (default) or individual.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/compliance/requirements" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","country":"IN","numberType":"local","userType":"business"}'

Response 200

{
"success": true,
"data": {
"requirement_id": "5f8e1a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b",
"country_iso": "IN",
"number_type": "local",
"user_type": "business",
"document_types": [
{
"document_type_id": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
"name": "Business registration: Certificate of Incorporation",
"description": "Accepted documents: Certificate of Incorporation, GST Certificate. The first option is used by default.",
"proof_required": true,
"required_fields": [
{
"field_name": "business_name",
"friendly_name": "Business name",
"required": true
},
{
"field_name": "unique_identification_number",
"friendly_name": "Registration number",
"required": true
}
]
}
]
}
}

Errors

Code When
400 Validation failed, stored Plivo credentials incomplete, or Plivo rejected them.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 No Plivo account connected, or Plivo returned no requirements for that combination.
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/plivo/compliance/applications/list

Lists the Plivo compliance applications linked to your organisation, read live from Plivo, with optional filters. Applications Plivo could not return right now are listed in unavailable rather than silently dropped, so treat the list as incomplete while verificationUnavailable is true.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
country string no Two-letter country filter.
numberType string no Number type filter.
userType string no End-user type filter (business or individual).
status string no Exact Plivo status filter.
alias string no Substring match on the alias.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/compliance/applications/list" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","country":"IN"}'

Response 200

{
"success": true,
"data": {
"compliances": [
{
"compliance_id": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809",
"alias": "Priya Sharma Foods IN compliance [org:cmf3k2j9x0001abcd1234efgh]",
"status": "accepted",
"country_iso": "IN",
"number_type": "local",
"user_type": "business",
"rejection_reason": null,
"created_at": "2026-09-10T09:00:00Z",
"documents": [
{
"document_id": "d0c1e2f3-a4b5-4c6d-8e7f-9a0b1c2d3e4f",
"document_type_id": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
"status": "accepted"
}
]
}
],
"unavailable": [],
"verificationUnavailable": false,
"meta": {
"limit": 20,
"next": null,
"offset": 0,
"previous": null,
"total_count": 1
}
}
}

Errors

Code When
400 Validation failed, or stored Plivo credentials incomplete.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 No Plivo account is connected.
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/plivo/compliance/applications

Creates and submits a Plivo compliance (KYC) application in one call: creates the end user, uploads each document, creates the application and submits it for Plivo’s review, then links it to your organisation. Sent as multipart/form-data. Nothing is charged by Foan, but it creates real records on your Plivo account and cannot be undone through this API.

Scope: numbers:write

Body (multipart/form-data)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
data string yes A JSON string (not an object) describing the application. Keys: country_iso (required, two letters), number_type (default local), user_type (business default, or individual), alias (optional label, must not contain “[org:”), end_user {name, last_name, business_name, address_line1, address_line2, city, postal_code, country, registration_number, email}, documents (required, at least one) [{document_type_id, data_fields {field_name: value}}]. End-user address, name, registration number and email are used as defaults for each document’s fields.
documents[0].file file no File for documents[0]. Add documents[1].file, documents[2].file and so on for the other documents. Optional per document; up to 10 files, 10 MB each.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/compliance/applications" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 201

{
"success": true,
"data": {
"compliance": {
"compliance_id": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809",
"alias": "Priya Sharma Foods IN compliance [org:cmf3k2j9x0001abcd1234efgh]",
"status": "submitted",
"country_iso": "IN",
"number_type": "local",
"user_type": "business",
"rejection_reason": null,
"created_at": "2026-09-10T09:00:00Z",
"documents": [
{
"document_id": "d0c1e2f3-a4b5-4c6d-8e7f-9a0b1c2d3e4f",
"document_type_id": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
"status": "accepted"
}
]
}
}
}

Errors

Code When
400 Validation failed, data is not valid JSON, country_iso or documents missing, alias contains “[org:”, no Plivo requirement found for the combination, or stored Plivo credentials incomplete.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 No Plivo account is connected.
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
502 Plivo did not return an ID for the end user, a document or the application.

POST /telephony/plivo/compliance/applications/{complianceId}

Asks Plivo for the current status of one of your compliance applications, records the answer, and returns it with the normalised KYC state and next action. The application must be linked to your organisation (403 otherwise).

Scope: numbers:write

Parameters

Name In Type Required Description
complianceId path string yes Plivo compliance application ID.

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/compliance/applications/{complianceId}" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"compliance": {
"compliance_id": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809",
"alias": "Priya Sharma Foods IN compliance [org:cmf3k2j9x0001abcd1234efgh]",
"status": "accepted",
"country_iso": "IN",
"number_type": "local",
"user_type": "business",
"rejection_reason": null,
"created_at": "2026-09-10T09:00:00Z",
"documents": [
{
"document_id": "d0c1e2f3-a4b5-4c6d-8e7f-9a0b1c2d3e4f",
"document_type_id": "7a6b5c4d-3e2f-4a1b-9c8d-7e6f5a4b3c2d",
"status": "accepted"
}
]
},
"kyc": {
"state": "approved",
"providerStatus": "accepted",
"submittedAt": "2026-09-10T09:00:00.000Z",
"decidedAt": "2026-09-12T14:20:00.000Z",
"rejectionReason": null,
"lastCheckedAt": "2026-09-24T08:30:00.000Z",
"nextAction": {
"code": "buy_number",
"message": "KYC is approved. You can buy a number."
}
}
}
}

Errors

Code When
400 Validation failed, or stored Plivo credentials incomplete.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, or the application is not linked to your organisation.
404 No Plivo account connected, or Plivo says the application does not exist.
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/plivo/compliance/link

Attaches a Plivo compliance application to one of your Plivo numbers (at Plivo and in Foan) and adds it to your organisation’s approved list. Identify the number by numberId or phoneNumber. The application must be one Foan created for your organisation or already linked to it; applications belonging to another organisation are refused.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
complianceApplicationId string yes Plivo compliance application ID.
numberId string no Foan phone number ID. Takes precedence over phoneNumber.
phoneNumber string no E.164 number, exactly as stored in Foan, used when numberId is not given.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/compliance/link" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","complianceApplicationId":"a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809","numberId":"cmf3k2j9x0002abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"linked": true,
"numberId": "cmf3k2j9x0002abcd1234efgh",
"complianceApplicationId": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809"
}
}

Errors

Code When
400 Validation failed, stored Plivo credentials incomplete, or Plivo rejected the update.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, or the application belongs to or was not created for this organisation.
404 No Plivo account connected, number not found in your organisation, or Plivo has no such application.
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
502 Could not verify the application with Plivo.

GET /telephony/kyc/{organisationId}

Where your number KYC stands, one entry per provider application (compliance applications for your connected number provider, and the India numbering wizard), each with its state, whether it currently allows a purchase, and a plain next-action message. Answers from Foan’s records without calling any provider; use POST /telephony/kyc/refresh to re-check with providers.

Scope: numbers:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/telephony/kyc/{organisationId}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"applications": [
{
"provider": "plivo",
"providerApplicationId": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809",
"state": "approved",
"providerStatus": "accepted",
"statusSource": "provider_api",
"lastStep": null,
"submittedAt": "2026-09-10T09:00:00.000Z",
"decidedAt": "2026-09-12T14:20:00.000Z",
"rejectionReason": null,
"lastCheckedAt": "2026-09-24T08:30:00.000Z",
"countryIso": "IN",
"numberType": "local",
"stale": false,
"verificationUnavailable": false,
"statusUnrecognised": false,
"purchaseAllowed": true,
"purchaseBlockedReason": null,
"nextAction": {
"code": "buy_number",
"message": "KYC is approved. You can buy a number."
}
}
]
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 Organisation not found.
429 Rate limited

POST /telephony/kyc/refresh

Asks each provider for the latest status of your KYC applications, records the answers, and returns the refreshed view (same shape as GET /telephony/kyc/{organisationId}). A provider that cannot be reached is reported per application as verificationUnavailable, never as a rejection.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/kyc/refresh" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"applications": [
{
"provider": "plivo",
"providerApplicationId": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809",
"state": "approved",
"providerStatus": "accepted",
"statusSource": "provider_api",
"lastStep": null,
"submittedAt": "2026-09-10T09:00:00.000Z",
"decidedAt": "2026-09-12T14:20:00.000Z",
"rejectionReason": null,
"lastCheckedAt": "2026-09-24T08:30:00.000Z",
"countryIso": "IN",
"numberType": "local",
"stale": false,
"verificationUnavailable": false,
"statusUnrecognised": false,
"purchaseAllowed": true,
"purchaseBlockedReason": null,
"nextAction": {
"code": "buy_number",
"message": "KYC is approved. You can buy a number."
}
}
]
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 Organisation not found.
429 Rate limited: about 20 requests per minute per API key, plus a stricter shared limit of about 30 per minute on this sensitive route (body: {success: false, message}).

POST /telephony/numbers/{id}/assign

Sets which agent answers inbound calls on this number, or unassigns it when agentId is null or omitted. An agent answers on only one number, so any other number that agent had is unassigned. The agent’s calling number and provider are also set to this number. For Twilio numbers, the number’s webhook at Twilio is repointed to the agent. For a Plivo number imported with routingStatus NEEDS_SETUP (it answered through another Plivo application), assigning an agent points the number at Foan’s application on your Plivo account first. For a number on a connected Plivo, Twilio or Exotel account the change runs under that account’s lock, so it can be refused with 409 while a connect, sync or disconnect of the account is running.

Scope: numbers:write

Parameters

Name In Type Required Description
id path string yes Foan phone number ID (from the numbers list).

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
agentId string no Agent to assign. null or omitted unassigns the number.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/numbers/{id}/assign" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","agentId":"cmf3k2j9x0003abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "14155550123",
"friendlyName": "+14155550123",
"status": "ACTIVE",
"routingStatus": "ASSIGNED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": "cmf3k2j9x0003abcd1234efgh",
"agent": {
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
},
"assignedAgents": [
{
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
}
],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_purchase",
"type": "local",
"region": "California"
},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z"
}
}

Errors

Code When
400 Validation failed, or the carrier (Twilio or Plivo) rejected the routing update or the stored credentials.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 Number not found in your organisation, or agent not found.
409 The Plivo account must be reconnected before this number can be assigned (“Reconnect the Plivo account before assigning this number”), or another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

POST /telephony/numbers/{id}/outbound-agents

Replaces the full list of agents that dial out using this number as caller ID. Many agents can share one outbound number. Agents currently using this number but left out of agentIds lose their caller ID (their calling number is cleared), so send the complete list. An empty list clears everyone. For a number on a connected Plivo, Twilio or Exotel account the change runs under that account’s lock.

Scope: numbers:write

Parameters

Name In Type Required Description
id path string yes Foan phone number ID.

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
agentIds array of string yes Every agent that should dial out from this number. Duplicates are ignored.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/numbers/{id}/outbound-agents" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","agentIds":["cmf3k2j9x0003abcd1234efgh","cmf3k2j9x0006abcd1234efgh"]}'

Response 200

{
"success": true,
"data": {
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "plivo",
"phoneNumber": "+14155550123",
"countryCode": "US",
"providerNumberId": "14155550123",
"friendlyName": "+14155550123",
"status": "ACTIVE",
"routingStatus": "ASSIGNED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": "cmf3k2j9x0003abcd1234efgh",
"agent": {
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
},
"assignedAgents": [
{
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
}
],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {
"source": "plivo_purchase",
"type": "local",
"region": "California"
},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"outboundAgents": [
{
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
},
{
"id": "cmf3k2j9x0006abcd1234efgh",
"name": "Payment reminder"
}
]
}
}

Errors

Code When
400 Validation failed (agentIds must be an array of strings).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 Number not found in your organisation, or one or more agents not found.
409 Another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

POST /telephony/numbers/replace

Moves every agent that dials out from one number onto another number in one step (for example to rotate away from a number flagged as spam). Only outbound caller ID moves; inbound assignment is unchanged. Both numbers must be in your organisation and the target must be active.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
fromNumberId string yes Number the agents currently dial out from.
toNumberId string yes Number they should dial out from instead. Must be active.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/numbers/replace" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","fromNumberId":"cmf3k2j9x0002abcd1234efgh","toNumberId":"cmf3k2j9x0005abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"movedAgentCount": 2,
"movedAgentIds": [
"cmf3k2j9x0003abcd1234efgh",
"cmf3k2j9x0006abcd1234efgh"
],
"from": {
"id": "cmf3k2j9x0002abcd1234efgh",
"phoneNumber": "+918041234567"
},
"to": {
"id": "cmf3k2j9x0005abcd1234efgh",
"phoneNumber": "+918041234568"
}
}
}

Errors

Code When
400 Validation failed, or fromNumberId equals toNumberId.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 Either number not found in your organisation (or the target is inactive).
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/voicelink/client

Creates your organisation’s profile with Foan’s India numbering partner (VoiceLink), the first step before India KYC and buying Indian numbers. Uses your organisation’s name, the API key owner’s email and the organisation’s mobile. Nothing is charged. Safe to repeat: if a profile exists it is returned unchanged.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/voicelink/client" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh"}'

Response 201

{
"success": true,
"data": {
"id": "cmf3k2j9x0004abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"provider": "voicelink",
"isActive": true,
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"config": {
"kyc_status": "not_started",
"vl_username": "configured",
"vl_password": "configured"
}
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, or India number provisioning is not enabled.
404 Organisation not found.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
502 The partner did not return a client ID.

GET /telephony/voicelink/status/{organisationId}

Asks Foan’s India numbering partner (VoiceLink) for your India KYC status right now, records the answer, and returns your India connection, the partner’s verdict reduced to state, wording and rejection reason, and your full KYC view.

Scope: numbers:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/telephony/voicelink/status/{organisationId}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"integration": {
"id": "cmf3k2j9x0004abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"provider": "voicelink",
"isActive": true,
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z",
"config": {
"kyc_status": "in_progress",
"kyc_step": "pan",
"last_kyc_step": "pan",
"vl_username": "configured",
"vl_password": "configured"
}
},
"remoteStatus": {
"state": "in_progress",
"providerStatus": "pending",
"rejectionReason": null
},
"kyc": {
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"applications": [
{
"provider": "voicelink",
"providerApplicationId": "4821",
"state": "in_progress",
"providerStatus": "pending",
"statusSource": "provider_api",
"lastStep": "pan",
"submittedAt": null,
"decidedAt": null,
"rejectionReason": null,
"lastCheckedAt": "2026-09-24T08:30:00.000Z",
"countryIso": null,
"numberType": null,
"stale": false,
"verificationUnavailable": false,
"statusUnrecognised": false,
"purchaseAllowed": false,
"purchaseBlockedReason": "kyc_not_approved",
"nextAction": {
"code": "continue_kyc",
"message": "Finish the remaining KYC steps."
}
}
]
}
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 No India profile exists yet (create one with POST /telephony/voicelink/client).
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).

POST /telephony/voicelink/kyc/{step}

Submits one step of the India number KYC wizard to Foan’s India numbering partner (VoiceLink), in order: register, pan, aadhaar, gst (business accounts only), final. The register step records the customer’s legal acceptance of the partner’s terms, so send it only after the customer has agreed. The aadhaar step returns aadhaarVerificationUrl, a DigiLocker link the customer must open in a browser before gst or final. Submits immediately; there is no confirm flag.

Scope: numbers:write

Parameters

Name In Type Required Description
step path string: register, pan, aadhaar, gst, final yes Which wizard step to submit.

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
payload object no Step fields, passed to the partner as-is. register: account_type (individual or business), full_name, email, phone, billing_address, term_and_condition, business_name (businesses). pan: pan_holder_name, pan_number. aadhaar: optional redirect_url. gst: gst_number (15-character GSTIN). final: nothing. Defaults to {}.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/voicelink/kyc/{step}" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","payload":{"pan_holder_name":"Priya Sharma","pan_number":"YOUR_PAN_NUMBER"}}'

Response 200

{
"success": true,
"data": {
"provider": {
"state": null,
"providerStatus": null,
"rejectionReason": null
},
"kyc": {
"state": "in_progress",
"lastStep": "pan",
"nextAction": {
"code": "continue_kyc",
"message": "Finish the remaining KYC steps."
}
}
}
}

Errors

Code When
400 Validation failed (payload must be an object), invalid step, no India profile yet, or the partner rejected the submitted details.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, or India number provisioning is not enabled.
404 No India connection exists.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
502 The partner rejected Foan’s reseller credentials.

GET /telephony/voicelink/dids/{organisationId}

Lists Indian numbers available to buy from Foan’s India numbering partner (VoiceLink), with each number’s monthly price. Paginated. Read-only.

Scope: numbers:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
countryCode query string no Dialling code. country_code is accepted as an alias.
country_code query string no Alias of countryCode.
type query integer no Partner’s number type code.
number query string no Digits to search for.
months query integer no Rental term the prices are quoted for.
page query integer no
perPage query integer no per_page is accepted as an alias.
per_page query integer no Alias of perPage.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/telephony/voicelink/dids/{organisationId}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"dids": [
{
"id": 90211,
"did_number": "918041234567",
"country_code": "91",
"type": 2,
"months": 1,
"city": "Bengaluru",
"state": "Karnataka",
"rate_per_month": 499,
"currency": "INR"
}
]
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, or India number provisioning is not enabled.
404 Organisation not found.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
502 The partner rejected Foan’s reseller credentials.

POST /telephony/voicelink/purchase

Buys an Indian number immediately from Foan’s India numbering partner (VoiceLink), maps it to your India profile and routes its calls to Foan. There is no confirm step or dry run. Needs India KYC approved (checked live with the partner) and a wallet funded above the minimum balance. Buying with an API key never tops up the partner float: if the float is low you get 402 and an owner or admin must complete one purchase from the dashboard.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
didId integer yes The number’s id from the India numbers list.
didNumber string yes The number itself from the list, for example 918041234567.
months integer no Rental term in months. Defaults to 1.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/voicelink/purchase" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","didId":90211,"didNumber":"918041234567","months":1}'

Response 201

{
"success": true,
"data": {
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "voicelink",
"phoneNumber": "+918041234567",
"countryCode": "IN",
"providerNumberId": "90211",
"friendlyName": "918041234567",
"status": "ACTIVE",
"routingStatus": "READY",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": null,
"agent": null,
"assignedAgents": [],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z"
}
}

Errors

Code When
400 Validation failed, or no India profile exists yet.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded or below the minimum balance, or the India float is too low and cannot be topped up with an API key.
403 Missing scope, foreign organisation, or India number provisioning is not enabled.
404 No India connection exists.
409 India KYC is not approved; the message says what to do next.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
502 The partner did not return an order or bot ID, or rejected Foan’s reseller credentials.
503 KYC could not be confirmed with the partner just now; nothing was bought.

POST /telephony/voicelink/numbers/{id}/renew

Renews the rental on one of your Indian numbers with Foan’s India numbering partner (VoiceLink), immediately and with no confirm step. Needs a wallet funded above the minimum balance. The renewal is paid from Foan’s reseller account with the partner, not debited from your wallet by this call.

Scope: numbers:write

Parameters

Name In Type Required Description
id path string yes Foan phone number ID of an active India number.

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/voicelink/numbers/{id}/renew" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"number": {
"id": "cmf3k2j9x0002abcd1234efgh",
"organisationId": "cmf3k2j9x0001abcd1234efgh",
"integrationId": "cmf3k2j9x0004abcd1234efgh",
"provider": "voicelink",
"phoneNumber": "+918041234567",
"countryCode": "IN",
"providerNumberId": "90211",
"friendlyName": "918041234567",
"status": "ACTIVE",
"routingStatus": "ASSIGNED",
"capabilities": {
"voice": true,
"sms": false
},
"agentId": "cmf3k2j9x0003abcd1234efgh",
"agent": {
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
},
"assignedAgents": [
{
"id": "cmf3k2j9x0003abcd1234efgh",
"name": "Order confirmation"
}
],
"customerRatePerMin": null,
"monthlyCostUsd": 0,
"metadata": {},
"createdAt": "2026-09-20T10:15:00.000Z",
"updatedAt": "2026-09-24T08:30:00.000Z"
},
"renewal": {
"renewedAt": "2026-09-24T08:30:00.000Z",
"purchaseId": "77120"
}
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Wallet not funded or below the minimum balance.
403 Missing scope, foreign organisation, or India number provisioning is not enabled.
404 India number not found in your organisation, or the partner has no active renewal record for it.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
502 The partner rejected Foan’s reseller credentials.

POST /telephony/plivo/sync

Re-reads every number on your connected Plivo account and reconciles Foan with it: new numbers are imported (for example ones you bought in the Plivo console), existing ones refreshed, and numbers no longer on the account are deactivated. Foan makes sure its application exists on your account and points imported numbers at it; a number that answers through another Plivo application is left alone with routingStatus NEEDS_SETUP. Numbers on Plivo subaccounts are never imported. Nothing is bought and no wallet funding is needed. One connect, sync or disconnect per carrier account runs at a time. With an API key, the numbers:write scope is the permission (only an owner or admin can create keys); a dashboard session must belong to an owner or admin.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/plivo/sync" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"remoteCount": 5,
"imported": 1,
"updated": 4,
"needsSetup": 1,
"skippedOtherProvider": 0,
"deactivated": 0,
"syncedAt": "2026-10-05T09:30:00.000Z"
}
}

Errors

Code When
400 Validation failed, the stored Plivo credentials are incomplete, or Plivo rejected them.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, a dashboard user who is not an owner or admin, or Plivo self-serve is not enabled.
404 No Plivo account is connected (“plivo integration not found”).
409 This organisation gets its Plivo numbers from Foan (Numbers from Foan), so it has no Plivo account of its own to use here. Use the /telephony/managed routes instead. Also returned when another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited: about 20 requests per minute per API key, plus a stricter shared limit of about 30 per minute on this sensitive route (body: {success: false, message}).
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

POST /telephony/twilio/sync

Re-reads every incoming number on your connected Twilio account (all pages) and reconciles Foan with it: new numbers are imported, existing ones refreshed, and numbers no longer on the account are deactivated (only when the whole account was read). Nothing is changed at Twilio; a number’s voice webhook is set when you assign it to an agent. Nothing is bought and no wallet funding is needed. One connect, sync or disconnect per carrier account runs at a time. With an API key, the numbers:write scope is the permission (only an owner or admin can create keys); a dashboard session must belong to an owner or admin.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/twilio/sync" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"remoteCount": 3,
"imported": 1,
"updated": 2,
"needsSetup": 0,
"skippedOtherProvider": 0,
"deactivated": 0,
"syncedAt": "2026-10-05T09:30:00.000Z"
}
}

Errors

Code When
400 Validation failed, the stored Twilio credentials are incomplete, or Twilio rejected them.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, a dashboard user who is not an owner or admin, or Twilio self-serve is not enabled.
404 No Twilio account is connected (“twilio integration not found”).
409 Another connect, sync or disconnect of this carrier account is still running (“Another change to this carrier account is still running. Try again in a moment.”), or this change ran too long and was stopped. Retry shortly.
429 Rate limited: about 20 requests per minute per API key, plus a stricter shared limit of about 30 per minute on this sensitive route (body: {success: false, message}).
503 Foan could not take the lock it uses to serialise changes to one carrier account. Nothing was changed; retry shortly.

GET /telephony/managed/{organisationId}

Numbers from Foan: for an organisation billed in India with no carrier account of its own, Foan rents Indian numbers on its own Plivo account, under a compliance application and subaccount of the organisation’s own. Returns whether this is open to your organisation and how it buys numbers, the state of its business verification, its Foan phone account, prices, and the numbers it rents. Read-only and free; it may ask Plivo for a pending verification decision. Prices come from the rate card in minor units (paise for INR): today a number is Rs 500 a month (numberMonthlyMinor 50000) plus a phone line charge of Rs 0.50 a minute in 30-second blocks on its calls. A Muncho venue whose calls are paid from the Muncho wallet pays its numbers from that wallet instead, at Muncho’s prices.

Scope: numbers:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/telephony/managed/{organisationId}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"available": true,
"route": "subaccount",
"planRequired": false,
"outsideIndia": false,
"country": "IN",
"useCases": [
{
"id": "TRANSACTIONAL",
"offered": true,
"label": "Service and transactional",
"example": "Confirming a booking, a delivery slot or an appointment; answering customers who call in."
},
{
"id": "PROMOTIONAL",
"offered": false,
"label": "Promotional",
"example": "Offering a discount or a new product to people who did not ask to be called."
},
{
"id": "FINANCIAL",
"offered": false,
"label": "Financial services (licensed entities)",
"example": "Calls from a bank, lender or insurer about their regulated products."
}
],
"onboarding": {
"state": "accepted",
"useCase": "TRANSACTIONAL",
"businessName": "Example Foods Private Limited",
"registrationKind": "COI",
"taxKind": "PAN",
"details": null,
"rejectionReason": null,
"submittedAt": "2026-10-01T06:00:00.000Z",
"checkedAt": "2026-10-02T04:10:00.000Z",
"canBuy": true,
"documents": [
{
"role": "REGISTRATION",
"kind": "COI",
"fileName": "incorporation.pdf",
"sizeBytes": 182344,
"uploadedAt": "2026-10-01T06:00:00.000Z"
},
{
"role": "TAX",
"kind": "PAN",
"fileName": "pan.pdf",
"sizeBytes": 96210,
"uploadedAt": "2026-10-01T06:00:00.000Z"
}
]
},
"account": "ready",
"prices": {
"currency": "INR",
"numberMonthlyMinor": 50000,
"numberMonthly": "Rs 500",
"phoneLinePerMinuteMinor": 50,
"phoneLinePerMinute": "Rs 0.50",
"phoneLineBlockSeconds": 30
},
"graceDays": 7,
"numbers": [
{
"id": "cmf3k2j9x0009abcd1234efgh",
"phoneNumber": "+918041234567",
"country": "IN",
"status": "active",
"routingStatus": "PURCHASED",
"agentId": null,
"monthlyPrice": "Rs 500",
"paidThrough": "2026-11-05T09:30:00.000Z",
"releaseOn": null,
"since": "2026-10-05T09:30:00.000Z"
}
]
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 The key lacks the required scope, or organisationId is not the key’s own organisation.
404 Organisation not found.
429 Rate limited

Submit business verification for Numbers from Foan

Section titled “Submit business verification for Numbers from Foan”

POST /telephony/managed/onboarding

Numbers from Foan: for an organisation billed in India with no carrier account of its own, Foan rents Indian numbers on its own Plivo account, under a compliance application and subaccount of the organisation’s own. Files (or, after a rejection, refiles) your business verification with Plivo: a compliance application in your organisation’s name built from your details and two documents, a registration certificate (certificate of incorporation or Udyam) and a PAN or GST certificate. Both documents are required the first time; a refile may replace either and reuses the stored copy of the other. Plivo usually decides within a day; read the decision with Get Numbers from Foan status. After submission Foan also sets up your Foan phone account (retried later if it fails). Nothing is charged. Refused while verification is already submitted or accepted, and when your organisation has its own Plivo account connected. Sent as multipart/form-data. With an API key, the numbers:write scope is the permission (only an owner or admin can create keys); a dashboard session must belong to an owner or admin.

Scope: numbers:write

Body (multipart/form-data)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
data string yes JSON string with the business details, see the example.
registration file no Registration certificate: PDF, JPEG or PNG, at most 5 MB.
tax file no PAN or GST certificate: PDF, JPEG or PNG, at most 5 MB.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/managed/onboarding" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 201

{
"success": true,
"data": {
"available": true,
"route": "subaccount",
"planRequired": false,
"outsideIndia": false,
"country": "IN",
"useCases": [
{
"id": "TRANSACTIONAL",
"offered": true,
"label": "Service and transactional",
"example": "Confirming a booking, a delivery slot or an appointment; answering customers who call in."
},
{
"id": "PROMOTIONAL",
"offered": false,
"label": "Promotional",
"example": "Offering a discount or a new product to people who did not ask to be called."
},
{
"id": "FINANCIAL",
"offered": false,
"label": "Financial services (licensed entities)",
"example": "Calls from a bank, lender or insurer about their regulated products."
}
],
"onboarding": {
"state": "submitted",
"useCase": "TRANSACTIONAL",
"businessName": "Example Foods Private Limited",
"registrationKind": "COI",
"taxKind": "PAN",
"details": {
"businessName": "Example Foods Private Limited",
"registrationKind": "COI",
"registrationNumber": "U12345KA2020PTC123456",
"taxKind": "PAN",
"taxNumber": "ABCDE1234F",
"email": "compliance@example.com",
"addressLine1": "12 Example Road",
"addressLine2": "",
"city": "Bengaluru",
"state": "Karnataka",
"postalCode": "560001"
},
"rejectionReason": null,
"submittedAt": "2026-10-05T09:30:00.000Z",
"checkedAt": "2026-10-05T09:30:00.000Z",
"canBuy": false,
"documents": [
{
"role": "REGISTRATION",
"kind": "COI",
"fileName": "incorporation.pdf",
"sizeBytes": 182344,
"uploadedAt": "2026-10-01T06:00:00.000Z"
},
{
"role": "TAX",
"kind": "PAN",
"fileName": "pan.pdf",
"sizeBytes": 96210,
"uploadedAt": "2026-10-01T06:00:00.000Z"
}
]
},
"account": "ready",
"prices": {
"currency": "INR",
"numberMonthlyMinor": 50000,
"numberMonthly": "Rs 500",
"phoneLinePerMinuteMinor": 50,
"phoneLinePerMinute": "Rs 0.50",
"phoneLineBlockSeconds": 30
},
"graceDays": 7,
"numbers": []
}
}

Errors

Code When
400 Validation failed, data is not a JSON string, a required detail is missing or invalid (“Please add …”), a document is not a real PDF, JPEG or PNG, a document is missing, or Plivo refused the details.
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, a dashboard user who is not an owner or admin, or Numbers from Foan is not open to this organisation yet.
404 Organisation not found.
409 Not possible right now: no Foan plan, not billed in India, own Plivo account connected, use case not offered, verification already submitted or approved, or another submission is in progress. The message says which.
429 Rate limited: about 20 requests per minute per API key, plus a stricter shared limit of about 30 per minute on this sensitive route (body: {success: false, message}).
500 A document over 5 MB, or a file in a field other than registration or tax, is currently rejected with a generic server error.
502 Plivo did not confirm the submission. Retry.
503 Numbers from Foan is not configured, Plivo could not be reached, Plivo’s document requirements no longer match what Foan collects, or a Muncho venue’s billing is moving wallets. Nothing was filed; retry later.

POST /telephony/managed/search

Numbers from Foan: for an organisation billed in India with no carrier account of its own, Foan rents Indian numbers on its own Plivo account, under a compliance application and subaccount of the organisation’s own. Lists up to 20 Indian numbers you may rent, with Foan’s monthly price from the rate card. Only series your use case allows come back (today Bengaluru 080 and Mumbai 022 landlines for service and transactional calls). Searching reserves nothing and charges nothing. Needs a submitted business verification; canBuy says whether it is approved yet. Prices come from the rate card in minor units (paise for INR): today a number is Rs 500 a month (numberMonthlyMinor 50000) plus a phone line charge of Rs 0.50 a minute in 30-second blocks on its calls. A Muncho venue whose calls are paid from the Muncho wallet pays its numbers from that wallet instead, at Muncho’s prices.

Scope: numbers:read

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
pattern string no Digits the number should contain; non-digits are removed.
city string no Keep only numbers in this city (Bengaluru or Mumbai), case-insensitive.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/managed/search" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","pattern":"8041","city":"Bengaluru"}'

Response 200

{
"success": true,
"data": {
"country": "IN",
"canBuy": true,
"prices": {
"currency": "INR",
"numberMonthlyMinor": 50000,
"numberMonthly": "Rs 500",
"phoneLinePerMinuteMinor": 50,
"phoneLinePerMinute": "Rs 0.50",
"phoneLineBlockSeconds": 30
},
"numbers": [
{
"phoneNumber": "+918041234567",
"series": 80,
"city": "Bengaluru",
"type": "local",
"monthlyPrice": "Rs 500",
"monthlyPriceMinor": 50000,
"currency": "INR"
}
]
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, or Numbers from Foan is not open to this organisation yet.
404 Organisation not found.
409 No business verification submitted yet, no Foan plan, or not billed in India.
429 Rate limited: this route allows about 20 requests per minute per API key (body: {success: false, message}).
500 Plivo returned an error for the search.
503 Numbers from Foan is not configured, the Muncho wallet could not be reached, or a Muncho venue’s billing is moving wallets.

POST /telephony/managed/purchase

Numbers from Foan: for an organisation billed in India with no carrier account of its own, Foan rents Indian numbers on its own Plivo account, under a compliance application and subaccount of the organisation’s own. Rents the number immediately and charges its first month to your wallet up front (Foan wallet, or the Muncho wallet for a Muncho venue paying from it). There is no confirm step or dry run. Only the number comes from the request: the price is the rate card’s and the compliance application and subaccount are your organisation’s own. Your verification is re-checked live with Plivo first and must be accepted. Each month is then charged when the paid month runs out; an unpaid month is warned about, given graceDays of grace, then the number is released. If any step after the charge fails, the number is given back and the charge refunded. A number you already rent is returned as it is, with no new charge. Prices come from the rate card in minor units (paise for INR): today a number is Rs 500 a month (numberMonthlyMinor 50000) plus a phone line charge of Rs 0.50 a minute in 30-second blocks on its calls. A Muncho venue whose calls are paid from the Muncho wallet pays its numbers from that wallet instead, at Muncho’s prices. With an API key, the numbers:write scope is the permission (only an owner or admin can create keys); a dashboard session must belong to an owner or admin.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
phoneNumber string yes A number from Search Numbers from Foan (E.164 or digits).

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/managed/purchase" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","phoneNumber":"+918041234567"}'

Response 201

{
"success": true,
"data": {
"id": "cmf3k2j9x0009abcd1234efgh",
"phoneNumber": "+918041234567",
"country": "IN",
"status": "active",
"routingStatus": "PURCHASED",
"agentId": null,
"monthlyPrice": "Rs 500",
"paidThrough": "2026-11-05T09:30:00.000Z",
"releaseOn": null,
"since": "2026-10-05T09:30:00.000Z"
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
402 Your wallet cannot pay the first month (“A number costs Rs 500 a month, paid from your wallet up front. Top up to continue.”), your plan is paused for non-payment, or the Muncho wallet refused. Nothing was charged.
403 Missing scope, foreign organisation, a dashboard user who is not an owner or admin, or Numbers from Foan is not open to this organisation yet.
404 Organisation not found.
409 Not possible: no verification submitted, verification not approved or suspended, a series your use case may not use (140, 160, or outside Bengaluru and Mumbai), the number is already connected or already being bought, the number was just taken (refunded), own Plivo account connected, no Foan plan, or not billed in India. The message says which.
429 Rate limited: about 20 requests per minute per API key, plus a stricter shared limit of about 30 per minute on this sensitive route (body: {success: false, message}).
500 Your Foan phone account needs attention; contact support.
502 The purchase is still finishing (“It will complete, or be refunded, automatically”), or set-up failed and the number was given back and the charge refunded. Check Get Numbers from Foan status before retrying.
503 Your verification could not be confirmed with Plivo just now, Numbers from Foan is not configured, or the Muncho wallet could not be reached or is moving. Nothing was bought.

POST /telephony/managed/release

Gives a number rented from Foan (Numbers from Foan) back to the carrier, permanently. Its monthly charges stop; the rest of the month already paid is not refunded. Refused with 409 while an agent answers on it or dials out from it, unless force is true, in which case those agents lose the number. Numbers on your own carrier account cannot be released here (release them in that carrier’s console). With an API key, the numbers:write scope is the permission (only an owner or admin can create keys); a dashboard session must belong to an owner or admin.

Scope: numbers:write

Body (application/json)

Field Type Required Description
organisationId string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
numberId string yes Foan phone number ID from Get Numbers from Foan status.
force boolean no Release even though agents still use the number; they lose it.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/telephony/managed/release" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"organisationId":"cmf3k2j9x0001abcd1234efgh","numberId":"cmf3k2j9x0009abcd1234efgh"}'

Response 200

{
"success": true,
"data": {
"released": true,
"numberId": "cmf3k2j9x0009abcd1234efgh",
"phoneNumber": "+918041234567",
"freedAgents": 0
}
}

Errors

Code When
400 Validation failed (the error message lists the failing fields).
401 Missing, invalid or revoked API key, or the key owner no longer belongs to the organisation.
403 Missing scope, foreign organisation, or a dashboard user who is not an owner or admin.
404 Not an active number rented from Foan in this organisation.
409 Agents still use this number (“1 agent(s) still use this number …”); move them first or send force: true.
429 Rate limited: about 20 requests per minute per API key, plus a stricter shared limit of about 30 per minute on this sensitive route (body: {success: false, message}).
502 The carrier could not release the number just now. It is still yours; retry shortly.
503 Numbers from Foan is not configured on this server.