Webhook Response¶
Build call flow instructions using typed Pydantic verbs.
How It Works¶
When jambonz receives a call, it sends an HTTP POST to your webhook URL. You respond with a list of verbs that tell jambonz what to do.
from jambonz import JambonzResponse, Say, Hangup
# Your response is a list of verbs
verbs = [Say(text="Hello!"), Hangup()]
# Wrap in JambonzResponse for serialization
response = JambonzResponse(verbs)
response.model_dump()
# → [{"verb": "say", "text": "Hello!"}, {"verb": "hangup"}]
Available Verbs¶
Say¶
Text-to-speech:
Say(text="Hello world")
# With specific TTS vendor
Say(
text="Hola mundo",
synthesizer=Synthesizer(
vendor="elevenlabs",
language="es",
voice="pNInz6obpgDQGcFmaJgB",
label="elevenlabs_bookline",
),
)
Play¶
Play an audio file:
Gather¶
Collect speech or DTMF input:
Gather(
input=[Input.SPEECH, Input.DIGITS],
action_hook="/handle-input",
timeout=10,
num_digits=4,
recognizer=Recognizer(vendor="google", language="en-US"),
say=Say(text="Please say your account number"),
)
Pause¶
Wait:
Hangup¶
End the call:
Redirect¶
Transfer to a different webhook:
LLM¶
Connect to a conversational AI:
LLM(
vendor="elevenlabs",
auth=LLMAuth(agent_id="your-agent-id"),
llm_options={},
action_hook="/llm-complete",
tool_hook="/tool-call",
)
Dial¶
Dial out to a number:
Dial(
action_hook="/dial-status",
caller_id="+34931228497",
timeout=30,
target=[{"type": "phone", "number": "+34600000000"}],
)
Building Responses with Logic¶
from jambonz import JambonzResponse, Say, Gather, Hangup, Input
def handle_call(is_business_hours: bool) -> JambonzResponse:
verbs = [Say(text="Welcome to our service.")]
if is_business_hours:
verbs.append(
Gather(
input=[Input.SPEECH],
action_hook="/menu",
say=Say(text="How can I help you today?"),
)
)
else:
verbs.extend([
Say(text="We are currently closed. Please call back during business hours."),
Hangup(),
])
return JambonzResponse(verbs)
Serialization¶
The JambonzResponse automatically handles:
- Excludes null fields — jambonz rejects payloads with null values
- camelCase aliases —
action_hookbecomesactionHook - Enum serialization —
Input.SPEECHbecomes"speech"
response = JambonzResponse([
Gather(input=[Input.SPEECH], action_hook="/resp"),
])
response.model_dump()
# → [{"verb": "gather", "input": ["speech"], "actionHook": "/resp", "timeout": 10}]
# Note: no nulls, camelCase keys, enum as string
response.model_dump_json()
# → '[{"verb":"gather","input":["speech"],"actionHook":"/resp","timeout":10}]'
The Verb Type¶
All verbs are part of a discriminated union:
from jambonz import Verb
# Verb = Say | Play | Gather | Pause | Hangup | Redirect | LLM | Dial
# Discriminated on the "verb" field
This means Pydantic can automatically parse a verb dict into the correct type: