API reference
Assistants
An assistant is one agent: its instructions, model, voice, tools and channels. Every call and chat runs on an assistant, and every update creates a new version.
- POST
/api/assistantsCreate an assistant - GET
/api/assistantsList assistants - GET
/api/assistants/{id}Get an assistant - PATCH
/api/assistants/{id}Update an assistant - DELETE
/api/assistants/{id}Delete an assistant - POST
/api/assistant-avatarsUpload an assistant avatar - POST
/api/assistants/{id}/chat-test-conversationStart a test chat conversation - GET
/api/assistants/{id}/draftGet the assistant's draft - PUT
/api/assistants/{id}/draftSave the assistant's draft - DELETE
/api/assistants/{id}/draftDiscard the assistant's draft - POST
/api/assistants/{id}/draft/rebaseUpdate the draft from live - POST
/api/assistants/{id}/publishPublish the draft - GET
/api/assistants/{id}/versionsList the assistant's config history - GET
/api/assistants/{id}/versions/{version}Get one version of the assistant's config - POST
/api/assistants/{id}/versions/{version}/restoreRestore a version
Create an assistant
POST/api/assistants
Creates an assistant at version 1. config needs agent.instructions and session.llm, session.stt and session.tts, each with a provider and model from the registry; everything else has a default. An org-wide key must name project_id. Validation checks the shape, not that the provider account works: place a test call or chat to be sure.
Secret API key, not read-only. How it works
Request body
project_idstringRequired for an org-wide key; ignored (must match) for a project-scoped key.
namestringrequirednot emptyconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition7 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
falserequestobjectwrite-only, never returnedServer-side HTTP execution spec, never returned on reads. A write that omits it keeps the stored spec for the same tool name; removing or renaming the tool drops it.
4 attributes
urlstringrequiredurimethodstringOne of
GETPOSTPUTPATCHDELETEheadersobjecttimeout_msinteger1 to 120000
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition7 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
falserequestobjectwrite-only, never returnedServer-side HTTP execution spec, never returned on reads. A write that omits it keeps the stored spec for the same tool name; removing or renaming the tool drops it.
4 attributes
urlstringrequiredurimethodstringOne of
GETPOSTPUTPATCHDELETEheadersobjecttimeout_msinteger1 to 120000
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
Returns
201 OK
Response attributes
dataAssistantrequired10 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequirednamestringrequiredconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
versionintegerrequireddraft_revisionintegerThe revision a draft save names as expected_draft_revision; 0 before the first draft.
draftobject | nullWhether a draft exists, without its config (GET /assistants/{id}/draft has it).
3 attributes
revisionintegerbase_versionintegerupdated_atstringISO 8601 timestamp
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X POST "https://api.myleadsfactory.tech/api/assistants" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Front desk",
"project_id": "proj_2f9c41d0a8b34e6f9d1c7a5b3e8f0a12",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel. Be brief and friendly."
},
"session": {
"llm": {
"provider": "openai",
"model": "gpt-4o-mini"
},
"stt": {
"provider": "deepgram",
"model": "nova-3"
},
"tts": {
"provider": "elevenlabs",
"model": "eleven_flash_v2_5"
}
},
"channels": {
"web_chat": {
"enabled": true,
"allowed_origins": [
"https://www.acmetravel.com"
]
}
}
}
}'{
"data": {
"id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"name": "Front desk",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"version": 1,
"draft_revision": 1,
"draft": {
"revision": 1,
"base_version": 1,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
}List assistants
GET/api/assistants
Every assistant in scope with its full current configuration. Secrets in the config come back as <key>_set flags.
Secret API key. How it works
Query parameters
project_idstringOnly this project's assistants.
Returns
200 OK
Response attributes
dataarray of Assistantrequired10 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequirednamestringrequiredconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
versionintegerrequireddraft_revisionintegerThe revision a draft save names as expected_draft_revision; 0 before the first draft.
draftobject | nullWhether a draft exists, without its config (GET /assistants/{id}/draft has it).
3 attributes
revisionintegerbase_versionintegerupdated_atstringISO 8601 timestamp
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/assistants" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": [
{
"id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"name": "Front desk",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{}
]
},
"session": null,
"variables": [
{
"key": {},
"label": {},
"description": {},
"default": {}
}
],
"knowledge": {
"key": {
"chat": {},
"voice": {},
"priority": {}
}
}
},
"version": 1,
"draft_revision": 1,
"draft": {
"revision": 1,
"base_version": 1,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
]
}Get an assistant
GET/api/assistants/{id}
One assistant with its current configuration and version.
Secret API key. How it works
Path parameters
idstringrequiredAssistant id,
asst_....
Returns
200 OK
Response attributes
dataAssistantrequired10 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequirednamestringrequiredconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
versionintegerrequireddraft_revisionintegerThe revision a draft save names as expected_draft_revision; 0 before the first draft.
draftobject | nullWhether a draft exists, without its config (GET /assistants/{id}/draft has it).
3 attributes
revisionintegerbase_versionintegerupdated_atstringISO 8601 timestamp
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 404 Not found, or outside what the key can see
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"name": "Front desk",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"version": 1,
"draft_revision": 1,
"draft": {
"revision": 1,
"base_version": 1,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
}Update an assistant
PATCH/api/assistants/{id}
Send name, config or both. A config replaces the whole stored configuration (it is not merged), except that omitted secrets and tool request specs are kept: read the assistant, change what you need and send the full config back. Each update bumps version.
Secret API key, not read-only. How it works
Path parameters
idstringrequiredAssistant id,
asst_....
Request body
namestringnot emptyconfigAssistantConfigThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition7 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
falserequestobjectwrite-only, never returnedServer-side HTTP execution spec, never returned on reads. A write that omits it keeps the stored spec for the same tool name; removing or renaming the tool drops it.
4 attributes
urlstringrequiredurimethodstringOne of
GETPOSTPUTPATCHDELETEheadersobjecttimeout_msinteger1 to 120000
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition7 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
falserequestobjectwrite-only, never returnedServer-side HTTP execution spec, never returned on reads. A write that omits it keeps the stored spec for the same tool name; removing or renaming the tool drops it.
4 attributes
urlstringrequiredurimethodstringOne of
GETPOSTPUTPATCHDELETEheadersobjecttimeout_msinteger1 to 120000
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
expected_versionintegermin 1The version the caller read. A save over a newer version is refused with 409 version_conflict and the current_version.
Returns
200 OK
Response attributes
dataAssistantrequired10 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequirednamestringrequiredconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
versionintegerrequireddraft_revisionintegerThe revision a draft save names as expected_draft_revision; 0 before the first draft.
draftobject | nullWhether a draft exists, without its config (GET /assistants/{id}/draft has it).
3 attributes
revisionintegerbase_versionintegerupdated_atstringISO 8601 timestamp
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409 Conflict
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X PATCH "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Front desk (UK)"
}'{
"data": {
"id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"name": "Front desk",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"version": 1,
"draft_revision": 1,
"draft": {
"revision": 1,
"base_version": 1,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
}Delete an assistant
DELETE/api/assistants/{id}
Deletes the assistant. Its past calls, conversations and leads stay readable.
Secret API key, not read-only. How it works
Path parameters
idstringrequiredAssistant id,
asst_....
Returns
200 OK
Response attributes
dataDeleteResultrequired2 attributes
idstringrequireddeletedbooleanrequired
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X DELETE "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"id": "id_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"deleted": true
}
}Upload an assistant avatar
POST/api/assistant-avatars
Stores a PNG, JPEG or WebP (at most 512 KB and 4096 pixels a side) as a public org asset and returns its URL, for channels.web_chat.appearance.avatar_url. The same picture always gets the same URL.
Secret API key, not read-only. How it works
Request body
content_typestringrequiredOne of
image/pngimage/jpegimage/webpbase64stringrequiredThe file's bytes, base64-encoded.
Returns
201 OK
Response attributes
dataAssistantAvatarrequired1 attribute
urlstringrequireduri
- 400
invalid_requestfor a malformed body, oravatar_empty,avatar_too_large,avatar_type_mismatch(the bytes are not the declared image type) oravatar_dimensions, inerror. - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address). - 503
asset_storage_not_configured: this deployment has no storage for uploaded images.
curl -X POST "https://api.myleadsfactory.tech/api/assistant-avatars" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content_type": "image/png",
"base64": "string"
}'{
"data": {
"url": "https://example.com/hook"
}
}Start a test chat conversation
POST/api/assistants/{id}/chat-test-conversation
Starts a one-hour conversation with an assistant whose web chat is on, without a publishable key or an origin check, for trying a prompt from your own tooling. Use the returned token with the public chat routes. Test conversations carry metadata.test and are left out of lists and analytics unless asked for.
Secret API key, not read-only. How it works
Path parameters
idstringrequiredAssistant id,
asst_....
Returns
201 Test conversation created
Response attributes
dataobjectrequired2 attributes
conversation_idstringrequiredtokenstringrequired
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409
web_chat_disabled: turn on the assistant'schannels.web_chat.enabledfirst - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X POST "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/chat-test-conversation" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"conversation_id": "conv_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"token": "string"
}
}Get the assistant's draft
GET/api/assistants/{id}/draft
The config being worked on in test mode, or null when there is none. Test chats (test keys and the console's test chat) run it; visitors never do until it is published.
Secret API key. How it works
Path parameters
idstringrequired
Returns
200 OK
Response attributes
dataAssistantDraft | nullrequired8 attributes
assistant_idstringconfigAssistantConfigThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
hidden_changesarray of stringPaths that differ from live but read back the same: credentials and tool request specs. Values are never returned.
revisionintegerbase_versionintegerThe live version the draft started from.
live_versionintegerstalebooleanLive was edited after the draft started; publishing is refused.
updated_atstringISO 8601 timestamp
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 404 Not found, or outside what the key can see
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/draft" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"assistant_id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"hidden_changes": [
"string"
],
"revision": 1,
"base_version": 1,
"live_version": 1,
"stale": true,
"updated_at": "2026-10-28T09:30:00.000Z"
}
}Save the assistant's draft
PUT/api/assistants/{id}/draft
Starts a draft from the live config, or replaces the current one. Credentials and tool request specs left out are kept from the stored draft (or from live for a new draft).
Secret API key, not read-only. How it works
Path parameters
idstringrequired
Request body
configAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition7 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
falserequestobjectwrite-only, never returnedServer-side HTTP execution spec, never returned on reads. A write that omits it keeps the stored spec for the same tool name; removing or renaming the tool drops it.
4 attributes
urlstringrequiredurimethodstringOne of
GETPOSTPUTPATCHDELETEheadersobjecttimeout_msinteger1 to 120000
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition7 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
falserequestobjectwrite-only, never returnedServer-side HTTP execution spec, never returned on reads. A write that omits it keeps the stored spec for the same tool name; removing or renaming the tool drops it.
4 attributes
urlstringrequiredurimethodstringOne of
GETPOSTPUTPATCHDELETEheadersobjecttimeout_msinteger1 to 120000
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
expected_draft_revisionintegermin 0The draft_revision the caller read. A save over a newer draft is refused with 409 draft_conflict.
expected_versionintegermin 1The live version the caller edited from. A save that starts a new draft is refused with 409 live_changed when live has moved on since.
Returns
200 OK
Response attributes
dataAssistantDraft | nullrequired8 attributes
assistant_idstringconfigAssistantConfigThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
hidden_changesarray of stringPaths that differ from live but read back the same: credentials and tool request specs. Values are never returned.
revisionintegerbase_versionintegerThe live version the draft started from.
live_versionintegerstalebooleanLive was edited after the draft started; publishing is refused.
updated_atstringISO 8601 timestamp
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409 Conflict
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X PUT "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/draft" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"session": null
}
}'{
"data": {
"assistant_id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"hidden_changes": [
"string"
],
"revision": 1,
"base_version": 1,
"live_version": 1,
"stale": true,
"updated_at": "2026-10-28T09:30:00.000Z"
}
}Discard the assistant's draft
DELETE/api/assistants/{id}/draft
Throws the draft away and returns the assistant; the live config is unchanged. Succeeds when there is no draft too.
Secret API key, not read-only. How it works
Path parameters
idstringrequired
Query parameters
expected_draft_revisionintegerThe draft_revision the caller looked at; a newer draft is not discarded (409 draft_conflict).
Returns
200 OK
Response attributes
dataAssistantrequired10 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequirednamestringrequiredconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
versionintegerrequireddraft_revisionintegerThe revision a draft save names as expected_draft_revision; 0 before the first draft.
draftobject | nullWhether a draft exists, without its config (GET /assistants/{id}/draft has it).
3 attributes
revisionintegerbase_versionintegerupdated_atstringISO 8601 timestamp
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409 Conflict
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X DELETE "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/draft" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"name": "Front desk",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"version": 1,
"draft_revision": 1,
"draft": {
"revision": 1,
"base_version": 1,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
}Update the draft from live
POST/api/assistants/{id}/draft/rebase
After live changed under a draft (a stale draft), lays what the draft changed since its base version over today's live config, so it can be published without undoing live's change. Settings both changed differently are refused with 409 rebase_conflict and their paths, unless keep_draft keeps the draft's values; those paths are returned as kept_draft. Also 409 no_draft, draft_conflict, rebase_unavailable when the base version is not in history, or rebase_invalid (with issues) when the merged config would not be valid; the draft is then left as it was.
Secret API key, not read-only. How it works
Path parameters
idstringrequired
Request body
expected_draft_revisionintegermin 0keep_draftbooleanKeep the draft's value where live changed the same setting differently.
Returns
200 The updated draft, and the settings where the draft's value was kept over live's.
Response attributes
dataAssistantDraft | nullrequired8 attributes
assistant_idstringconfigAssistantConfigThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
hidden_changesarray of stringPaths that differ from live but read back the same: credentials and tool request specs. Values are never returned.
revisionintegerbase_versionintegerThe live version the draft started from.
live_versionintegerstalebooleanLive was edited after the draft started; publishing is refused.
updated_atstringISO 8601 timestamp
kept_draftarray of stringrequired
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409 Conflict
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X POST "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/draft/rebase" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expected_draft_revision": 1,
"keep_draft": true
}'{
"data": {
"assistant_id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"hidden_changes": [
"string"
],
"revision": 1,
"base_version": 1,
"live_version": 1,
"stale": true,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"kept_draft": [
"string"
]
}Publish the draft
POST/api/assistants/{id}/publish
Makes the draft the live config and records the new version. Refused with 409 no_draft, version_conflict, draft_conflict, or live_changed when live was edited after the draft started.
Secret API key, not read-only. How it works
Path parameters
idstringrequired
Request body
expected_versionintegermin 1expected_draft_revisionintegermin 0notestringup to 500 characters
Returns
200 OK
Response attributes
dataAssistantrequired10 attributes
idstringrequiredorg_idstringrequiredproject_idstringrequirednamestringrequiredconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
versionintegerrequireddraft_revisionintegerThe revision a draft save names as expected_draft_revision; 0 before the first draft.
draftobject | nullWhether a draft exists, without its config (GET /assistants/{id}/draft has it).
3 attributes
revisionintegerbase_versionintegerupdated_atstringISO 8601 timestamp
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409 Conflict
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X POST "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/publish" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"expected_version": 1,
"expected_draft_revision": 1
}'{
"data": {
"id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"name": "Front desk",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
},
"version": 1,
"draft_revision": 1,
"draft": {
"revision": 1,
"base_version": 1,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
}List the assistant's config history
GET/api/assistants/{id}/versions
Every live config the assistant has had, newest first (the latest 100).
Secret API key. How it works
Path parameters
idstringrequired
Returns
200 OK
Response attributes
dataarray of AssistantVersionrequired8 attributes
assistant_idstringrequiredversionintegerrequirednamestringsourcestringrequiredOne of
createapi_editpublishrestorebulk_updateseedcreated_bystring | nullnotestring | nullcreated_atstringISO 8601 timestampconfigAssistantConfigThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/versions" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": [
{
"assistant_id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"version": 1,
"name": "Front desk",
"source": "create",
"created_by": "string",
"note": "string",
"created_at": "2026-10-28T09:30:00.000Z",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{}
]
},
"session": null,
"variables": [
{
"key": {},
"label": {},
"description": {},
"default": {}
}
],
"knowledge": {
"key": {
"chat": {},
"voice": {},
"priority": {}
}
}
}
}
]
}Get one version of the assistant's config
GET/api/assistants/{id}/versions/{version}
The live config the assistant had at that version, as the history list returns it. 404 for a version not in its history.
Secret API key. How it works
Path parameters
idstringrequiredversionintegerrequired
Returns
200 OK
Response attributes
dataAssistantVersionrequired8 attributes
assistant_idstringrequiredversionintegerrequirednamestringsourcestringrequiredOne of
createapi_editpublishrestorebulk_updateseedcreated_bystring | nullnotestring | nullcreated_atstringISO 8601 timestampconfigAssistantConfigThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
- 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 404 Not found, or outside what the key can see
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/versions/VERSION" \
-H "Authorization: Bearer $MLF_API_KEY"{
"data": {
"assistant_id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"version": 1,
"name": "Front desk",
"source": "create",
"created_by": "string",
"note": "string",
"created_at": "2026-10-28T09:30:00.000Z",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{
"name": {},
"description": {},
"parameters": {},
"enabled": {},
"channels": {},
"read_only": {}
}
]
},
"session": null,
"variables": [
{
"key": "string",
"label": "string",
"description": "string",
"default": "string"
}
],
"knowledge": {
"key": {
"chat": true,
"voice": true,
"priority": 1
}
}
}
}
}Restore a version
POST/api/assistants/{id}/versions/{version}/restore
Brings an old config back with today's credentials and tool auth: into the draft by default, or straight to live with target live.
Secret API key, not read-only. How it works
Path parameters
idstringrequiredversionintegerrequired
Request body
targetstringOne of
draftliveDefault
"draft"expected_versionintegermin 1expected_draft_revisionintegermin 0
Returns
200 The draft it was restored into, or the assistant with target live.
Response attributes
dataAssistantDraft | null | AssistantrequiredOne of 2 shapes
AssistantDraft
assistant_idstringconfigAssistantConfigThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
hidden_changesarray of stringPaths that differ from live but read back the same: credentials and tool request specs. Values are never returned.
revisionintegerbase_versionintegerThe live version the draft started from.
live_versionintegerstalebooleanLive was edited after the draft started; publishing is refused.
updated_atstringISO 8601 timestamp
Assistant
idstringrequiredorg_idstringrequiredproject_idstringrequirednamestringrequiredconfigAssistantConfigrequiredThe runtime profile minus per-call fields. agent.instructions and either session.realtime or the complete session.{llm,stt,tts} pipeline are required. Realtime requires provider; its model may use the runtime default. A pipeline LLM may omit provider for a LiveKit-hosted model id. Credentials are write-only: integrations.google_analytics.api_secret, channels.web_chat.analytics.ga4.api_secret and recording.s3.{access_key,secret,session_token} come back as
<key>_set: boolean, and a write that omits one keeps the stored value. Chat (web or WhatsApp) answers with channels.web_chat.llm, defaulting independently to openai/gpt-6.1-sol with medium reasoning; creating or enabling web chat, or changing that model while web chat or WhatsApp routing is live, is refused with 400 when chat has no adapter for its provider.5 attributes
agentobjectrequired1 attribute
instructionsstringrequired
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
sessionanyrequired5 attributes
llmobject2 attributes
providerstringnot emptymodelstringrequirednot empty
realtimeobject2 attributes
providerstringrequirednot emptymodelstringnot empty
sttProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
ttsProviderModel2 attributes
providerstringrequirednot emptymodelstringrequirednot empty
toolsAssistantToolsCustom tools. config.tools is the canonical home; the legacy session.tools is read only when config.tools is absent.
1 attribute
definitionsarray of AssistantToolDefinition6 attributes
namestringrequireddescriptionstringparametersobjectJSON Schema for the arguments, as exposed to the model.
enabledbooleanFalse keeps the tool saved, with its request, but offers it on no channel.
Default
truechannelsarray of stringWhere the tool is offered: text is web chat and WhatsApp, voice is every call including browser test calls. Absent means both.
read_onlybooleanTrue when the tool only looks things up. Test and preview chats call only read-only tools; any other tool answers that requests are off in a test chat.
Default
false
variablesarray of AssistantVariableDefup to 50 itemsAuthoring-time schema for {{key}} placeholders in agent.instructions, agent.context, agent.first_message, and agent.first_message_instructions; never delivered to the runtime.
4 attributes
keystringrequiredup to 64 characterslabelstringup to 120 charactersdescriptionstringup to 500 charactersdefaultstringup to 2000 characters
knowledgeobjectThe knowledge bases the assistant answers from, by knowledge base id (
kb_...). Unlike the rest of the config, leaving it out of a write keeps the stored selection; send{}to detach every base. An entry with bothchatandvoicefalse counts as detached. Changing it needs an org-wide key and editor access to each base: 403organization_knowledge_access_requiredfor a project key orknowledge_forbiddenwithout editor access, 400knowledge_base_not_foundfor an unknown id, 409knowledge_voice_requires_pipeline_assistantfor voice on a realtime session. Each refusal names the base inknowledge_base_id.3 attributes
chatbooleanrequiredSearch it in web chat and WhatsApp.
voicebooleanrequiredSearch it on calls. Needs a pipeline session, not realtime.
priorityintegerrequired0 to 100Each search reaches up to four of the attached bases that have a live publication, highest priority first (then by id), and searches them in parallel.
versionintegerrequireddraft_revisionintegerThe revision a draft save names as expected_draft_revision; 0 before the first draft.
draftobject | nullWhether a draft exists, without its config (GET /assistants/{id}/draft has it).
3 attributes
revisionintegerbase_versionintegerupdated_atstringISO 8601 timestamp
created_atstringISO 8601 timestampupdated_atstringISO 8601 timestamp
- 400 Validation error: usually
invalid_request, with the failing fields inissueswhen there are any - 401 Missing, malformed, unknown or revoked API key (
unauthorized) - 403 Refused, for example a read-only key on a write (
read_only_key), a role too low for the route (insufficient_role), or a route that needs a console session - 404 Not found, or outside what the key can see
- 409 Conflict
- 429 Rate limit exceeded (
rate_limited). WaitRetry-Afterseconds. Budgets are per 60-second window: developer API 120 per key and 600 per organization; public chat 30 per IP address, except polling for updates (60 per conversation and IP address) and analytics events (120 per IP address).
curl -X POST "https://api.myleadsfactory.tech/api/assistants/ASSISTANT_ID/versions/VERSION/restore" \
-H "Authorization: Bearer $MLF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"target": "draft",
"expected_version": 1
}'{
"data": {
"id": "asst_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"org_id": "org_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"project_id": "proj_5f0c2a9e7b1d4c3e8a6f0b2d4c6e8a1f",
"name": "Front desk",
"config": {
"agent": {
"instructions": "You answer enquiries for Acme Travel."
},
"tools": {
"definitions": [
{}
]
},
"session": null,
"variables": [
{
"key": {},
"label": {},
"description": {},
"default": {}
}
],
"knowledge": {
"key": {
"chat": {},
"voice": {},
"priority": {}
}
}
},
"version": 1,
"draft_revision": 1,
"draft": {
"revision": 1,
"base_version": 1,
"updated_at": "2026-10-28T09:30:00.000Z"
},
"created_at": "2026-10-28T09:30:00.000Z",
"updated_at": "2026-10-28T09:30:00.000Z"
}
}