---
title: "Partial update of a saved voice config"
method: PATCH
path: "/v1/voice/saved-configs/{config_id}"
tags: ["voice"]
---

# Partial update of a saved voice config

`PATCH /v1/voice/saved-configs/{config_id}`

## Path parameters

- `config_id` string, uuid, required

## Request body

- SavedVoiceConfigUpdate — Partial update for saved configs. ``name`` can be patched on saved configs. Other fields share the same validation as inline configs.
  - `voice_tuning` object, nullable
  - `stt_provider` string, nullable
  - `stt_model` string, nullable
  - `stt_provider_data` object, nullable
  - `tts_speed` number, nullable
  - `tts_provider_data` VoiceTTSProviderDataInput — OpenAPI-visible TTS overrides accepted by voice-config CRUD. The linked ``voice_id`` remains the authority for which provider member is valid. The service resolves that row and validates this payload again against the provider-specific discriminated union, including model support and the Inworld TTS-2-only expressive-speech constraint.
    - `provider` 'elevenlabs' | 'inworld', nullable
    - `model` string, nullable
    - `expressive_speech` boolean — Enable managed expressive steering. Valid only for an Inworld voice using the effective inworld-tts-2 model.
    - `expressive_style` 'warm' | 'professional' | 'upbeat' | 'calm' | 'empathetic' | 'confident' | 'dynamic' — Selectable delivery style for Inworld TTS-2 expressive steering. Each value maps to a tone block interpolated into the shared expressive contract (:func:`src.runtime.speech_output.build_inworld_tts2_expressive_directive`) and, in the voice layer, to a default Inworld ``delivery_mode``. ``WARM`` reproduces the original single-directive behavior and is the default applied when a config enables expressive speech without picking a style.
  - `vad_provider_data` object, nullable
  - `local_vad_params` LocalVADParams — Silero VAD tuning. Always applied for Deepgram Nova; ignored otherwise.
    - `confidence` number
    - `start_secs` number
    - `stop_secs` number
    - `min_volume` number
  - `turn_analyzer_params` TurnAnalyzerParams — Smart-turn-v3 tuning. Always applied for Deepgram Nova; ignored otherwise.
    - `stop_secs` number
    - `pre_speech_ms` number
    - `max_duration_secs` number
  - `pronunciation_overrides` object, nullable
  - `noise_cancellation_enabled` boolean, nullable
  - `noise_cancellation_provider` 'rnnoise' | 'dtln' — Noise-suppression engine wired by ``audio_filters.build_audio_in_filter``. Applies only when ``noise_cancellation_enabled``. String values MUST match the provider strings the factory dispatches on.
  - `language` string, nullable
  - `locale` string, nullable
  - `multilingual_enabled` boolean, nullable
  - `multilingual_languages` string[], nullable
  - `first_speaker` 'agent' | 'user', nullable
  - `mode` 'static' | 'dynamic', nullable
  - `text` string, nullable
  - `instructions` string, nullable
  - `interruptible` boolean, nullable
  - `ai_disclosure_text` string, nullable
  - `name` string, nullable
  - `voice_id` string, uuid, nullable

## Response `200`

Successful Response

- VoicePipelineConfigResponse
  - `id` string, uuid, required
  - `organization_id` string, uuid, nullable
  - `name` string, nullable
  - `agent_id` string, uuid, nullable
  - `team_id` string, uuid, nullable
  - `persona_id` string, uuid, nullable
  - `voice_id` string, uuid, required
  - `voice` VoiceOut, required
    - `id` string, uuid, required
    - `provider` 'elevenlabs' | 'inworld', required
    - `external_id` string, required
    - `name` string, required
    - `description` string, nullable
    - `preview_url` string, nullable
    - `language` string, nullable
    - `accent` string, nullable
    - `category` string, nullable
    - `labels` object
    - `supported_models` string[]
    - `is_active` boolean
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
  - `voice_tuning` object
  - `stt_provider` string, required
  - `stt_model` string, nullable
  - `stt_language` string, required
  - `stt_provider_data` object
  - `tts_speed` number, nullable
  - `tts_provider_data` object
  - `vad_provider` string, required
  - `vad_provider_data` object
  - `local_vad_params` object
  - `turn_analyzer_params` object
  - `interruption_sensitivity` number, required
  - `hard_turn_timeout_ms` integer, nullable
  - `min_endpoint_delay_ms` integer, required
  - `max_endpoint_delay_ms` integer, required
  - `preemptive_generation_enabled` boolean, required
  - `end_call_phrases` string[]
  - `pronunciation_overrides` object
  - `noise_cancellation_enabled` boolean, required
  - `noise_cancellation_provider` 'rnnoise' | 'dtln', required — Noise-suppression engine wired by ``audio_filters.build_audio_in_filter``. Applies only when ``noise_cancellation_enabled``. String values MUST match the provider strings the factory dispatches on.
  - `normalize_for_speech` boolean, required
  - `audio_in_sample_rate` integer, required
  - `audio_out_sample_rate` integer, required
  - `metrics_enabled` boolean, required
  - `usage_metrics_enabled` boolean, required
  - `heartbeats_period_secs` integer, nullable
  - `idle_pipeline_timeout_ms` integer, nullable
  - `language` string, required
  - `locale` string, nullable
  - `multilingual_enabled` boolean, required
  - `multilingual_languages` string[]
  - `linked_agent_count` integer
  - `linked_agent_names` string[]
  - `linked_team_count` integer
  - `linked_team_names` string[]
  - `metadata_` object
  - `first_speaking_config` FirstSpeakingConfig — Config for the AI's opening turn (no user input yet). Lives inside ``ChannelConfig`` — first-speaking is per-channel. Mode-agnostic fields: - ``first_speaker``: ``"agent"`` opens the call with the rendered message; ``"user"`` skips the greeting (caller speaks first). Non-voice channels treat the inbound user message as the ``"user"`` opener and ignore this field at runtime. Greeting source (only applies when ``first_speaker="agent"``): - ``static`` mode: ``text`` is required and emitted verbatim (templated via the shared ``{{var}}`` engine, ``src.shared.templating.render``). - ``dynamic`` mode: ``instructions`` are sent to the model router with the agent persona to render an opening line (instructions are templated). When omitted/empty, ``instructions`` falls back to ``DEFAULT_DYNAMIC_FIRST_SPEAKING_INSTRUCTIONS`` so operators who just want a generic friendly opener don't have to author copy. Voice-only fields (ignored on non-audio channels): - ``interruptible``: whether the caller can barge in mid-greeting. - ``ai_disclosure_text``: regulatory disclosure (e.g. CA SB 1001), played as an uninterruptible TTS frame BEFORE the greeting. Disclosure plays even when ``first_speaker="user"`` because the regulation requires the disclosure regardless of who speaks first.
    - `first_speaker` 'agent' | 'user'
    - `mode` 'static' | 'dynamic'
    - `text` string, nullable
    - `instructions` string, nullable
    - `interruptible` boolean
    - `ai_disclosure_text` string, nullable
  - `warnings` string[]
  - `effective_stt_model` string, nullable
  - `effective_stt_provider_data` object, nullable
  - `effective_tts_model` string, nullable
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `400` — Bad request
- `401` — Authentication required
- `404` — Resource not found
- `422` — Validation Error

---

[API](https://skmtc.net/oneloop-hq/apis/feather-api.md) · [All operations](https://skmtc.net/oneloop-hq/apis/feather-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/oneloop-hq/feather-api/revisions/9cd7291d4228/schema)
