Create an agent from a template, optionally setting its fields in the same request. Without template it starts blank; GET /api/v1/voice/catalog lists the templates with the languages and voices an agent takes. Templates are written in English and Chinese, so for another language send system_prompt and first_message in it. Either the whole request is saved or no agent is made, so a refused request can be sent again once corrected. The answer's dashboard_url is the agent's page in the dashboard, where you can talk to the draft in your browser. Every agent runs on EvaSay ASR, EvaSay LLM and EvaSay TTS, chosen by EvaSay for each call's language and load and included in the call price; there are no other providers' accounts to set.
curl https://evasay.com/api/v1/voice/agents \
-X POST \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"name": "Front desk",
"language": "en",
"first_message": "Hi, thanks for calling Sunrise Salon. How can I help?",
"system_prompt": "You are the front desk of Sunrise Salon..."
}'
Update any of these fields with PATCH /api/v1/voice/agents/{id}:
| Field | Notes |
|---|---|
name, first_message, system_prompt | Text |
status | published publishes the draft as a new version; draft stops taking calls |
language | One of 27 languages, e.g. en, zh, es, de, or multi to follow the caller |
temperature | 0-100 |
max_duration_sec, silence_timeout_sec | Call limits |
interruptible, end_call_enabled | Booleans |
confirm_details | Boolean; say numbers and names back and have them confirmed |
ai_disclosure | Boolean, default true; before its first message the agent says in the call's language that the caller is speaking with an AI (left out when the first message already says so) |
voicemail_detection | Boolean; outbound calls listen first and end on a mailbox |
voicemail_message | Left on a mailbox, may use {{variables}}; none to hang up |
transfer_number | Number to transfer to, international format |
transfer_destinations | Up to 9 more numbers, [{name, number, when}]; the agent picks one by when |
transfer_briefing | Boolean; the person who answers first hears the agent's summary of the call |
pronunciations | Up to 100 [{word, say, case_sensitive}]; the voice says say for word |
idle_messages | Up to 3 reminders said in turn to a silent caller before the call ends |
noise_reduction | Boolean; the caller's background noise is filtered before they are heard |
recording_enabled | Boolean; calls are recorded in two channels (caller left, agent right) |
recording_consent | announce, ask (kept only if the caller agrees) or none |
recording_notice | The notice or question said first; empty for the built-in one in the call language |
handoffs | Up to 5 [{agent_id, when}]: other agents this one may hand a call to |
knowledge_base_id | One of your knowledge bases |
vocabulary_id | One of your vocabularies; callers saying its terms are heard more reliably |
voice_id | A built-in EvaSay voice id, or one of your cloned voices (clone:…) |
Built-in voices depend on the language: Chinese has ming-designed-female-clear, ming-designed-female-warm (female), ming-designed-male-clear and ming-designed-male-friendly (male), the other languages F1–F5 (female) and M1–M5 (male). A built-in voice that does not speak the agent's language becomes the voice of the same gender that does. Any other value, or a cloned voice that is not ready yet, is refused. The older field name tts_voice_id is still accepted.
analysis_config sets what is worked out from each call once it ends: summary (default true), summaryLanguage, successCriteria (what a successful call achieves), fields (up to 20 {name, type, description} to extract, type being string, number or boolean) and scorecard (up to 10 {name, description, weight}, weight 1–5). The results are in the call's analysis and the call.analyzed webhook.
Changing an agent's fields changes its draft. Calls keep using the published version until you publish the draft with POST /api/v1/voice/agents/{id}/publish (optionally with a note), or with status: "published" in the same PATCH. Each publish keeps a numbered version; published_version in the agent says which one calls use. A call stays on the version that was live when it started, so publishing during a call does not change it. Test calls from the dashboard use the draft.
GET /agents/{id}/versions lists the versions, and POST /agents/{id}/versions/{version}/restore rolls back: new calls use that version and the draft becomes it. The agent's name, deployment, widget look and notifications are not versioned and change at once, as do the documents of its knowledge base.