---
title: "Update Voice Agent"
method: PUT
path: "/voice/agents/{agentId}"
tags: ["Voice Agents"]
---

# Update Voice Agent

`PUT /voice/agents/{agentId}`

## Request

- Base URL: `https://api.speakai.co/v1`
- URL: `https://api.speakai.co/v1/voice/agents/{agentId}`
- Auth: API key in header `x-speakai-key` and API key in header `x-access-token`

### Update Agent

Requires the OWNER or ADMIN role. Partial update — send only the fields you want to change; fields left out of the body are left untouched, including `avatar`. `companyId`, `agentId`, and other immutable fields are silently dropped if sent.

If the body sets `avatar.avatarId`, the server re-resolves `avatarUrl`/`provider`/Tavus ids from the catalog row and overwrites the agent's whole avatar sub-object with that resolved value; an unresolvable `avatarId` is rejected with 400 rather than saved.

## Path parameters

- `agentId` string, required

## Request body

- object
  - `_id` string: MongoDB document id, included because every document has one; use agentId to identify it.
  - `agentId` string: Server-generated UUID. Immutable — sent in the body on create or update is silently dropped.
  - `companyId` string: Stamped from the caller's authenticated company. Sending your own value on create or update is silently dropped; you cannot re-parent an agent.
  - `userId` string: Id of the user who created the agent.
  - `name` string: Required on create. Trimmed, non-empty.
  - `personality` string: Required on create. Free text describing the agent's tone. Can be cleared to an empty string on update.
  - `instructions` string: Required on create. The agent's system instructions. Can be cleared to an empty string on update.
  - `voice` object: Required on create.
    - `provider` string, required: TTS provider, e.g. elevenlabs or openai.
    - `voiceId` string, required
    - `model` string
  - `stt` object: Speech-to-text provider config. Shape is not validated beyond being an object.
  - `llm` object
    - `provider` string: Must be one of the voice-agent LLM providers if sent.
    - `model` string: Must be one of the voice-agent model ids if sent.
  - `liveVoice` string, nullable: The voice id used when llm.model is a Live (speech-to-speech) model. Rejected with a 400 listing the valid ids if it is not one of the voices the resolved Live model offers. Cleared by sending an empty string or null.
  - `avatar` object: Set avatar.avatarId to attach an avatar; the server looks it up in your avatar catalog and derives avatarUrl, provider, and any provider-specific ids (e.g. Tavus faceId/palId) from that catalog row. Any of those fields sent in the request body are ignored — they cannot be set directly. An avatarId with no matching catalog row is rejected with 400, not saved.
    - `avatarId` string: Required to set an avatar. Must match a row in your company's avatar catalog (your own uploads or the shared system catalog).
    - `avatarUrl` string: Read-only in practice: always overwritten from the matched catalog row.
    - `provider` string: Read-only in practice: always overwritten from the matched catalog row.
    - `tavusFaceId` string: Read-only: derived server-side from the catalog row's tavus.faceId. Cannot be set by the client.
    - `tavusPalId` string: Read-only: derived server-side from the catalog row's tavus.palId. Cannot be set by the client.
  - `conversationMode` 'voice' | 'avatar'
  - `status` string: One of the agent status values.
  - `chatSettings` object
    - `welcomeMessage` string
    - `conversationStarters` string[]
    - `maxResponseLength` integer
    - `topicsToAvoid` string[]
    - `maxSessionLength` integer
    - `language` string
    - `responsePace` string: One of the response-pace presets, if set.
  - `websiteUrl` string
  - `enableWebSearch` boolean
  - `creativityLevel` number
  - `folderId` string
  - `telephony` object: Telephony settings for the agent: whether phone calls are enabled, which of your phone numbers the agent uses, call recording, and handoff to a person. Accepted on create and, unlike most other server-managed fields, NOT stripped on update. The keys listed here are validated, so a malformed value returns 400: `enabled` and `settings.recordCalls` must be booleans, `phoneNumberId` must be a string, and `handoff.targetNumber` must be an E.164 number, required whenever `handoff.enabled` is true. Unknown keys inside the object are still accepted and stored as sent. Setting `phoneNumberId` is not the same as assigning that number to the agent: the assignment lives on the phone number's own `agentId` field and is written by the phone number endpoints, which this reference does not yet cover.
    - `enabled` boolean
    - `phoneNumberId` string
    - `handoff` object
      - `enabled` boolean
      - `targetNumber` string: The number the call is transferred to when the agent hands off to a person. Must be in E.164 format: a plus sign, then 2 to 15 digits, the first of which cannot be zero (for example +15551234567). Conditionally required: required when `handoff.enabled` is true, otherwise optional and an empty string is accepted. A malformed number returns 400 even when `handoff.enabled` is false.
      - `summaryPrompt` string
    - `settings` object
      - `recordCalls` boolean
  - `isDeleted` boolean: DELETE soft-deletes: this flips to true and the agent stops appearing in list/get, but the document is not removed.
  - `deletedAt` string, date-time, nullable
  - `createdAt` string, date-time
  - `updatedAt` string, date-time

## Response `200`

OK

- object
  - `status` 'success'
  - `data` object
    - `agent` object
      - `_id` string: MongoDB document id, included because every document has one; use agentId to identify it.
      - `agentId` string: Server-generated UUID. Immutable — sent in the body on create or update is silently dropped.
      - `companyId` string: Stamped from the caller's authenticated company. Sending your own value on create or update is silently dropped; you cannot re-parent an agent.
      - `userId` string: Id of the user who created the agent.
      - `name` string: Required on create. Trimmed, non-empty.
      - `personality` string: Required on create. Free text describing the agent's tone. Can be cleared to an empty string on update.
      - `instructions` string: Required on create. The agent's system instructions. Can be cleared to an empty string on update.
      - `voice` object: Required on create.
        - `provider` string, required: TTS provider, e.g. elevenlabs or openai.
        - `voiceId` string, required
        - `model` string
      - `stt` object: Speech-to-text provider config. Shape is not validated beyond being an object.
      - `llm` object
        - `provider` string: Must be one of the voice-agent LLM providers if sent.
        - `model` string: Must be one of the voice-agent model ids if sent.
      - `liveVoice` string, nullable: The voice id used when llm.model is a Live (speech-to-speech) model. Rejected with a 400 listing the valid ids if it is not one of the voices the resolved Live model offers. Cleared by sending an empty string or null.
      - `avatar` object: Set avatar.avatarId to attach an avatar; the server looks it up in your avatar catalog and derives avatarUrl, provider, and any provider-specific ids (e.g. Tavus faceId/palId) from that catalog row. Any of those fields sent in the request body are ignored — they cannot be set directly. An avatarId with no matching catalog row is rejected with 400, not saved.
        - `avatarId` string: Required to set an avatar. Must match a row in your company's avatar catalog (your own uploads or the shared system catalog).
        - `avatarUrl` string: Read-only in practice: always overwritten from the matched catalog row.
        - `provider` string: Read-only in practice: always overwritten from the matched catalog row.
        - `tavusFaceId` string: Read-only: derived server-side from the catalog row's tavus.faceId. Cannot be set by the client.
        - `tavusPalId` string: Read-only: derived server-side from the catalog row's tavus.palId. Cannot be set by the client.
      - `conversationMode` 'voice' | 'avatar'
      - `status` string: One of the agent status values.
      - `chatSettings` object
        - `welcomeMessage` string
        - `conversationStarters` string[]
        - `maxResponseLength` integer
        - `topicsToAvoid` string[]
        - `maxSessionLength` integer
        - `language` string
        - `responsePace` string: One of the response-pace presets, if set.
      - `websiteUrl` string
      - `enableWebSearch` boolean
      - `creativityLevel` number
      - `folderId` string
      - `telephony` object
        - `enabled` boolean
        - `phoneNumberId` string
        - `handoff` object
          - `enabled` boolean
          - `targetNumber` string
          - `summaryPrompt` string
        - `settings` object
          - `recordCalls` boolean
      - `isDeleted` boolean: DELETE soft-deletes: this flips to true and the agent stops appearing in list/get, but the document is not removed.
      - `deletedAt` string, date-time, nullable
      - `createdAt` string, date-time
      - `updatedAt` string, date-time

## Other responses

- `400`: Validation failed, or avatar.avatarId does not match a catalog row visible to your company
- `403`: Caller's role is not OWNER or ADMIN
- `404`: Agent not found

---

[API](https://skmtc.dev/speakai/apis/speak-ai-api.md) · [All operations](https://skmtc.dev/speakai/apis/speak-ai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/speakai/apis/speak-ai-api/revisions/52d777e6d46e?raw)
