Skip to content

Agents

Voice and chat agents: list, read, create, update, clone and delete.

POST /voice/agents

Creates a voice or chat agent in the API key’s organisation. The combined length of agentIdentity, agentPersonality, agentTask, pronunciation and languageAccent must stay within the instruction budget (4,000 characters by default, see GET /voice/agent-instruction-budget), otherwise 400. Outbound number: if callingNumber and telephonyProvider are not both sent, the agent gets your organisation’s newest active Plivo number, else the newest active number on another provider (a callingNumber sent without telephonyProvider is replaced by that default when you own any active number). Set builderMode FLOW with a flowDefinition to create a Flow Agent (voice only, organisations with Flow Agents switched on, see GET /voice/organisations/{organisationId}/flow-agents); its resultsConfig is then derived from the flow. A PROMPT agent can set resultsConfig to choose what the Results page tracks. Creating an agent also starts generating its cached greeting audio in the background.

Scope: agents:write

Body (application/json)

Field Type Required Description
name string yes Agent name.
description string no
organisationId string no Optional. If sent it must be the API key’s own organisation; the key’s organisation is always used.
agentType string: VOICE, CHAT no
callbackAgentId string no A VOICE agent in the same organisation that places callbacks for this (chat) agent.
agentIdentity string yes Who the agent is. Counts toward the instruction budget.
agentPersonality string no Tone and style. Counts toward the instruction budget.
agentTask string no What the agent must do on the call. Required unless builderMode is FLOW (a FLOW agent may send it empty and gets a one-line placeholder). Counts toward the instruction budget.
builderMode string: PROMPT, FLOW no PROMPT agents follow their written task. FLOW agents follow a step-by-step call flow (flowDefinition). Only voice agents can be FLOW agents, and only organisations that have Flow Agents switched on may turn an agent into a FLOW agent or change its flow (see GET /voice/organisations/{organisationId}/flow-agents); otherwise 403. Switching modes never loses either side: a PROMPT agent keeps its saved flow switched off, and switching a FLOW agent back to PROMPT needs a real agentTask.
flowDefinition object no The call flow. Required when builderMode is FLOW. It is checked against the tools the agent will have (its functionTools, plus knowledge_search / product_search when customVariables lists knowledge bases / catalogues) and the handover number in handoverData. Sent while the agent is PROMPT it is checked and stored switched off.
pronunciation string no Pronunciation hints. Counts toward the instruction budget.
greetingMessage string no First line the agent speaks. Required for VOICE agents. Supports {{variable}} placeholders filled from customVariables.
closingMessage string no
escalationMessage string no
voicemailMessage string no Message left when a voicemail answers.
language string no BCP-47 language code.
languageAccent string no Spoken language and accent in plain words, for example “Indian English”. Empty string or null clears it. Counts toward the instruction budget.
resultsConfig object no What the Results page tracks for this agent: the outcomes each call can end in and the details to note down. After each call the AI analysis picks one outcome and fills the details. null (or no outcomes and no fields) tracks nothing. For FLOW agents this is derived from the flow on every save and any value you send is ignored.
gender string: MALE, FEMALE, NEUTRAL no
voiceProvider string no Speech engine. Leave it unset; Foan uses its current engine.
voiceId string no Voice name. See GET /voice/voices.
voiceSpeed number no
timezone string no IANA time zone, for example Asia/Kolkata.
sttMode string: GLOBAL, INDIA, HUMANOID, GENERIC no
supportedLanguageGroup string: English, Indian, Global no
languageSelectionMode string: group, language no
supportedLanguage string no A supported language key such as “Hindi”, used when languageSelectionMode is language.
backgroundNoise string no Background audio identifier or URL.
backgroundNoiseVolume number no
customVariables object no Default key/value variables for the agent’s prompts.
functionTools object no Webhook tools the agent can call during a conversation, keyed by tool key. At most 5. Bearer tokens are encrypted at rest and come back encrypted on reads.
contextMemory object no Context memory settings. Known key: custom_instructions (string).
handoverData object no Human handover settings. On update only the keys you send are changed (shallow merge); null clears a key.
webCallEnabled boolean no CHAT agents only: show a web call button in the chat widget.
callingNumber string no Outbound caller number. A local format is resolved to the matching E.164 number your organisation owns.
telephonyProvider string: frejun, twilio, exotel, voicelink, plivo no

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/voice/agents" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Order confirmation","agentIdentity":"You are Nina, a friendly order confirmation assistant for an online store.","agentPersonality":"Warm, polite and brief.","agentTask":"Confirm the order {{order_id}} and the delivery address, then thank the customer.","greetingMessage":"Hi {{name}}, this is Nina calling about your recent order. Is this a good time?","voicemailMessage":"Hi, this is Nina calling about your order. We will try again later.","languageAccent":"Indian English","gender":"FEMALE","voiceId":"Nina","timezone":"Asia/Kolkata","resultsConfig":{"outcomes":[{"key":"confirmed","label":"Confirmed","description":"The customer confirmed the order and address."},{"key":"cancelled","label":"Cancelled"}],"fields":[{"key":"delivery_slot","label":"Delivery slot","type":"choice","choices":["Morning","Evening"]}]}}'

Response 201

{
"success": true,
"data": {
"id": "cmf3k2j9x0001abcd1234efgh",
"name": "Order confirmation",
"description": "Confirms cash-on-delivery orders before dispatch",
"organisationId": "cmf3k2j9x0000orgabcd1234",
"createdById": "cmf3k2j9x0002user5678abcd",
"createdBy": {
"id": "cmf3k2j9x0002user5678abcd",
"name": "Priya Sharma",
"email": "priya@example.com"
},
"agentType": "VOICE",
"callbackAgentId": null,
"agentIdentity": "You are Nina, a friendly order confirmation assistant for an online store.",
"agentPersonality": "Warm, polite and brief.",
"agentTask": "Confirm the order {{order_id}} and the delivery address, then thank the customer.",
"pronunciation": null,
"greetingMessage": "Hi {{name}}, this is Nina calling about your recent order. Is this a good time?",
"closingMessage": "Thank you, have a great day!",
"escalationMessage": null,
"voicemailMessage": "Hi, this is Nina calling about your order. We will try again later.",
"language": "en-US",
"languageAccent": "Indian English",
"gender": "FEMALE",
"voiceId": "Nina",
"voiceSpeed": 1,
"sttMode": null,
"supportedLanguageGroup": null,
"languageSelectionMode": null,
"supportedLanguage": null,
"timezone": "Asia/Kolkata",
"backgroundNoise": null,
"backgroundNoiseVolume": 0.1,
"customVariables": {},
"functionTools": null,
"contextMemory": null,
"handoverData": {
"handover_enabled": false
},
"webCallEnabled": false,
"isActive": true,
"version": 1,
"lastUsed": "2026-09-20T10:15:00.000Z",
"totalCalls": 42,
"createdAt": "2026-08-01T06:30:00.000Z",
"updatedAt": "2026-09-20T10:15:00.000Z",
"builderMode": "PROMPT",
"flowDefinition": null,
"resultsConfig": {
"outcomes": [
{
"key": "confirmed",
"label": "Confirmed",
"description": "The customer confirmed the order and address."
},
{
"key": "cancelled",
"label": "Cancelled"
}
],
"fields": [
{
"key": "delivery_slot",
"label": "Delivery slot",
"type": "choice",
"choices": [
"Morning",
"Evening"
]
}
]
},
"callingNumber": "+918045671234",
"telephonyProvider": "plivo",
"sipConfigurations": []
},
"message": "Voice agent created successfully"
}

Errors

Code When
400 Validation failed (missing name/identity/task/greeting, bad enum, invalid resultsConfig, more than 5 function tools, instruction budget exceeded, invalid callback agent, a CHAT agent given a call flow), or the call flow was rejected (flowErrors lists each problem). Body: {success:false, error}.
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 Missing agents:write scope, organisationId in the body is not the key’s organisation, or builderMode FLOW / a flowDefinition was sent while Flow Agents are not switched on for your organisation.
429 Rate limited.

GET /voice/agents/{id}

Returns one agent. The agent must belong to the API key’s organisation. Deleted agents return 404.

Scope: agents:read

Parameters

Name In Type Required Description
id path string yes Agent ID.
includeTools query string: decrypted no With an API key, decrypted returns functionTools with webhook auth tokens decrypted (built-in server-managed tools removed). Otherwise tokens come back encrypted.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/voice/agents/{id}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"id": "cmf3k2j9x0001abcd1234efgh",
"name": "Order confirmation",
"description": "Confirms cash-on-delivery orders before dispatch",
"organisationId": "cmf3k2j9x0000orgabcd1234",
"createdById": "cmf3k2j9x0002user5678abcd",
"createdBy": {
"id": "cmf3k2j9x0002user5678abcd",
"name": "Priya Sharma",
"email": "priya@example.com"
},
"agentType": "VOICE",
"callbackAgentId": null,
"agentIdentity": "You are Nina, a friendly order confirmation assistant for an online store.",
"agentPersonality": "Warm, polite and brief.",
"agentTask": "Confirm the order {{order_id}} and the delivery address, then thank the customer.",
"pronunciation": null,
"greetingMessage": "Hi {{name}}, this is Nina calling about your recent order. Is this a good time?",
"closingMessage": "Thank you, have a great day!",
"escalationMessage": null,
"voicemailMessage": "Hi, this is Nina calling about your order. We will try again later.",
"language": "en-US",
"languageAccent": "Indian English",
"gender": "FEMALE",
"voiceId": "Nina",
"voiceSpeed": 1,
"sttMode": null,
"supportedLanguageGroup": null,
"languageSelectionMode": null,
"supportedLanguage": null,
"timezone": "Asia/Kolkata",
"backgroundNoise": null,
"backgroundNoiseVolume": 0.1,
"customVariables": {},
"functionTools": null,
"contextMemory": null,
"handoverData": {
"handover_enabled": false
},
"webCallEnabled": false,
"isActive": true,
"version": 1,
"lastUsed": "2026-09-20T10:15:00.000Z",
"totalCalls": 42,
"createdAt": "2026-08-01T06:30:00.000Z",
"updatedAt": "2026-09-20T10:15:00.000Z",
"builderMode": "PROMPT",
"flowDefinition": null,
"resultsConfig": {
"outcomes": [
{
"key": "confirmed",
"label": "Confirmed",
"description": "The customer confirmed the order and address."
},
{
"key": "cancelled",
"label": "Cancelled"
}
],
"fields": [
{
"key": "delivery_slot",
"label": "Delivery slot",
"type": "choice",
"choices": [
"Morning",
"Evening"
]
}
]
},
"callingNumber": "+918045671234",
"telephonyProvider": "plivo",
"sipConfigurations": []
},
"message": "Voice agent retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or the resource belongs to another organisation.
404 Agent not found or deleted.
429 Rate limited

PUT /voice/agents/{id}

Partially updates an agent: only the fields you send change (despite the PUT verb). The agent must belong to the API key’s organisation. The combined length of agentIdentity, agentPersonality, agentTask, pronunciation and languageAccent must stay within the instruction budget (4,000 characters by default, see GET /voice/agent-instruction-budget), otherwise 400. An agent already over the budget can still be saved as long as the edit does not make it longer. Flow Agents: switching builderMode keeps both sides. Switching to FLOW needs a flow (sent or already saved) and keeps your own resultsConfig aside; switching back to PROMPT needs a real agentTask and restores that resultsConfig. On a FLOW agent, any change to flowDefinition, builderMode, functionTools, customVariables or handoverData re-checks the whole flow (400 with flowErrors if it no longer fits), resultsConfig is re-derived from the flow, and a resultsConfig you send is ignored. Turning an agent into a FLOW agent or changing (or deleting) its flow needs Flow Agents switched on for your organisation, otherwise 403. Every update also regenerates the agent’s cached greeting audio in the background.

Scope: agents:write

Parameters

Name In Type Required Description
id path string yes Agent ID.

Body (application/json)

Field Type Required Description
name string no Agent name.
description string no
agentType string: VOICE, CHAT no
callbackAgentId string no A VOICE agent in the same organisation that places callbacks for this (chat) agent.
agentIdentity string no Who the agent is. Counts toward the instruction budget.
agentPersonality string no Tone and style. Counts toward the instruction budget.
agentTask string no What the agent must do on the call. Counts toward the instruction budget. Sent empty to a FLOW agent it keeps the stored task. Needed (non-empty) when switching a FLOW agent back to PROMPT.
builderMode string: PROMPT, FLOW no PROMPT agents follow their written task. FLOW agents follow a step-by-step call flow (flowDefinition). Only voice agents can be FLOW agents, and only organisations that have Flow Agents switched on may turn an agent into a FLOW agent or change its flow (see GET /voice/organisations/{organisationId}/flow-agents); otherwise 403. Switching modes never loses either side: a PROMPT agent keeps its saved flow switched off, and switching a FLOW agent back to PROMPT needs a real agentTask.
flowDefinition object no null deletes the saved flow (allowed only while the agent is PROMPT and Flow Agents are switched on). The call flow. Required when builderMode is FLOW. It is checked against the tools the agent will have (its functionTools, plus knowledge_search / product_search when customVariables lists knowledge bases / catalogues) and the handover number in handoverData. Sent while the agent is PROMPT it is checked and stored switched off.
pronunciation string no Pronunciation hints. Counts toward the instruction budget.
greetingMessage string no First line the agent speaks. Required for VOICE agents. Supports {{variable}} placeholders filled from customVariables.
closingMessage string no
escalationMessage string no
voicemailMessage string no Message left when a voicemail answers.
language string no BCP-47 language code.
languageAccent string no Spoken language and accent in plain words, for example “Indian English”. Empty string or null clears it. Counts toward the instruction budget.
resultsConfig object no What the Results page tracks for this agent: the outcomes each call can end in and the details to note down. After each call the AI analysis picks one outcome and fills the details. null (or no outcomes and no fields) tracks nothing. For FLOW agents this is derived from the flow on every save and any value you send is ignored.
gender string: MALE, FEMALE, NEUTRAL no
voiceProvider string no Speech engine. Leave it unset; Foan uses its current engine.
voiceId string no Voice name. See GET /voice/voices.
voiceSpeed number no
timezone string no IANA time zone, for example Asia/Kolkata.
sttMode string: GLOBAL, INDIA, HUMANOID, GENERIC no
supportedLanguageGroup string: English, Indian, Global no
languageSelectionMode string: group, language no
supportedLanguage string no A supported language key such as “Hindi”, used when languageSelectionMode is language.
backgroundNoise string no Background audio identifier or URL.
backgroundNoiseVolume number no
customVariables object no Default key/value variables for the agent’s prompts.
functionTools object no Webhook tools the agent can call during a conversation, keyed by tool key. At most 5. Bearer tokens are encrypted at rest and come back encrypted on reads.
contextMemory object no Context memory settings. Known key: custom_instructions (string).
handoverData object no Human handover settings. On update only the keys you send are changed (shallow merge); null clears a key.
webCallEnabled boolean no CHAT agents only: show a web call button in the chat widget.
callingNumber string no Outbound caller number. A local format is resolved to the matching E.164 number your organisation owns.
telephonyProvider string: frejun, twilio, exotel, voicelink, plivo no
isActive boolean no false pauses the agent; inactive agents cannot place calls.

Example request

Terminal window
curl -X PUT "https://api.foan.ai/api/v1/voice/agents/{id}" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"agentTask":"Confirm the order {{order_id}}, the delivery address and the preferred delivery slot.","voiceSpeed":1.1,"handoverData":{"handover_enabled":true,"handover_target_number":"+919876543210"}}'

Response 200

{
"success": true,
"data": {
"id": "cmf3k2j9x0001abcd1234efgh",
"name": "Order confirmation",
"description": "Confirms cash-on-delivery orders before dispatch",
"organisationId": "cmf3k2j9x0000orgabcd1234",
"createdById": "cmf3k2j9x0002user5678abcd",
"createdBy": {
"id": "cmf3k2j9x0002user5678abcd",
"name": "Priya Sharma",
"email": "priya@example.com"
},
"agentType": "VOICE",
"callbackAgentId": null,
"agentIdentity": "You are Nina, a friendly order confirmation assistant for an online store.",
"agentPersonality": "Warm, polite and brief.",
"agentTask": "Confirm the order {{order_id}} and the delivery address, then thank the customer.",
"pronunciation": null,
"greetingMessage": "Hi {{name}}, this is Nina calling about your recent order. Is this a good time?",
"closingMessage": "Thank you, have a great day!",
"escalationMessage": null,
"voicemailMessage": "Hi, this is Nina calling about your order. We will try again later.",
"language": "en-US",
"languageAccent": "Indian English",
"gender": "FEMALE",
"voiceId": "Nina",
"voiceSpeed": 1,
"sttMode": null,
"supportedLanguageGroup": null,
"languageSelectionMode": null,
"supportedLanguage": null,
"timezone": "Asia/Kolkata",
"backgroundNoise": null,
"backgroundNoiseVolume": 0.1,
"customVariables": {},
"functionTools": null,
"contextMemory": null,
"handoverData": {
"handover_enabled": false
},
"webCallEnabled": false,
"isActive": true,
"version": 1,
"lastUsed": "2026-09-20T10:15:00.000Z",
"totalCalls": 42,
"createdAt": "2026-08-01T06:30:00.000Z",
"updatedAt": "2026-09-20T10:15:00.000Z",
"builderMode": "PROMPT",
"flowDefinition": null,
"resultsConfig": {
"outcomes": [
{
"key": "confirmed",
"label": "Confirmed",
"description": "The customer confirmed the order and address."
},
{
"key": "cancelled",
"label": "Cancelled"
}
],
"fields": [
{
"key": "delivery_slot",
"label": "Delivery slot",
"type": "choice",
"choices": [
"Morning",
"Evening"
]
}
]
},
"callingNumber": "+918045671234",
"telephonyProvider": "plivo",
"sipConfigurations": []
},
"message": "Voice agent updated successfully"
}

Errors

Code When
400 Validation failed, invalid resultsConfig, more than 5 function tools, instruction budget exceeded, a VOICE agent left without a greeting, invalid callback agent, switching a FLOW agent to PROMPT without a task, a CHAT agent given a call flow, or the call flow was rejected (flowErrors lists each problem).
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:write scope, the resource belongs to another organisation, or the edit turns the agent into a FLOW agent or changes its flow while Flow Agents are not switched on for your organisation.
404 Agent not found or deleted.
429 Rate limited

DELETE /voice/agents/{id}

Soft-deletes an agent in the API key’s organisation. It disappears from lists and can no longer take calls; its past calls remain in call history.

Scope: agents:write

Parameters

Name In Type Required Description
id path string yes Agent ID.

Example request

Terminal window
curl -X DELETE "https://api.foan.ai/api/v1/voice/agents/{id}" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": null,
"message": "Voice agent deleted successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:write scope, or the resource belongs to another organisation.
404 Agent not found or already deleted.
429 Rate limited

GET /voice/organisations/{organisationId}/agents

Lists the organisation’s agents (not deleted), newest first, with page-based pagination.

Scope: agents:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID. Must be the API key’s own organisation, otherwise 403.
page query integer no Page number.
limit query integer no Agents per page.
agentType query string: VOICE, CHAT no Only voice or only chat agents.

Example request

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

Response 200

{
"success": true,
"data": {
"agents": [
{
"id": "cmf3k2j9x0001abcd1234efgh",
"name": "Order confirmation",
"description": "Confirms cash-on-delivery orders before dispatch",
"organisationId": "cmf3k2j9x0000orgabcd1234",
"createdById": "cmf3k2j9x0002user5678abcd",
"createdBy": {
"id": "cmf3k2j9x0002user5678abcd",
"name": "Priya Sharma",
"email": "priya@example.com"
},
"agentType": "VOICE",
"callbackAgentId": null,
"agentIdentity": "You are Nina, a friendly order confirmation assistant for an online store.",
"agentPersonality": "Warm, polite and brief.",
"agentTask": "Confirm the order {{order_id}} and the delivery address, then thank the customer.",
"pronunciation": null,
"greetingMessage": "Hi {{name}}, this is Nina calling about your recent order. Is this a good time?",
"closingMessage": "Thank you, have a great day!",
"escalationMessage": null,
"voicemailMessage": "Hi, this is Nina calling about your order. We will try again later.",
"language": "en-US",
"languageAccent": "Indian English",
"gender": "FEMALE",
"voiceId": "Nina",
"voiceSpeed": 1,
"sttMode": null,
"supportedLanguageGroup": null,
"languageSelectionMode": null,
"supportedLanguage": null,
"timezone": "Asia/Kolkata",
"backgroundNoise": null,
"backgroundNoiseVolume": 0.1,
"customVariables": {},
"functionTools": null,
"contextMemory": null,
"handoverData": {
"handover_enabled": false
},
"webCallEnabled": false,
"isActive": true,
"version": 1,
"lastUsed": "2026-09-20T10:15:00.000Z",
"totalCalls": 42,
"createdAt": "2026-08-01T06:30:00.000Z",
"updatedAt": "2026-09-20T10:15:00.000Z",
"builderMode": "PROMPT",
"flowDefinition": null,
"resultsConfig": {
"outcomes": [
{
"key": "confirmed",
"label": "Confirmed",
"description": "The customer confirmed the order and address."
},
{
"key": "cancelled",
"label": "Cancelled"
}
],
"fields": [
{
"key": "delivery_slot",
"label": "Delivery slot",
"type": "choice",
"choices": [
"Morning",
"Evening"
]
}
]
},
"callingNumber": "+918045671234",
"telephonyProvider": "plivo",
"sipConfigurations": []
}
],
"total": 1,
"totalPages": 1,
"currentPage": 1
},
"message": "Voice agents retrieved successfully"
}

Errors

Code When
400 Invalid page, limit or agentType.
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or the resource belongs to another organisation.
429 Rate limited

GET /voice/organisations/{organisationId}/agents/stats

Counts the organisation’s agents (excluding deleted ones) in total and by type.

Scope: agents: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/voice/organisations/{organisationId}/agents/stats" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"total": 5,
"voice": 4,
"chat": 1
},
"message": "Agent stats retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or the resource belongs to another organisation.
429 Rate limited

PATCH /voice/agents/{id}/voice-settings

Changes only the voice fields of an agent (voice, provider, gender, speed). The agent must belong to the API key’s organisation. Regenerates the cached greeting audio in the background.

Scope: agents:write

Parameters

Name In Type Required Description
id path string yes Agent ID.

Body (application/json)

Field Type Required Description
voiceId string no Voice name from GET /voice/voices.
voiceProvider string no Speech engine. Leave it unset; Foan uses its current engine.
gender string: MALE, FEMALE, NEUTRAL no
voiceSpeed number no

Example request

Terminal window
curl -X PATCH "https://api.foan.ai/api/v1/voice/agents/{id}/voice-settings" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"voiceId":"Nina","gender":"FEMALE","voiceSpeed":1}'

Response 200

{
"success": true,
"data": {
"id": "cmf3k2j9x0001abcd1234efgh",
"name": "Order confirmation",
"description": "Confirms cash-on-delivery orders before dispatch",
"organisationId": "cmf3k2j9x0000orgabcd1234",
"createdById": "cmf3k2j9x0002user5678abcd",
"createdBy": {
"id": "cmf3k2j9x0002user5678abcd",
"name": "Priya Sharma",
"email": "priya@example.com"
},
"agentType": "VOICE",
"callbackAgentId": null,
"agentIdentity": "You are Nina, a friendly order confirmation assistant for an online store.",
"agentPersonality": "Warm, polite and brief.",
"agentTask": "Confirm the order {{order_id}} and the delivery address, then thank the customer.",
"pronunciation": null,
"greetingMessage": "Hi {{name}}, this is Nina calling about your recent order. Is this a good time?",
"closingMessage": "Thank you, have a great day!",
"escalationMessage": null,
"voicemailMessage": "Hi, this is Nina calling about your order. We will try again later.",
"language": "en-US",
"languageAccent": "Indian English",
"gender": "FEMALE",
"voiceId": "Nina",
"voiceSpeed": 1,
"sttMode": null,
"supportedLanguageGroup": null,
"languageSelectionMode": null,
"supportedLanguage": null,
"timezone": "Asia/Kolkata",
"backgroundNoise": null,
"backgroundNoiseVolume": 0.1,
"customVariables": {},
"functionTools": null,
"contextMemory": null,
"handoverData": {
"handover_enabled": false
},
"webCallEnabled": false,
"isActive": true,
"version": 1,
"lastUsed": "2026-09-20T10:15:00.000Z",
"totalCalls": 42,
"createdAt": "2026-08-01T06:30:00.000Z",
"updatedAt": "2026-09-20T10:15:00.000Z",
"builderMode": "PROMPT",
"flowDefinition": null,
"resultsConfig": {
"outcomes": [
{
"key": "confirmed",
"label": "Confirmed",
"description": "The customer confirmed the order and address."
},
{
"key": "cancelled",
"label": "Cancelled"
}
],
"fields": [
{
"key": "delivery_slot",
"label": "Delivery slot",
"type": "choice",
"choices": [
"Morning",
"Evening"
]
}
]
},
"callingNumber": "+918045671234",
"telephonyProvider": "plivo",
"sipConfigurations": []
},
"message": "Voice settings updated successfully"
}

Errors

Code When
400 Invalid voiceProvider, gender or voiceSpeed.
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:write scope, or the resource belongs to another organisation.
404 Agent not found or deleted.
429 Rate limited

POST /voice/agents/{id}/duplicate

Copies an agent (prompts, voice, variables, tools, context memory, Results settings, and for a FLOW agent its call flow and handover number) under a new name in the same organisation. A saved flow a PROMPT agent keeps switched off, or the own Results settings a FLOW agent keeps aside, travel with the copy too. The copy must fit the instruction budget; an over-budget legacy agent must be shortened before it can be duplicated. Copying a FLOW agent needs Flow Agents switched on for your organisation.

Scope: agents:write

Parameters

Name In Type Required Description
id path string yes ID of the agent to copy.

Body (application/json)

Field Type Required Description
name string yes Name of the new agent.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/voice/agents/{id}/duplicate" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Order confirmation (Hindi)"}'

Response 201

{
"success": true,
"data": {
"id": "cmf3k2j9x0003abcd5678wxyz",
"name": "Order confirmation (Hindi)",
"description": "Confirms cash-on-delivery orders before dispatch",
"organisationId": "cmf3k2j9x0000orgabcd1234",
"createdById": "cmf3k2j9x0002user5678abcd",
"createdBy": {
"id": "cmf3k2j9x0002user5678abcd",
"name": "Priya Sharma",
"email": "priya@example.com"
},
"agentType": "VOICE",
"callbackAgentId": null,
"agentIdentity": "You are Nina, a friendly order confirmation assistant for an online store.",
"agentPersonality": "Warm, polite and brief.",
"agentTask": "Confirm the order {{order_id}} and the delivery address, then thank the customer.",
"pronunciation": null,
"greetingMessage": "Hi {{name}}, this is Nina calling about your recent order. Is this a good time?",
"closingMessage": "Thank you, have a great day!",
"escalationMessage": null,
"voicemailMessage": "Hi, this is Nina calling about your order. We will try again later.",
"language": "en-US",
"languageAccent": "Indian English",
"gender": "FEMALE",
"voiceId": "Nina",
"voiceSpeed": 1,
"sttMode": null,
"supportedLanguageGroup": null,
"languageSelectionMode": null,
"supportedLanguage": null,
"timezone": "Asia/Kolkata",
"backgroundNoise": null,
"backgroundNoiseVolume": 0.1,
"customVariables": {},
"functionTools": null,
"contextMemory": null,
"handoverData": {
"handover_enabled": false
},
"webCallEnabled": false,
"isActive": true,
"version": 1,
"lastUsed": "2026-09-20T10:15:00.000Z",
"totalCalls": 0,
"createdAt": "2026-08-01T06:30:00.000Z",
"updatedAt": "2026-09-20T10:15:00.000Z",
"builderMode": "PROMPT",
"flowDefinition": null,
"resultsConfig": {
"outcomes": [
{
"key": "confirmed",
"label": "Confirmed",
"description": "The customer confirmed the order and address."
},
{
"key": "cancelled",
"label": "Cancelled"
}
],
"fields": [
{
"key": "delivery_slot",
"label": "Delivery slot",
"type": "choice",
"choices": [
"Morning",
"Evening"
]
}
]
},
"callingNumber": "+918045671234",
"telephonyProvider": "plivo",
"sipConfigurations": []
},
"message": "Voice agent duplicated successfully"
}

Errors

Code When
400 name missing, the copy exceeds the instruction budget, or the copied call flow no longer passes its checks (flowErrors).
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:write scope, the resource belongs to another organisation, or the agent is a FLOW agent and Flow Agents are not switched on for your organisation.
404 Agent not found or deleted.
429 Rate limited

GET /voice/languages

Returns the fixed list of BCP-47 language codes the agent language field accepts, with English and native names.

Scope: agents:read

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/voice/languages" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": [
{
"code": "en-US",
"name": "English (US)",
"nativeName": "English"
},
{
"code": "hi-IN",
"name": "Hindi (India)",
"nativeName": "हिन्दी"
},
{
"code": "ta-IN",
"name": "Tamil (India)",
"nativeName": "தமிழ்"
}
],
"message": "Languages retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or the resource belongs to another organisation.
429 Rate limited

GET /voice/stt-modes

Returns the fixed list of values accepted in the agent sttMode field.

Scope: agents:read

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/voice/stt-modes" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": [
{
"id": "GLOBAL",
"name": "Global 1.4"
},
{
"id": "INDIA",
"name": "India 1.2"
},
{
"id": "HUMANOID",
"name": "Humanoid 1.1"
},
{
"id": "GENERIC",
"name": "Generic 2.1"
}
],
"message": "STT modes retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or the resource belongs to another organisation.
429 Rate limited

GET /voice/agent-instruction-budget

Returns the character budget enforced on an agent’s combined instructions: the warning threshold, the hard limit, and the fields that count toward it.

Scope: agents:read

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/voice/agent-instruction-budget" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": {
"warnChars": 3000,
"maxChars": 4000,
"fields": [
{
"key": "agentIdentity",
"label": "Identity"
},
{
"key": "agentPersonality",
"label": "Personality"
},
{
"key": "agentTask",
"label": "Task"
},
{
"key": "pronunciation",
"label": "Pronunciation"
},
{
"key": "languageAccent",
"label": "Language and accent"
}
]
},
"message": "Agent instruction budget retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or the resource belongs to another organisation.
429 Rate limited

GET /voice/voices

Returns the voice library you can assign to agents (the same list for every organisation), default voice first, then by name.

Scope: agents:read

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/voice/voices" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": [
{
"id": "cmf3k2j9x0004voice123abcd",
"name": "Nina",
"gender": "FEMALE",
"voiceId": "Nina",
"voiceSpeed": 1,
"accent": "Indian English",
"voiceSampleUrl": "https://cdn.example.com/voices/ruhi.mp3",
"isDefault": true,
"createdAt": "2026-06-01T00:00:00.000Z",
"updatedAt": "2026-06-01T00:00:00.000Z"
}
],
"message": "Voices retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or the resource belongs to another organisation.
429 Rate limited
500 Unexpected server error.

GET /voice/organisations/{organisationId}/flow-agents

Says whether your organisation may use Flow Agents (agents that follow a step-by-step call flow, builderMode FLOW). Flow Agents are being rolled out organisation by organisation; while this is false, creating a FLOW agent, switching an agent to FLOW or changing a saved flow answers 403. Agents that are already FLOW keep working and can still be edited or switched back to PROMPT. Read only, no side effects.

Scope: agents:read

Parameters

Name In Type Required Description
organisationId path string yes Your organisation ID (the API key’s organisation).

Example request

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

Response 200

{
"success": true,
"data": {
"enabled": true
},
"message": "Flow Agents access retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope, or organisationId is not the key’s organisation.
429 Rate limited

GET /voice/flow-templates

Returns the ready-made call flows (take a booking, restaurant receptionist, order confirmation, payment reminder, answer questions then hand over, event invite, and a blank one). Each comes with a matching greeting, identity, personality, escalation and voicemail text, so it can be saved as a FLOW agent straight away (copy the fields into POST /voice/agents with builderMode FLOW). Pass the agent’s tool names in tools to get flows that use them, for example a booking tool or knowledge_search. Every returned flow is already valid. Read only, no side effects.

Scope: agents:read

Parameters

Name In Type Required Description
tools query string no Comma-separated tool names the agent has (its function tool names, plus knowledge_search when it has a knowledge base and product_search when it has a catalogue). Up to 50 are used. Templates fall back to noting the request for your team when no matching tool is given.

Example request

Terminal window
curl -X GET "https://api.foan.ai/api/v1/voice/flow-templates" \
-H "Authorization: Bearer $FOAN_API_KEY"

Response 200

{
"success": true,
"data": [
{
"id": "blank",
"name": "Start from scratch",
"description": "One question and a goodbye. Build the rest yourself.",
"greeting": "Hello, thanks for calling.",
"agentIdentity": "You answer calls for the business and help callers with what they need.",
"agentPersonality": "Warm, calm and polite. Speaks in short, clear sentences, listens without interrupting, and never rushes the caller.",
"escalationMessage": "Let me put you through to someone from the team who can help.",
"voicemailMessage": "Hello, sorry we missed you. Please call us back when you can. Thank you.",
"flowDefinition": {
"version": "foan-flow-v1",
"entryNodeId": "start",
"outcomes": [
{
"key": "done",
"label": "Done"
}
],
"nodes": [
{
"id": "start",
"kind": "ask",
"name": "Ask what they need",
"position": {
"x": 0,
"y": 0
},
"text": "What can I help you with today?",
"collect": [
{
"key": "request",
"label": "What they wanted",
"type": "text",
"required": true
}
],
"maxRetries": 2,
"next": "end"
},
{
"id": "end",
"kind": "end",
"name": "End call",
"position": {
"x": 0,
"y": 260
},
"text": "Thanks, goodbye!",
"outcome": "done"
}
]
}
}
],
"message": "Flow templates retrieved successfully"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope.
429 Rate limited

POST /voice/flow-definitions/validate

Runs the same checks a save runs on a call flow, without saving anything, and lists every problem with the step it is on. Errors block a save; warnings do not (for example a Handover step with no number yet, or a call result no step uses). Always answers 200, even for an invalid or missing flow: read data.valid. Send toolNames to also check that every Tool step uses a tool the agent has; send transferNumber to check the number Handover steps transfer to. Does not check whether your organisation may use Flow Agents.

Scope: agents:read

Body (application/json)

Field Type Required Description
flowDefinition object yes A call flow in the foan-flow-v1 format: a list of steps (nodes) the agent walks through, and the call results (outcomes) its End call and Handover steps record. Up to 60 steps, 12 call results, 20 noted-down details and 8 “At any point” rules. Easiest start: take one from GET /voice/flow-templates and edit it, and check it with POST /voice/flow-definitions/validate before saving.
toolNames object no Tool names the agent will have (array, or a comma-separated string; up to 50 used). Omit to skip the tool check. On save the agent’s own function tools, knowledge_search and product_search are used.
transferNumber string no The number Handover steps transfer to (the agent’s handoverData.handover_target_number). Omit to skip the check. Empty or null gives a warning; a value that is not 8 to 15 digits (spaces and a leading + allowed) is an error.

Example request

Terminal window
curl -X POST "https://api.foan.ai/api/v1/voice/flow-definitions/validate" \
-H "Authorization: Bearer $FOAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"flowDefinition":{"version":"foan-flow-v1","entryNodeId":"start","outcomes":[{"key":"done","label":"Done"}],"nodes":[{"id":"start","kind":"ask","name":"Ask what they need","text":"What can I help you with today?","collect":[{"key":"request","label":"What they wanted","type":"text"}],"next":"end"},{"id":"end","kind":"end","name":"End call","text":"Thanks, goodbye!","outcome":"done"}]},"toolNames":["knowledge_search"],"transferNumber":"+919876543210"}'

Response 200

{
"success": true,
"data": {
"valid": false,
"errors": [
{
"code": "ask_text",
"message": "Step \"Ask what they need\" has no question to ask yet.",
"nodeId": "start",
"name": "Ask what they need"
}
],
"warnings": [
{
"code": "handover_number",
"message": "Step \"Handover\" needs a phone number to transfer the call to.",
"nodeId": "handover",
"name": "Handover"
}
]
},
"message": "Flow checked"
}

Errors

Code When
401 Missing, invalid or revoked API key, or the key’s owner is deactivated or no longer in the organisation.
403 The key lacks the agents:read scope.
429 Rate limited