Skip to main content
PATCH
/
v1
/
voice
/
configs
/
{config_id}
Partial update of a voice pipeline config
curl --request PATCH \
  --url https://api-sandbox.featherhq.com/v1/voice/configs/{config_id} \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '
{
  "voice_tuning": {},
  "stt_provider": "<string>",
  "stt_model": "<string>",
  "stt_provider_data": {},
  "tts_speed": 5,
  "tts_provider_data": {},
  "vad_provider_data": {},
  "local_vad_params": {
    "confidence": 0.7,
    "start_secs": 0.2,
    "stop_secs": 0.5,
    "min_volume": 0.6
  },
  "turn_analyzer_params": {
    "stop_secs": 2,
    "pre_speech_ms": 500,
    "max_duration_secs": 8
  },
  "interruptions_enabled": true,
  "interruption_min_words": 10,
  "interruption_min_duration_ms": 5000,
  "interruption_backoff_ms": 5000,
  "interruption_trigger_phrases": [
    "<string>"
  ],
  "interruption_hard_phrases": [
    "<string>"
  ],
  "interruption_final_transcript_grace_ms": 1000,
  "voicemail_detection_timeout_ms": 30000,
  "voicemail_detection_model": "<string>",
  "voicemail_message": "<string>",
  "max_call_duration_ms": 7200500,
  "silence_timeout_ms": 300000,
  "silence_reminder_count": 5,
  "silence_reminder_message": "<string>",
  "silence_end_message": "<string>",
  "dtmf_enabled": true,
  "dtmf_termination_digit": "<string>",
  "dtmf_inter_digit_timeout_ms": 30125,
  "dtmf_max_digits": 32,
  "dtmf_prefix": "<string>",
  "pronunciation_overrides": {},
  "noise_cancellation_enabled": true,
  "background_audio_enabled": true,
  "background_audio_volume": 0.5,
  "background_audio_loop": true,
  "language": "<string>",
  "locale": "<string>",
  "multilingual_enabled": true,
  "multilingual_languages": [
    "<string>"
  ],
  "text": "<string>",
  "instructions": "<string>",
  "interruptible": true,
  "ai_disclosure_text": "<string>",
  "voice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'
{
  "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "voice_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "voice": {
    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "provider": "<string>",
    "external_id": "<string>",
    "name": "<string>",
    "created_at": "2023-11-07T05:31:56Z",
    "updated_at": "2023-11-07T05:31:56Z",
    "description": "<string>",
    "preview_url": "<string>",
    "language": "<string>",
    "accent": "<string>",
    "category": "<string>",
    "labels": {},
    "supported_models": [
      "<string>"
    ],
    "is_active": true
  },
  "stt_provider": "<string>",
  "stt_language": "<string>",
  "vad_provider": "<string>",
  "interruptions_enabled": true,
  "interruption_min_words": 123,
  "interruption_min_duration_ms": 123,
  "interruption_backoff_ms": 123,
  "interruption_sensitivity": 123,
  "interruption_final_transcript_grace_ms": 123,
  "min_endpoint_delay_ms": 123,
  "max_endpoint_delay_ms": 123,
  "preemptive_generation_enabled": true,
  "voicemail_detection_mode": "<string>",
  "voicemail_detection_timeout_ms": 123,
  "max_call_duration_ms": 123,
  "silence_timeout_ms": 123,
  "silence_reminder_count": 123,
  "silence_reminder_mode": "<string>",
  "silence_end_action": "<string>",
  "dtmf_enabled": true,
  "dtmf_termination_digit": "<string>",
  "dtmf_inter_digit_timeout_ms": 123,
  "dtmf_max_digits": 123,
  "dtmf_prefix": "<string>",
  "backchannel_enabled": true,
  "background_audio_volume": 123,
  "background_audio_loop": true,
  "background_audio_enabled": true,
  "noise_cancellation_enabled": true,
  "recording_enabled": true,
  "transcription_storage_enabled": true,
  "normalize_for_speech": true,
  "audio_in_sample_rate": 123,
  "audio_out_sample_rate": 123,
  "metrics_enabled": true,
  "usage_metrics_enabled": true,
  "language": "<string>",
  "multilingual_enabled": true,
  "created_at": "2023-11-07T05:31:56Z",
  "updated_at": "2023-11-07T05:31:56Z",
  "organization_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "team_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "voice_tuning": {},
  "stt_model": "<string>",
  "stt_provider_data": {},
  "tts_speed": 123,
  "tts_provider_data": {},
  "vad_provider_data": {},
  "local_vad_params": {},
  "turn_analyzer_params": {},
  "interruption_trigger_phrases": [
    "<string>"
  ],
  "interruption_hard_phrases": [
    "<string>"
  ],
  "hard_turn_timeout_ms": 123,
  "voicemail_detection_model": "<string>",
  "voicemail_message": "<string>",
  "end_call_phrases": [
    "<string>"
  ],
  "silence_reminder_message": "<string>",
  "silence_end_message": "<string>",
  "backchannel_frequency": 123,
  "pronunciation_overrides": {},
  "background_audio_preset": "<string>",
  "heartbeats_period_secs": 123,
  "idle_pipeline_timeout_ms": 123,
  "locale": "<string>",
  "multilingual_languages": [
    "<string>"
  ],
  "metadata_": {},
  "first_speaking_config": {
    "first_speaker": "agent",
    "mode": "static",
    "text": "<string>",
    "instructions": "<string>",
    "interruptible": true,
    "ai_disclosure_text": "<string>"
  },
  "warnings": [
    "<string>"
  ]
}

Authorizations

x-api-key
string
header
required

Path Parameters

config_id
string<uuid>
required

Body

application/json
voice_tuning
Voice Tuning · object
stt_provider
string | null
Maximum string length: 32
stt_model
string | null
Maximum string length: 64
stt_provider_data
Stt Provider Data · object
tts_speed
number | null
Required range: 0 <= x < 10
tts_provider_data
Tts Provider Data · object
vad_provider_data
Vad Provider Data · object
local_vad_params
LocalVADParams · object

Silero VAD tuning. Always applied for Deepgram Nova; ignored otherwise.

turn_analyzer_params
TurnAnalyzerParams · object

Smart-turn-v3 tuning. Always applied for Deepgram Nova; ignored otherwise.

interruptions_enabled
boolean | null
interruption_min_words
integer | null
Required range: 0 <= x <= 20
interruption_min_duration_ms
integer | null
Required range: 0 <= x <= 10000
interruption_backoff_ms
integer | null
Required range: 0 <= x <= 10000
interruption_trigger_phrases
string[] | null
Maximum array length: 50
interruption_hard_phrases
string[] | null
Maximum array length: 20
interruption_final_transcript_grace_ms
integer | null
Required range: 0 <= x <= 2000
voicemail_detection_mode
enum<string> | null
Available options:
off,
leave_message
voicemail_detection_timeout_ms
integer | null
Required range: 0 <= x <= 60000
voicemail_detection_model
string | null
Maximum string length: 64
voicemail_message
string | null
Maximum string length: 1000
max_call_duration_ms
integer | null
Required range: 1000 <= x <= 14400000
silence_timeout_ms
integer | null
Required range: 0 <= x <= 600000
silence_reminder_count
integer | null
Required range: 0 <= x <= 10
silence_reminder_mode
enum<string> | null
Available options:
static,
auto
silence_reminder_message
string | null
Maximum string length: 500
silence_end_action
enum<string> | null
Available options:
hangup_immediate,
speak_then_hangup
silence_end_message
string | null
Maximum string length: 500
dtmf_enabled
boolean | null
dtmf_termination_digit
string | null
Maximum string length: 1
dtmf_inter_digit_timeout_ms
integer | null
Required range: 250 <= x <= 60000
dtmf_max_digits
integer | null
Required range: 1 <= x <= 64
dtmf_prefix
string | null
Maximum string length: 32
pronunciation_overrides
Pronunciation Overrides · object
noise_cancellation_enabled
boolean | null
background_audio_enabled
boolean | null
background_audio_preset
enum<string> | null

Bundled CC0 ambience presets resolved by the voice worker.

String values MUST match the keys of _PRESET_FILES in src/communication/voice/agent/background_audio.py; a unit test (tests/voice/test_background_audio.py) fails CI if the two ever drift.

Available options:
office,
cafe,
city,
keyboard_typing,
keyboard_typing2
background_audio_volume
number | null
Required range: 0 <= x <= 1
background_audio_loop
boolean | null
language
string | null
Maximum string length: 16
locale
string | null
Maximum string length: 16
multilingual_enabled
boolean | null
multilingual_languages
string[] | null
Maximum array length: 50
first_speaker
enum<string> | null
Available options:
agent,
user
mode
enum<string> | null
Available options:
static,
dynamic
text
string | null
Maximum string length: 1000
instructions
string | null
Maximum string length: 2000
interruptible
boolean | null
ai_disclosure_text
string | null
Maximum string length: 500
voice_id
string<uuid> | null

Response

Successful Response

id
string<uuid>
required
voice_id
string<uuid>
required
voice
VoiceOut · object
required
stt_provider
string
required
stt_language
string
required
vad_provider
string
required
interruptions_enabled
boolean
required
interruption_min_words
integer
required
interruption_min_duration_ms
integer
required
interruption_backoff_ms
integer
required
interruption_sensitivity
number
required
interruption_final_transcript_grace_ms
integer
required
min_endpoint_delay_ms
integer
required
max_endpoint_delay_ms
integer
required
preemptive_generation_enabled
boolean
required
voicemail_detection_mode
string
required
voicemail_detection_timeout_ms
integer
required
max_call_duration_ms
integer
required
silence_timeout_ms
integer
required
silence_reminder_count
integer
required
silence_reminder_mode
string
required
silence_end_action
string
required
dtmf_enabled
boolean
required
dtmf_termination_digit
string
required
dtmf_inter_digit_timeout_ms
integer
required
dtmf_max_digits
integer
required
dtmf_prefix
string
required
backchannel_enabled
boolean
required
background_audio_volume
number
required
background_audio_loop
boolean
required
background_audio_enabled
boolean
required
noise_cancellation_enabled
boolean
required
recording_enabled
boolean
required
transcription_storage_enabled
boolean
required
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
language
string
required
multilingual_enabled
boolean
required
created_at
string<date-time>
required
updated_at
string<date-time>
required
organization_id
string<uuid> | null
agent_id
string<uuid> | null
team_id
string<uuid> | null
persona_id
string<uuid> | null
voice_tuning
Voice Tuning · object
stt_model
string | null
stt_provider_data
Stt Provider Data · object
tts_speed
number | null
tts_provider_data
Tts Provider Data · object
vad_provider_data
Vad Provider Data · object
local_vad_params
Local Vad Params · object
turn_analyzer_params
Turn Analyzer Params · object
interruption_trigger_phrases
string[]
interruption_hard_phrases
string[]
hard_turn_timeout_ms
integer | null
voicemail_detection_model
string | null
voicemail_message
string | null
end_call_phrases
string[]
silence_reminder_message
string | null
silence_end_message
string | null
backchannel_frequency
integer | null
pronunciation_overrides
Pronunciation Overrides · object
background_audio_preset
string | null
heartbeats_period_secs
integer | null
idle_pipeline_timeout_ms
integer | null
locale
string | null
multilingual_languages
string[]
metadata_
Metadata · object
first_speaking_config
FirstSpeakingConfig · object

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.
warnings
string[]