Create an assistant
import { createClient, createResources } from "@morevoice/sdk";
const mv = createResources({ client: createClient({ baseUrl: "https://api.morevoice.ai/v1", auth: process.env.MOREVOICE_API_KEY }),});
const assistant = await mv.assistants.create({ first_message: "שלום, הגעתם למרפאת השרון. איך אפשר לעזור?", language: "he", metadata: { crm_id: "0031x00000AbCdE", }, name: "Clinic receptionist", system_prompt: "You book, move and cancel appointments. Keep answers short.", tools: { custom: [ { description: "Find free appointment slots for a doctor and date", headers: { Authorization: "Bearer crm-secret", }, name: "find_slots", parameters: { properties: { date: { type: "string", }, doctor: { type: "string", }, }, required: [ "date", ], type: "object", }, url: "https://crm.example.com/voice/tools", }, ], end_call: true, transfer_call: { destination: "queue:reception", }, }, voice: { provider: "gemini", style: "warm", voice_id: "Kore", },});console.log(assistant);import osimport uuid
import requests
response = requests.post( "https://api.morevoice.ai/v1/assistants", headers={"Authorization": f"Bearer {os.environ['MOREVOICE_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())}, json={ "first_message": "שלום, הגעתם למרפאת השרון. איך אפשר לעזור?", "language": "he", "metadata": { "crm_id": "0031x00000AbCdE", }, "name": "Clinic receptionist", "system_prompt": "You book, move and cancel appointments. Keep answers short.", "tools": { "custom": [ { "description": "Find free appointment slots for a doctor and date", "headers": { "Authorization": "Bearer crm-secret", }, "name": "find_slots", "parameters": { "properties": { "date": { "type": "string", }, "doctor": { "type": "string", }, }, "required": [ "date", ], "type": "object", }, "url": "https://crm.example.com/voice/tools", }, ], "end_call": True, "transfer_call": { "destination": "queue:reception", }, }, "voice": { "provider": "gemini", "style": "warm", "voice_id": "Kore", }, },)response.raise_for_status()print(response.json())curl -X POST https://api.morevoice.ai/v1/assistants \ -H "Authorization: Bearer $MOREVOICE_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "first_message": "שלום, הגעתם למרפאת השרון. איך אפשר לעזור?", "language": "he", "metadata": { "crm_id": "0031x00000AbCdE" }, "name": "Clinic receptionist", "system_prompt": "You book, move and cancel appointments. Keep answers short.", "tools": { "custom": [ { "description": "Find free appointment slots for a doctor and date", "headers": { "Authorization": "Bearer crm-secret" }, "name": "find_slots", "parameters": { "properties": { "date": { "type": "string" }, "doctor": { "type": "string" } }, "required": [ "date" ], "type": "object" }, "url": "https://crm.example.com/voice/tools" } ], "end_call": true, "transfer_call": { "destination": "queue:reception" } }, "voice": { "provider": "gemini", "style": "warm", "voice_id": "Kore" }}'Creates an assistant. Only name is required; fields you leave out take their defaults (GET /v1/assistants/{id} shows them all).
Try it in the API playground with a test-mode key.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”The API version to use for this request. Defaults to the version the API key is pinned to.
Example
2026-11-01A unique key (for example a UUID) that makes this request safe to retry: for 24 hours, a retry with the same key and parameters returns the first response instead of acting twice.
Example
5f0c1e8a-7b2d-4c3e-9f1a-2b6d8e4c0a17Request Bodyrequired
Section titled “Request Bodyrequired”A new assistant. Only name is required; the rest takes the defaults (GET /v1/assistants/{id} shows them all). metadata entries with an empty string are dropped.
object
object
The vocal events the model may use.
object
1–10.
Said in turn when the caller is silent.
1–60.
object
0–3000.
The fillers.
100–1500.
8–60.
500–3000.
5–3600.
object
0–3.
0–3.
0–3.
0–5.
object
0–10.
0–3000.
0–10.
0–0.5.
object
1500–8000.
The message left with leave_message.
object
Said before the assistant ends the call.
Phrases that end the call.
What the assistant says first.
The call language.
object
16–8192.
0–2.
10–43200 (12 hours).
Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent.
object
The assistant’s name (yours; callers never hear it).
Allow publishable keys (the browser widget) to call this assistant. Default false.
The instructions the model follows.
Fields you leave out are kept.
object
Replaces the whole list. A tool sent without headers keeps the stored headers of the tool with the same name.
A custom tool as you send it. headers are write-only: stored with the assistant, never returned.
object
Default legacy.
What the tool does and when to call it.
Default true.
Extra request headers, e.g. Authorization. Write-only. On update, leave it out to keep the stored headers; send {} to remove them.
object
The answer of a mock tool.
The function name the model calls (unique per assistant).
JSON Schema (an object schema) of the arguments.
object
Spoken while the tool runs.
How long to wait for the webhook, 1–60 (default 15).
Default: webhook when url is set, else mock.
The webhook URL (http or https). Required for webhook tools.
object
Free text that helps recognition.
Languages to expect (ISO 639-1).
Words and names to recognise better.
object
The TTS model.
The text-to-speech provider.
Delivery direction.
A voice from GET /v1/voices.
Responses
Section titled “Responses”The new assistant.
An AI voice assistant: what it says and knows, how it sounds and listens, and the tools it can use. Assistants are shared by live and test mode.
object
Pipeline tuning. The defaults suit most assistants.
object
The vocal events the model may use when voice.expressions is on.
object
How many idle messages before giving up.
Said in turn when the caller is silent.
Silence before an idle message.
Semantic end-of-turn detection instead of fixed silence delays.
object
Delay before a filler.
The fillers.
Play a short filler if the answer is not audible yet.
Start preparing the answer during the caller’s pause.
Pause after which the early answer starts.
The longest first spoken chunk without punctuation.
object
The model for everything else (null: llm.model).
auto: simple turns go to simple_model.
The model for simple turns.
Turns that stay on the complex model after an escalation.
With intelligent turn taking: the longest wait after speech before the turn ends.
End the call after this much silence.
object
Wait after a transcript without final punctuation.
Wait after a transcript that ends with a number (the caller may be dictating).
Wait after a transcript that ends with punctuation.
Model-based end-of-turn detection.
Silence after the caller stops before the assistant answers.
object
Pause before the assistant speaks again after an interruption.
With num_words: 0: how long to wait for a real word before resuming.
Words the caller must say to interrupt the assistant (0: voice alone).
Seconds of caller voice that count as an interruption.
Answering-machine detection on outbound calls.
object
The longest the verdict may take after answer; unsure counts as a person.
The message left with leave_message.
On outbound calls: off, hang_up on a machine, or leave_message after the beep.
What is kept after a call.
object
Keep the call’s event log.
Record the call.
Write an AI summary (intent, outcome, action items) when the call ends.
Keep the transcript.
An ISO-8601 timestamp in UTC.
Said before the assistant ends the call.
Phrases that end the call when the assistant says them.
What the assistant says first.
Whether the assistant speaks first (first_message), waits for the caller, or generates its opening.
The assistant’s ID.
The call language (BCP-47, e.g. he, en).
true in live mode, false in test mode.
The language model behind the assistant.
object
The longest reply, in tokens.
The model, e.g. gpt-4.1.
The language-model provider.
Sampling temperature, 0–2.
Calls end after this long.
Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent.
object
The assistant’s name (yours; callers never hear it).
Publishable keys (the browser widget) may start web calls to this assistant.
The instructions the model follows.
The tools the assistant can use.
object
Your own tools (webhooks).
A tool the assistant can call during a call.
object
The request/response contract: legacy ({tool, arguments, call:{id}}) or v1 (rich call context and say / end_call / transfer responses).
What the tool does and when to call it, for the model.
Disabled tools are kept but not offered to the model.
Names of the extra request headers stored for this tool. Header values are write-only and never returned.
The answer of a mock tool; {{argument}} placeholders are filled in.
The function name the model calls (letters, digits, _ and -).
JSON Schema of the arguments the model passes.
object
Spoken while the tool runs (empty: nothing).
How long to wait for the webhook to answer.
webhook: a signed request is POSTed to url. mock: answers mock_response without any request (for testing prompts).
The webhook URL (webhook tools).
The assistant may end the call (end_call).
The assistant may look up the current date and time.
The assistant may search the web.
How the assistant hears.
object
Free text that helps recognition (the business, the topic).
Languages to expect (ISO 639-1).
The STT model.
The speech-to-text provider.
Only transcribe the hinted languages.
Words and names to recognise better (products, people, places).
An ISO-8601 timestamp in UTC.
How the assistant sounds.
object
Let the model add vocal events (breaths, laughs, pauses).
The TTS model.
The text-to-speech provider.
Delivery direction, e.g. warm, friendly and natural. With style_mode: dynamic it is the fallback.
dynamic: the model adapts the delivery to the caller per reply. fixed: style is always used.
TTS tier: auto (the plan’s default), premium or lite.
A voice from GET /v1/voices (its voice_id).
Example
{ "advanced": { "expression_tags": [ "breath", "laugh" ], "idle": { "max_messages": 3, "messages": [ "את/ה עדיין איתי?" ], "timeout_seconds": 7.5 }, "intelligent_turn_taking": false, "latency": { "acknowledgement_after_ms": 700, "acknowledgement_phrases": [ "אממ…" ], "acknowledgements": true, "early_start": true, "early_start_ms": 300, "first_chunk_max_words": 25 }, "llm_routing": { "complex_model": null, "mode": "off", "simple_model": "gpt-4.1-mini", "sticky_turns": 3 }, "max_endpoint_delay_ms": 1000, "silence_timeout_seconds": 30, "start_speaking_plan": { "on_no_punctuation_seconds": 1.5, "on_number_seconds": 0.5, "on_punctuation_seconds": 0.1, "smart_endpointing": "off", "wait_seconds": 0.4 }, "stop_speaking_plan": { "backoff_seconds": 1, "interruption_confirm_ms": 900, "num_words": 0, "voice_seconds": 0.2 } }, "answering_machine_detection": { "max_decision_ms": 3500, "message": "", "mode": "off" }, "artifacts": { "logging": true, "recording": true, "summary": true, "transcript": true }, "created": "2026-11-03T09:14:22.000Z", "end_call_message": "תודה ששוחחת איתי, יום נעים!", "end_call_phrases": [ "להתראות" ], "first_message": "שלום, הגעתם למרפאת השרון. איך אפשר לעזור?", "first_message_mode": "assistant_speaks_first", "flow_id": null, "id": "asst_3cYbE6uYvGkH8w4ZK1rTqd", "language": "he", "livemode": true, "llm": { "max_output_tokens": 400, "model": "gpt-4.1", "provider": "openai", "temperature": 1 }, "max_duration_seconds": 600, "metadata": { "crm_id": "0031x00000AbCdE" }, "name": "Clinic receptionist", "object": "assistant", "public": false, "system_prompt": "You book, move and cancel appointments. Keep answers short.", "tools": { "add_participant": null, "custom": [ { "contract": "legacy", "description": "Find free appointment slots for a doctor and date", "enabled": true, "header_names": [ "Authorization" ], "mock_response": "{\"ok\": true}", "name": "find_slots", "parameters": { "properties": { "date": { "type": "string" }, "doctor": { "type": "string" } }, "required": [ "date" ], "type": "object" }, "request_start_message": "רגע, אני בודקת", "timeout_seconds": 15, "type": "webhook", "url": "https://crm.example.com/voice/tools" } ], "end_call": true, "get_current_time": false, "transfer_call": { "destination": "queue:reception" }, "web_search": false }, "transcriber": { "context": "", "language_hints": [ "he", "en" ], "model": "stt-rt-v5", "provider": "soniox", "strict_language_hints": false, "terms": [ "השרון" ] }, "updated": "2026-11-03T09:14:22.000Z", "voice": { "expressions": true, "model": "gemini-3.8-flash-tts", "provider": "gemini", "style": "warm", "style_mode": "dynamic", "tier": "auto", "voice_id": "Kore" }}The request is invalid: a parameter is missing, malformed or unknown, or the version header is unknown.
Every /v1 error.
object
object
A stable, machine-readable code from the error-code catalogue.
Structured context, e.g. required_scope or the compliance verdict.
object
A link to the documentation of this code.
A human-readable explanation. Do not parse it.
The request parameter the error relates to, e.g. to or metadata[order_id].
The X-Request-Id of this request. Quote it when you contact support.
The category of the error.
Example
{ "error": { "code": "parameter_missing", "doc_url": "https://docs.morevoice.ai/api/errors#parameter-missing", "message": "Missing required parameter: to.", "param": "to", "request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ", "type": "invalid_request_error" }}Headers
Section titled “Headers”The request’s ID (req_…). Quote it when you contact support.
No valid API key was sent.
Every /v1 error.
object
object
A stable, machine-readable code from the error-code catalogue.
Structured context, e.g. required_scope or the compliance verdict.
object
A link to the documentation of this code.
A human-readable explanation. Do not parse it.
The request parameter the error relates to, e.g. to or metadata[order_id].
The X-Request-Id of this request. Quote it when you contact support.
The category of the error.
Example
{ "error": { "code": "invalid_api_key", "doc_url": "https://docs.morevoice.ai/api/errors#invalid-api-key", "message": "Invalid API key.", "request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ", "type": "authentication_error" }}Headers
Section titled “Headers”The request’s ID (req_…). Quote it when you contact support.
The key may not do this (a missing scope, a plan limit, or a compliance block).
Every /v1 error.
object
object
A stable, machine-readable code from the error-code catalogue.
Structured context, e.g. required_scope or the compliance verdict.
object
A link to the documentation of this code.
A human-readable explanation. Do not parse it.
The request parameter the error relates to, e.g. to or metadata[order_id].
The X-Request-Id of this request. Quote it when you contact support.
The category of the error.
Example
{ "error": { "code": "missing_scope", "doc_url": "https://docs.morevoice.ai/api/errors#missing-scope", "message": "This API key lacks the calls:write scope.", "request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ", "type": "permission_error" }}Headers
Section titled “Headers”The request’s ID (req_…). Quote it when you contact support.
The request conflicts with the object’s state, or the Idempotency-Key was reused with other parameters.
Every /v1 error.
object
object
A stable, machine-readable code from the error-code catalogue.
Structured context, e.g. required_scope or the compliance verdict.
object
A link to the documentation of this code.
A human-readable explanation. Do not parse it.
The request parameter the error relates to, e.g. to or metadata[order_id].
The X-Request-Id of this request. Quote it when you contact support.
The category of the error.
Example
{ "error": { "code": "idempotency_mismatch", "doc_url": "https://docs.morevoice.ai/api/errors#idempotency-mismatch", "message": "This Idempotency-Key was already used with different parameters.", "request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ", "type": "idempotency_error" }}Headers
Section titled “Headers”The request’s ID (req_…). Quote it when you contact support.
Too many requests, or no call capacity right now. Retry after the Retry-After delay.
Every /v1 error.
object
object
A stable, machine-readable code from the error-code catalogue.
Structured context, e.g. required_scope or the compliance verdict.
object
A link to the documentation of this code.
A human-readable explanation. Do not parse it.
The request parameter the error relates to, e.g. to or metadata[order_id].
The X-Request-Id of this request. Quote it when you contact support.
The category of the error.
Example
{ "error": { "code": "rate_limited", "doc_url": "https://docs.morevoice.ai/api/errors#rate-limited", "message": "Too many requests. Retry after 1 second.", "request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ", "type": "rate_limit_error" }}Headers
Section titled “Headers”Seconds to wait before retrying.
The request’s ID (req_…). Quote it when you contact support.
Something went wrong on MoreVoice’s side. Retry with the same Idempotency-Key.
Every /v1 error.
object
object
A stable, machine-readable code from the error-code catalogue.
Structured context, e.g. required_scope or the compliance verdict.
object
A link to the documentation of this code.
A human-readable explanation. Do not parse it.
The request parameter the error relates to, e.g. to or metadata[order_id].
The X-Request-Id of this request. Quote it when you contact support.
The category of the error.
Example
{ "error": { "code": "internal_error", "doc_url": "https://docs.morevoice.ai/api/errors#internal-error", "message": "Something went wrong on MoreVoice's side.", "request_id": "req_7Hk2LmN9pQ4rS6tV8wX0yZ", "type": "api_error" }}Headers
Section titled “Headers”The request’s ID (req_…). Quote it when you contact support.