{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/api/v1/campaigns/{campaign_id}/brain-configuration":{"patch":{"tags":["campaign"],"summary":"Update Brain Configuration","description":"Save only the customer-editable Brain campaign configuration fields.","operationId":"update_brain_configuration_api_v1_campaigns__campaign_id__brain_configuration_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrainConfigurationUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Brain Configuration Api V1 Campaigns  Campaign Id  Brain Configuration Patch"}}}},"404":{"description":"Campaign not found"},"409":{"description":"Campaign configuration version conflict"},"422":{"description":"Invalid Brain configuration"}}}},"/api/v1/campaigns/{campaign_id}/configuration":{"put":{"tags":["campaign"],"summary":"Replace a campaign's configuration","description":"Replace a campaign's configuration through the one validated write path.\n\nAuthorize, validate, then write via the ``apply_campaign_config`` RPC, which\nstamps the write so the version trigger records who made it. Returns the id\nof the version the write minted, the stored configuration, and the\n``base_updated_at`` token to send back on the next conditional write.\n\nSupplying ``base_updated_at`` makes the write conditional: if the\nconfiguration moved since that token was issued, the write is refused with\n409 instead of overwriting the other edit. Omit it to write unconditionally.\n\nWhat this endpoint does NOT do:\n  * No partial merge. The body's ``configuration`` REPLACES the stored one\n    outright, matching how the product saves today.\n  * No experiments consent flow. Consent arguments are always sent empty, so\n    a write that would disturb a running experiment is refused by the engine\n    and returned as 409 with the engine's message; that caller has to go\n    through the consent-aware path instead.\n  * No field stripping. Keys CampaignConfig does not declare are stored\n    verbatim and logged, never dropped.\n\n``request`` is the published contract and the first validation gate;\n``http_request`` supplies what actually gets written. Parsing the body into\nCampaignConfig would silently drop every undeclared key (the model is\n``extra=\"ignore\"``, and its nested models are too, so no amount of\n``extra=\"allow\"`` at the top level would make the parsed object faithful),\nso the raw JSON object is what reaches storage.\n\nDecoded from the cached BYTES, not from ``http_request.json()``: Starlette\ncaches the decoded object and hands the SAME one to FastAPI's parse, and\nseveral config validators rewrite what they are given in place\n(TTSConfig._resolve_params_by_provider replaces params with a model\ninstance and can inject a default model). Reading .json() would therefore\nreturn a body the parse had already corrupted. Re-decoding the bytes costs\none json parse and is the only form that is guaranteed pristine.","operationId":"apply_campaign_configuration_api_v1_campaigns__campaign_id__configuration_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignConfigurationUpdateRequest"}}}},"responses":{"200":{"description":"Configuration written; a new version was minted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignConfigurationResponse"}}}},"403":{"description":"User is not authorized to edit this campaign"},"404":{"description":"Campaign not found"},"409":{"description":"The configuration engine refused the write: a lost version race (stale base_updated_at) or a change that would disturb a running experiment. The detail carries the engine's own message."},"422":{"description":"Invalid campaign configuration"}}}},"/api/v1/campaigns/{campaign_id}/voicemail/reconfigure":{"post":{"tags":["campaign"],"summary":"Reconfigure Voicemail","description":"Generate a new personalized voicemail template and wav for a campaign.","operationId":"reconfigure_voicemail_api_v1_campaigns__campaign_id__voicemail_reconfigure_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/VoicemailReconfigureRequest"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input (bad campaign ID, voicemail disabled, no contacts, missing phone/prompt data, or empty generated voicemail text)"},"404":{"description":"Campaign or configuration not found"},"500":{"description":"Internal failure (script generation, or storage)"},"501":{"description":"Configured TTS provider does not support voicemail audio generation"},"502":{"description":"ElevenLabs TTS upstream failure"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/contacts/import/resolve":{"post":{"tags":["contact-import"],"summary":"Resolve Import Contacts","description":"Create or resolve CSV-imported contacts using backend-owned TCPA logic.\n\nThe frontend remains responsible for CSV preview/campaign linking. This\nendpoint owns canonical contact creation and the table-backed TCPA mapping.","operationId":"resolve_import_contacts_api_v1_contacts_import_resolve_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/cpu-stats":{"get":{"tags":["cpu-stats"],"summary":"Get Cpu Stats","description":"Get CPU pool statistics.","operationId":"get_cpu_stats_api_v1_cpu_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/full-cpu-stats":{"get":{"tags":["cpu-stats"],"summary":"Get Full Cpu Stats","description":"Get full CPU pool statistics across all logical cores.","operationId":"get_full_cpu_stats_api_v1_full_cpu_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/flow-graphs":{"get":{"tags":["flow-graphs"],"summary":"List Flow Graphs","operationId":"list_flow_graphs_api_v1_flow_graphs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"organization_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Organization Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["flow-graphs"],"summary":"Create Flow Graph","operationId":"create_flow_graph_api_v1_flow_graphs_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateFlowGraphRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/flow-graphs/import":{"post":{"tags":["flow-graphs"],"summary":"Import Flow Graph","operationId":"import_flow_graph_api_v1_flow_graphs_import_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportFlowGraphRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/flow-graphs/{graph_id}":{"get":{"tags":["flow-graphs"],"summary":"Get Flow Graph","operationId":"get_flow_graph_api_v1_flow_graphs__graph_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"graph_id","in":"path","required":true,"schema":{"type":"string","title":"Graph Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["flow-graphs"],"summary":"Archive Flow Graph","operationId":"archive_flow_graph_api_v1_flow_graphs__graph_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"graph_id","in":"path","required":true,"schema":{"type":"string","title":"Graph Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/flow-graphs/{graph_id}/draft":{"patch":{"tags":["flow-graphs"],"summary":"Update Flow Graph Draft","operationId":"update_flow_graph_draft_api_v1_flow_graphs__graph_id__draft_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"graph_id","in":"path","required":true,"schema":{"type":"string","title":"Graph Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDraftRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/flow-graphs/{graph_id}/validate":{"post":{"tags":["flow-graphs"],"summary":"Validate Flow Graph","operationId":"validate_flow_graph_api_v1_flow_graphs__graph_id__validate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"graph_id","in":"path","required":true,"schema":{"type":"string","title":"Graph Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/flow-graphs/{graph_id}/publish":{"post":{"tags":["flow-graphs"],"summary":"Publish Flow Graph","operationId":"publish_flow_graph_api_v1_flow_graphs__graph_id__publish_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"graph_id","in":"path","required":true,"schema":{"type":"string","title":"Graph Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/flow-bindings":{"get":{"tags":["flow-graphs"],"summary":"Get Campaign Flow Bindings","operationId":"get_campaign_flow_bindings_api_v1_campaigns__campaign_id__flow_bindings_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["flow-graphs"],"summary":"Update Campaign Flow Bindings","operationId":"update_campaign_flow_bindings_api_v1_campaigns__campaign_id__flow_bindings_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCampaignBindingsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"FlowGraph enablement fields do not match"}}}},"/api/v1/campaigns/{campaign_id}/flow-bindings/mint":{"post":{"tags":["flow-graphs"],"summary":"Mint Campaign Flow Template","operationId":"mint_campaign_flow_template_api_v1_campaigns__campaign_id__flow_bindings_mint_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MintCampaignTemplateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/flow-graphs/materialize":{"post":{"tags":["flow-graphs"],"summary":"Materialize Campaign Flow Graph","operationId":"materialize_campaign_flow_graph_api_v1_campaigns__campaign_id__flow_graphs_materialize_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaterializeCampaignSourceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/flow-graphs/preview":{"get":{"tags":["flow-graphs"],"summary":"Preview Campaign Flow Graph","operationId":"preview_campaign_flow_graph_api_v1_campaigns__campaign_id__flow_graphs_preview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}},{"name":"source_id","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/flow-graphs/capabilities":{"get":{"tags":["flow-graphs"],"summary":"Campaign Flow Graph Capabilities","description":"Capability catalog annotated with what this campaign has enabled.\n\nSingle source of truth for the editor's tool/action lists (replaces the\nfrontend's hardcoded options).","operationId":"campaign_flow_graph_capabilities_api_v1_campaigns__campaign_id__flow_graphs_capabilities_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/interactions/{interaction_id}/retag-classifications":{"post":{"tags":["interaction-tags"],"summary":"Retag Classifications","description":"Re-run named classification groups on one interaction and append tags.\n\nAn interaction that was not an actual conversation returns\n``not_eligible`` for every requested group and costs nothing. See\nELIGIBILITY in the module docstring.\n\nOnly ``interactions.tags`` is written, and only by appending. A group that\nalready carries a tag is always skipped, before the model call, and there\nis no way to override that. With ``dry_run`` (the default) the model still\nruns, so the caller can see the option and confidence it would have\nstored, but nothing is persisted.","operationId":"retag_classifications_api_v1_interactions__interaction_id__retag_classifications_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"interaction_id","in":"path","required":true,"schema":{"type":"string","title":"Interaction Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetagRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetagResponse"}}}},"400":{"description":"Invalid interaction ID"},"404":{"description":"Interaction not found"},"500":{"description":"Re-tagging failed"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/live_lead":{"post":{"tags":["live-lead"],"summary":"Live Lead","description":"Process a live lead request. Accepts both valid and malformed requests.\n\nFor valid requests: Process normally (create/update/remove contacts based on LeadStatus).\nFor malformed requests: Create a rejected contact with the available data.","operationId":"live_lead_api_v1_live_lead_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/schedule-uploaded-contacts":{"post":{"tags":["scheduling"],"summary":"Schedule Uploaded Contacts","description":"Trigger OTTR scheduling for all contacts in awaiting_scheduling status.\n\nThis endpoint processes all contacts across all campaigns that are in\n'awaiting_scheduling' status. It uses Thompson sampling to assign optimal\nnext_follow_up_date_time values and transitions contacts to 'awaiting_contact'.\n\nThe scheduling process:\n1. Fetches contacts in batches of 1000\n2. Groups by campaign_id and timezone\n3. Gets optimal hour distribution via Thompson sampling\n4. Samples a specific time for each contact\n5. Updates contacts to awaiting_contact status with scheduled time\n\nReturns:\n    ScheduleUploadResponse with counts and processing time","operationId":"schedule_uploaded_contacts_api_v1_schedule_uploaded_contacts_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleUploadResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ottr/resolve-touchpoint":{"post":{"tags":["ottr"],"summary":"Resolve Touchpoint","description":"Boundary guard: this endpoint must never return a 5xx.\n\n``_resolve_touchpoint`` already refuses on every failure it anticipates.\nThis exists for the ones it does not. Staging found two -- an unknown\ncampaign and an inverted range -- and both were 500s reaching a Brain run\nthat had already paid for classification. The specific causes are fixed;\nthis makes the CLASS of failure impossible rather than fixing them one at\na time.\n\nDeliberately a wrapper rather than another nested try: the resolver is\nalready at the edge of the cognitive-complexity limit, and a guard that\nmakes the guarded function harder to read is a bad trade.\n\nHTTPException passes through untouched -- a 404 for an unknown campaign is\na deliberate answer, not an escaped error.","operationId":"resolve_touchpoint_api_v1_ottr_resolve_touchpoint_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveTouchpointRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveTouchpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/schemas":{"get":{"tags":["schemas"],"summary":"Get Schemas","description":"Return the JSON Schema registry for the published models.","operationId":"get_schemas_api_v1_schemas_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/campaigns/{campaign_id}/derive-stt-vocabulary":{"post":{"tags":["stt-vocabulary"],"summary":"Derive Stt Vocabulary","description":"Extract and atomically replace publish-owned STT vocabulary entries.\n\n``auto_extract=false`` returns a successful no-op. Otherwise only\npublish_extraction entries are replaced; drift_feedback promotions and\nstaff-owned manual_terms / suppressed_terms / enabled / auto_extract /\nauto_promote are preserved. Injection at call spawn stays off until both\nSTT_VOCABULARY_ENABLED and the row's enabled flag are on; auto-promotion\nis gated separately by auto_promote.","operationId":"derive_stt_vocabulary_api_v1_campaigns__campaign_id__derive_stt_vocabulary_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid campaign ID"},"404":{"description":"Campaign not found"},"500":{"description":"Extraction or persistence failure"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/outbound_call":{"post":{"tags":["calls"],"summary":"Outbound Call","description":"Handle outbound call request using Daily.co PSTN infrastructure.\n\nArgs:\n    request: Outbound call details\n    daily_helper: Daily.co helper dependency\n    current_user: Authenticated user ID","operationId":"outbound_call_api_v1_outbound_call_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutboundCallRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/twilio_sip_webhook":{"get":{"tags":["twilio"],"summary":"Twilio Sip Webhook","description":"Handle Twilio SIP Domain webhook for call forwarding.\n\nThis endpoint processes incoming SIP calls from Twilio and generates\nTwiML instructions to forward the call to the appropriate phone number.\nThe SIP URI format is expected to be: sip:+1DESTINATION,+1PURCHASEDNUMBER@twilio-interconnect.daily.co","operationId":"twilio_sip_webhook_api_v1_twilio_sip_webhook_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid 'To' address format"}}}},"/api/v1/twilio_payment_silence.wav":{"get":{"tags":["twilio-payments"],"summary":"Twilio Payment Silence","description":"Silent ringback for the payment-return Connect.\n\nVonage plays a generated ring tone while a ``connect`` dials the room's\nSIP endpoint; pointing ``ringbackTone`` here makes the brief return\ntransfer silent instead. Named under the ``twilio_payment_`` prefix so\npayment-webhook proxies (e.g. the devbox Caddy allowlist) route it\nwithout extra rules.","operationId":"twilio_payment_silence_api_v1_twilio_payment_silence_wav_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/twilio_payment_audio/{name}.mp3":{"get":{"tags":["twilio-payments"],"summary":"Twilio Payment Audio","description":"Serve a whitelisted agent-voice payment prompt to <Play>/Stream.\n\nThe optional ``p``/``v``/``m`` query params select the campaign voice the\nbot registered at park time; absent params fall back to the env voice.\nOnly whitelisted prompt names and authorized (registered or env) voices\nare ever rendered, so caller-controlled input can't reach the TTS APIs.","operationId":"twilio_payment_audio_api_v1_twilio_payment_audio__name__mp3_get","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/twilio_payment_voice":{"post":{"tags":["twilio-payments"],"summary":"Twilio Payment Voice","description":"Voice webhook for the PCI payment number used by the payment transfer.\n\nReturns ``<Pay>`` TwiML so the caller keys their card via DTMF directly into\nTwilio's PCI environment (Shuttle Pay Connector). The PAN/CVC are captured\nentirely on the Twilio leg and never reach joma-api. The caller's return to\nthe bot's room is driven by the Vonage NCCO, not by Twilio.","operationId":"twilio_payment_voice_api_v1_twilio_payment_voice_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/twilio_payment_result":{"post":{"tags":["twilio-payments"],"summary":"Twilio Payment Result","description":"``<Pay>`` action callback. Confirm + hang up; the caller's return to the\nbot is driven by the Vonage NCCO action sequence, not by Twilio.","operationId":"twilio_payment_result_api_v1_twilio_payment_result_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/inbound_call_twilio":{"post":{"tags":["inbound-call-twilio"],"summary":"Inbound Call Twilio","description":"Handle inbound Twilio call webhook.\n\nConverts Twilio form data to the params format expected by the shared\ninbound_call() function, then converts the NCCO response to TwiML.\n\nArgs:\n    request: Inbound call details from Twilio\n    daily_helper: Daily.co helper dependency\n    process_manager: Process manager dependency\n    supabase_service: Supabase service dependency","operationId":"inbound_call_twilio_api_v1_inbound_call_twilio_post","responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/vonage_sip_webhook":{"get":{"tags":["vonage"],"summary":"Vonage Sip Webhook","description":"Handle Vonage SIP Domain webhook for inbound and outbound calls.\n\nThis endpoint processes incoming SIP calls from Vonage and generates\nNCCO object to forward the call to the appropriate phone number.\nCustome query params can be added to the SIP URI. Those will be prepended with \"SipHeader_\" by Vonage server side.\nThe SIP URI format is expected to be: sip:+1DESTINATION@outrival.sip-us.vonage.com?SipHeader_X-from=PURCHASEDNUMBER&SipHeader_X-joma_auth=JOMA_VONAGE_AUTH","operationId":"vonage_sip_webhook_api_v1_vonage_sip_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["vonage"],"summary":"Vonage Sip Webhook","description":"Handle Vonage SIP Domain webhook for inbound and outbound calls.\n\nThis endpoint processes incoming SIP calls from Vonage and generates\nNCCO object to forward the call to the appropriate phone number.\nCustome query params can be added to the SIP URI. Those will be prepended with \"SipHeader_\" by Vonage server side.\nThe SIP URI format is expected to be: sip:+1DESTINATION@outrival.sip-us.vonage.com?SipHeader_X-from=PURCHASEDNUMBER&SipHeader_X-joma_auth=JOMA_VONAGE_AUTH","operationId":"vonage_sip_webhook_api_v1_vonage_sip_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/vonage_event_webhook":{"get":{"tags":["vonage"],"summary":"Vonage Event Webhook","operationId":"vonage_event_webhook_api_v1_vonage_event_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["vonage"],"summary":"Vonage Event Webhook","operationId":"vonage_event_webhook_api_v1_vonage_event_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/vonage_recording_webhook":{"get":{"tags":["vonage"],"summary":"Vonage Recording Webhook","operationId":"vonage_recording_webhook_api_v1_vonage_recording_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["vonage"],"summary":"Vonage Recording Webhook","operationId":"vonage_recording_webhook_api_v1_vonage_recording_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/vonage_payment_event":{"get":{"tags":["vonage-payments"],"summary":"Vonage Payment Event","description":"Pay-leg status events for a payment transfer. Recalls the parked caller.","operationId":"vonage_payment_event_api_v1_vonage_payment_event_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["vonage-payments"],"summary":"Vonage Payment Event","description":"Pay-leg status events for a payment transfer. Recalls the parked caller.","operationId":"vonage_payment_event_api_v1_vonage_payment_event_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/vonage_test_scenario_answer":{"get":{"tags":["vonage-test-scenario"],"summary":"Vonage Test Scenario Answer","description":"Answer URL: serve the NCCO for the scenario mapped to the dialed number.","operationId":"vonage_test_scenario_answer_api_v1_vonage_test_scenario_answer_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["vonage-test-scenario"],"summary":"Vonage Test Scenario Answer","description":"Answer URL: serve the NCCO for the scenario mapped to the dialed number.","operationId":"vonage_test_scenario_answer_api_v1_vonage_test_scenario_answer_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/vonage_test_scenario_event":{"get":{"tags":["vonage-test-scenario"],"summary":"Vonage Test Scenario Event","description":"Event URL: log-only observability for test scenario call legs.","operationId":"vonage_test_scenario_event_api_v1_vonage_test_scenario_event_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["vonage-test-scenario"],"summary":"Vonage Test Scenario Event","description":"Event URL: log-only observability for test scenario call legs.","operationId":"vonage_test_scenario_event_api_v1_vonage_test_scenario_event_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/":{"get":{"summary":"Read Root","operationId":"read_root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/googlef4768bafb43084e7.html":{"get":{"summary":"Google Site Verification","operationId":"google_site_verification_googlef4768bafb43084e7_html_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health Check","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"503":{"description":"Scratch storage or Redis write probe failed"}}}}},"components":{"schemas":{"AfterHoursAction":{"properties":{"action":{"$ref":"#/components/schemas/AfterHoursActionType"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"metadata":{"anyOf":[{"$ref":"#/components/schemas/Metadata"},{"type":"null"}]}},"type":"object","required":["action"],"title":"AfterHoursAction"},"AfterHoursActionType":{"type":"string","enum":["forward","sms"],"title":"AfterHoursActionType"},"BotConfig":{"properties":{"allow_interruptions":{"type":"boolean","title":"Allow Interruptions","default":true},"answer_delay":{"type":"number","title":"Answer Delay","default":3.0},"idle_timeout_secs":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Idle Timeout Secs"}},"type":"object","title":"BotConfig"},"BrainConfigurationPatch":{"properties":{"brain_live":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Brain Live"},"insights":{"anyOf":[{"$ref":"#/components/schemas/BrainInsightsConfigurationPatch"},{"type":"null"}]}},"additionalProperties":false,"type":"object","title":"BrainConfigurationPatch"},"BrainConfigurationUpdateRequest":{"properties":{"configuration":{"$ref":"#/components/schemas/BrainConfigurationPatch"},"base_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Base Updated At"}},"additionalProperties":false,"type":"object","required":["configuration"],"title":"BrainConfigurationUpdateRequest"},"BrainInsightsConfigurationPatch":{"properties":{"custom_insights":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Custom Insights"}},"additionalProperties":false,"type":"object","title":"BrainInsightsConfigurationPatch"},"CadenceContextConfig":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/CadenceContextField"},"type":"array","title":"Fields"}},"type":"object","title":"CadenceContextConfig"},"CadenceContextField":{"properties":{"source":{"type":"string","enum":["exportable_fields","personalization_fields"],"title":"Source"},"path":{"type":"string","title":"Path","description":"Exact key to read from the configured contact field map"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label","description":"Optional prompt label; defaults to path"}},"type":"object","required":["source","path"],"title":"CadenceContextField"},"CallerIdRule":{"properties":{"number":{"type":"string","title":"Number"},"dial_pattern":{"anyOf":[{"$ref":"#/components/schemas/DialPattern"},{"type":"null"}]},"dials":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Dials"}},"type":"object","required":["number"],"title":"CallerIdRule","description":"Dial-aware caller ID override rule for outbound campaigns."},"CampaignConfig":{"properties":{"scripts":{"anyOf":[{"$ref":"#/components/schemas/LLMScripts"},{"type":"null"}]},"vad":{"anyOf":[{"$ref":"#/components/schemas/VadConfig"},{"type":"null"}]},"tts":{"anyOf":[{"$ref":"#/components/schemas/TTSConfig"},{"type":"null"}]},"llm":{"anyOf":[{"$ref":"#/components/schemas/LLMConfig"},{"type":"null"}]},"hangup":{"anyOf":[{"$ref":"#/components/schemas/HangupConfig"},{"type":"null"}]},"insights":{"anyOf":[{"$ref":"#/components/schemas/InsightsConfig"},{"type":"null"}]},"bot":{"anyOf":[{"$ref":"#/components/schemas/BotConfig"},{"type":"null"}]},"reattempt":{"anyOf":[{"$ref":"#/components/schemas/ReattemptConfig"},{"type":"null"}]},"transfer":{"anyOf":[{"$ref":"#/components/schemas/TransferConfig"},{"type":"null"}]},"hours_of_operation":{"anyOf":[{"$ref":"#/components/schemas/CampaignHoursOfOperation"},{"type":"null"}]},"sip_config":{"anyOf":[{"$ref":"#/components/schemas/SipConfig"},{"type":"null"}]},"inbound_config":{"anyOf":[{"$ref":"#/components/schemas/InboundConfig"},{"type":"null"}]},"outbound_config":{"anyOf":[{"$ref":"#/components/schemas/OutboundConfig"},{"type":"null"}]},"always_forward_action":{"anyOf":[{"$ref":"#/components/schemas/AfterHoursAction"},{"type":"null"}]},"mid_call_actions":{"anyOf":[{"items":{"$ref":"#/components/schemas/MidCallAction"},"type":"array"},{"type":"null"}],"title":"Mid Call Actions"},"context_injection":{"anyOf":[{"$ref":"#/components/schemas/ContextInjectionConfig"},{"type":"null"}]},"context_injection_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Context Injection Enabled","default":false},"verification_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Verification Enabled","default":false},"preferred_language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Language"},"pipecat_flows_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pipecat Flows Enabled"},"flow_graph_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Flow Graph Id"},"flow_graph_bindings":{"anyOf":[{"$ref":"#/components/schemas/DirectionalFlowGraphBindings"},{"type":"null"}]},"flow_graphs":{"anyOf":[{"$ref":"#/components/schemas/FlowGraphsConfig"},{"type":"null"}]},"context_fetch_mode":{"anyOf":[{"$ref":"#/components/schemas/ContextFetchMode"},{"type":"null"}]},"post_processing":{"anyOf":[{"$ref":"#/components/schemas/PostProcessingConfig"},{"type":"null"}]},"tag_definitions":{"anyOf":[{"$ref":"#/components/schemas/TagDefinitions"},{"type":"null"}]},"success_criteria":{"anyOf":[{"$ref":"#/components/schemas/SuccessCriteriaConfig"},{"type":"null"}]},"use_case_template_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Use Case Template Id"},"outcome_metrics":{"anyOf":[{"items":{"$ref":"#/components/schemas/OutcomeMetricRule"},"type":"array"},{"type":"null"}],"title":"Outcome Metrics"},"outcome_metrics_exclude_zero_dials":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Outcome Metrics Exclude Zero Dials"},"brain_live":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Brain Live","default":false},"reporting_library":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Reporting Library"},"action_detection":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Action Detection"}},"type":"object","title":"CampaignConfig"},"CampaignConfigurationResponse":{"properties":{"campaign_id":{"type":"string","title":"Campaign Id","description":"The campaign that was written."},"version_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version Id","description":"Id of the campaign version this write minted."},"configuration":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Configuration","description":"The configuration as now stored, including undeclared keys."},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At","description":"The campaign row's updated_at after the write."},"base_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Base Updated At","description":"Token to send as base_updated_at on the next conditional write. Advances only when the configuration really changes — do not derive it from updated_at, which moves on any column."}},"type":"object","required":["campaign_id"],"title":"CampaignConfigurationResponse","description":"What a successful configuration write returns.\n\n``configuration`` is an open mapping ON PURPOSE. Typing it as CampaignConfig\nwould make FastAPI's response filtering strip undeclared keys back out of the\nresponse, so a client could not tell what is actually stored. The request\nside is typed for the contract; this side reports storage verbatim."},"CampaignConfigurationUpdateRequest":{"properties":{"configuration":{"$ref":"#/components/schemas/CampaignConfig","description":"The complete campaign configuration. Replaces the stored one outright — this is not a partial merge. Keys not declared below are accepted and stored verbatim rather than rejected or dropped."},"base_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Base Updated At","description":"Compare-and-set token from a previous response's base_updated_at. When supplied the write is refused with 409 if the configuration changed since. Omit to write unconditionally."}},"additionalProperties":false,"type":"object","required":["configuration"],"title":"CampaignConfigurationUpdateRequest","description":"Envelope for a whole-configuration replacement.\n\n``extra=\"forbid\"`` applies to the envelope ONLY. ``configuration`` is typed\nas CampaignConfig so the full config schema is published in the OpenAPI spec\nand the frontend can generate types from it — but CampaignConfig is\n``extra=\"ignore\"``, so parsing it DROPS every undeclared key. This model is\ntherefore the contract and the first validation gate, never the source of\nwhat gets stored: the handler reads the raw body and writes that instead."},"CampaignHoursOfOperation":{"properties":{"days":{"$ref":"#/components/schemas/DaysSchedule"},"holiday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]},"after_hours_action":{"anyOf":[{"$ref":"#/components/schemas/AfterHoursAction"},{"type":"null"}]},"timezone":{"type":"string","title":"Timezone","default":"America/New_York"}},"type":"object","title":"CampaignHoursOfOperation"},"CartesiaEmotion":{"type":"string","enum":["neutral","angry","excited","content","sad","scared","happy","enthusiastic","elated","euphoric","triumphant","amazed","surprised","flirtatious","joking/comedic","curious","peaceful","serene","calm","grateful","affectionate","trust","sympathetic","anticipation","mysterious","mad","outraged","frustrated","agitated","threatened","disgusted","contempt","envious","sarcastic","ironic","dejected","melancholic","disappointed","hurt","guilty","bored","tired","rejected","nostalgic","wistful","apologetic","hesitant","insecure","confused","resigned","anxious","panicked","alarmed","proud","confident","distant","skeptical","contemplative","determined"],"title":"CartesiaEmotion","description":"Emotions supported by Cartesia Sonic-3.\n\nMirrors ``pipecat.services.cartesia.tts.CartesiaEmotion`` so that the\nfrontend can render a constrained dropdown and we validate inputs\nat the API boundary."},"CartesiaLanguage":{"type":"string","enum":["en","es"],"title":"CartesiaLanguage","description":"Languages exposed to the frontend for Cartesia. Extend as we broaden coverage."},"CartesiaTTSParams":{"properties":{"language":{"$ref":"#/components/schemas/CartesiaLanguage","default":"en"},"speed":{"anyOf":[{"type":"number","maximum":1.5,"minimum":0.6},{"type":"null"}],"title":"Speed"},"volume":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.5},{"type":"null"}],"title":"Volume"},"emotion":{"anyOf":[{"$ref":"#/components/schemas/CartesiaEmotion"},{"type":"null"}]},"pronunciation_dict_id":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Pronunciation Dict Id"}},"type":"object","title":"CartesiaTTSParams","description":"Runtime params for Cartesia Sonic TTS.\n\nRanges come from Cartesia's ``GenerationConfig`` (volume [0.5, 2.0],\nspeed [0.6, 1.5]). ``emotion`` is constrained to the supported set and\n``language`` is currently limited to English and Spanish until we have\ndemand (and localized scripts) for more.\n\n``pronunciation_dict_id`` is an opaque string returned by Cartesia's\n``POST /pronunciation-dicts`` endpoint (no fixed format) — it's stored\nas-is and forwarded to Cartesia on every TTS request."},"ContactImportItem":{"properties":{"row_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Row Id"},"first_name":{"type":"string","title":"First Name"},"last_name":{"type":"string","title":"Last Name"},"phone_number":{"type":"string","title":"Phone Number"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"preferred_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preferred Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"zip_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip Code"},"county":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"County"},"personalization_fields":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Personalization Fields"},"exportable_fields":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Exportable Fields"}},"type":"object","required":["first_name","last_name","phone_number"],"title":"ContactImportItem"},"ContactImportRequest":{"properties":{"campaign_id":{"type":"string","title":"Campaign Id"},"contacts":{"items":{"$ref":"#/components/schemas/ContactImportItem"},"type":"array","maxItems":500,"minItems":1,"title":"Contacts"},"conservative_override_window_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conservative Override Window Code"}},"type":"object","required":["campaign_id","contacts"],"title":"ContactImportRequest"},"ContactImportResponse":{"properties":{"total":{"type":"integer","title":"Total"},"created":{"type":"integer","title":"Created"},"existing":{"type":"integer","title":"Existing"},"updated_existing_tcpa":{"type":"integer","title":"Updated Existing Tcpa"},"failed":{"type":"integer","title":"Failed"},"contacts":{"items":{"$ref":"#/components/schemas/ContactImportResult"},"type":"array","title":"Contacts"}},"type":"object","required":["total","created","existing","updated_existing_tcpa","failed","contacts"],"title":"ContactImportResponse"},"ContactImportResult":{"properties":{"row_id":{"type":"string","title":"Row Id"},"phone_number":{"type":"string","title":"Phone Number"},"contact_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Id"},"status":{"type":"string","enum":["created","existing","existing_tcpa_updated","failed"],"title":"Status"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"time_zone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time Zone"},"tcpa_call_window_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tcpa Call Window Id"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["row_id","phone_number","status"],"title":"ContactImportResult"},"ContextFetchMode":{"type":"string","enum":["query","prefetch","disabled"],"title":"ContextFetchMode"},"ContextInjectionConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"include_verification":{"type":"boolean","title":"Include Verification","default":false},"include_history":{"type":"boolean","title":"Include History","default":true},"include_crm":{"type":"boolean","title":"Include Crm","default":true}},"type":"object","title":"ContextInjectionConfig","description":"Granular control over what context is injected into the LLM."},"CreateFlowGraphRequest":{"properties":{"organization_id":{"type":"string","title":"Organization Id"},"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"interaction_type":{"type":"string","title":"Interaction Type","default":"inbound"},"source":{"type":"string","title":"Source","default":"blank"},"template_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Id"}},"type":"object","required":["organization_id","name"],"title":"CreateFlowGraphRequest"},"CustomInsight":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Definition"},"maps_to_status":{"anyOf":[{"$ref":"#/components/schemas/CustomInsightStatus"},{"type":"string"},{"type":"null"}],"title":"Maps To Status"}},"type":"object","title":"CustomInsight","description":"READ-path shape of one stored customer-tier insight definition.\n\nEvery field is ``Optional`` and carries no validator on purpose.\n``CampaignConfig`` is constructed on every campaign read across prod, so\nthis model must be able to represent whatever is already in the jsonb.\nThe business rules (non-empty bounded name/definition, platform-name\ncollision, ``maps_to_status`` allowlist, uniqueness, cap) belong to the\nwrite path — see ``CustomerInsight`` and ``validate_custom_insights``.\n\n``maps_to_status`` is ``CustomInsightStatus | str`` rather than the bare\nenum so an unrecognised stored status is preserved verbatim instead of\nraising; the enum is published so joma-web still gets the vocabulary."},"CustomInsightStatus":{"type":"string","enum":["completed","awaiting_followup","awaiting_reply","awaiting_reattempt"],"title":"CustomInsightStatus","description":"Contact statuses a customer-created insight may map an interaction into.\n\nMirrors ``ALLOWED_CUSTOM_INSIGHT_STATUSES`` (defined further down, after\n``CampaignContactStatus``); the two are pinned together by a test. Declared\nhere because ``CustomInsight`` needs it and ``InsightsConfig`` needs\n``CustomInsight``."},"DaySchedule":{"properties":{"open":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Open"},"close":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close"}},"type":"object","title":"DaySchedule"},"DaysSchedule":{"properties":{"Monday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]},"Tuesday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]},"Wednesday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]},"Thursday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]},"Friday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]},"Saturday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]},"Sunday":{"anyOf":[{"$ref":"#/components/schemas/DaySchedule"},{"type":"null"}]}},"type":"object","title":"DaysSchedule"},"DialPattern":{"type":"string","enum":["all","odd","even","specific"],"title":"DialPattern"},"DirectionalFlowGraphBindings":{"properties":{"inbound":{"anyOf":[{"$ref":"#/components/schemas/FlowGraphVersionBinding"},{"type":"null"}]},"outbound":{"anyOf":[{"$ref":"#/components/schemas/FlowGraphVersionBinding"},{"type":"null"}]}},"type":"object","title":"DirectionalFlowGraphBindings"},"DirectionalFlowGraphSelectors":{"properties":{"inbound":{"anyOf":[{"$ref":"#/components/schemas/RuntimeFlowGraphSelector"},{"$ref":"#/components/schemas/PublishedFlowGraphVersionSelector"},{"$ref":"#/components/schemas/EmptyFlowGraphSelector"},{"type":"null"}],"title":"Inbound"},"outbound":{"anyOf":[{"$ref":"#/components/schemas/RuntimeFlowGraphSelector"},{"$ref":"#/components/schemas/PublishedFlowGraphVersionSelector"},{"$ref":"#/components/schemas/EmptyFlowGraphSelector"},{"type":"null"}],"title":"Outbound"}},"type":"object","title":"DirectionalFlowGraphSelectors"},"ElevenLabsTTSParams":{"properties":{"stability":{"type":"number","title":"Stability","default":0.9},"similarity_boost":{"type":"number","title":"Similarity Boost","default":1.0},"style":{"type":"number","title":"Style","default":1.0},"use_speaker_boost":{"type":"boolean","title":"Use Speaker Boost","default":false},"language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language","default":"en"},"speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Speed"},"auto_mode":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Mode","default":true},"enable_ssml_parsing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Ssml Parsing"}},"type":"object","title":"ElevenLabsTTSParams"},"EmptyFlowGraphSelector":{"properties":{"kind":{"type":"string","const":"none","title":"Kind","default":"none"}},"type":"object","title":"EmptyFlowGraphSelector"},"FlowGraphVersionBinding":{"properties":{"graph_id":{"type":"string","title":"Graph Id"},"version_id":{"type":"string","title":"Version Id"},"version_hash":{"type":"string","title":"Version Hash"},"graph_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Graph Name"},"source_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Id"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"},"published_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Published At"}},"type":"object","required":["graph_id","version_id","version_hash"],"title":"FlowGraphVersionBinding"},"FlowGraphsConfig":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"by_direction":{"anyOf":[{"$ref":"#/components/schemas/DirectionalFlowGraphSelectors"},{"type":"null"}]}},"type":"object","title":"FlowGraphsConfig"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HangupConfig":{"properties":{"call_timeout":{"type":"integer","title":"Call Timeout","default":30},"hangup_delay":{"type":"integer","title":"Hangup Delay","default":5}},"type":"object","title":"HangupConfig"},"ImportFlowGraphRequest":{"properties":{"organization_id":{"type":"string","title":"Organization Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"}},"type":"object","required":["organization_id","payload"],"title":"ImportFlowGraphRequest"},"InboundConfig":{"properties":{},"type":"object","title":"InboundConfig","description":"Configuration specific to inbound campaigns."},"InsightsConfig":{"properties":{"insights":{"items":{"type":"string"},"type":"array","title":"Insights","default":["SUCCESS_RESPONSE","VOICEMAIL_LEFT","VOICEMAIL_BOX_FULL","LINE_BUSY","CALL_FOLLOWUP_REQUESTED","SMS_FOLLOWUP_REQUESTED","DNC_REQUEST","UNSUBSCRIBE_REQUEST","NOT_INTERESTED","HANGUP","WRONG_NUMBER","LANGUAGE_BARRIER"]},"success_response_definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Response Definition"},"custom_insights":{"anyOf":[{"items":{"$ref":"#/components/schemas/CustomInsight"},"type":"array"},{"type":"null"}],"title":"Custom Insights"}},"type":"object","title":"InsightsConfig"},"InterruptionSensitivityPreset":{"type":"string","enum":["very_robust","robust","balanced","sensitive","very_sensitive"],"title":"InterruptionSensitivityPreset"},"InworldTTSParams":{"properties":{"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature","default":0.8}},"type":"object","title":"InworldTTSParams"},"LLMConfig":{"properties":{"model":{"type":"string","title":"Model","default":"gpt-4.1-mini"},"params":{"$ref":"#/components/schemas/LLMParams"}},"type":"object","title":"LLMConfig"},"LLMParams":{"properties":{"temperature":{"type":"number","title":"Temperature","default":0.8},"top_p":{"type":"number","title":"Top P","default":0.9},"frequency_penalty":{"type":"number","title":"Frequency Penalty","default":0.0},"presence_penalty":{"type":"number","title":"Presence Penalty","default":0.0},"max_tokens":{"type":"integer","title":"Max Tokens","default":80}},"type":"object","title":"LLMParams"},"LLMScripts":{"properties":{"inbound":{"items":{"$ref":"#/components/schemas/ScriptStep"},"type":"array","title":"Inbound"},"outbound":{"items":{"$ref":"#/components/schemas/ScriptStep"},"type":"array","title":"Outbound"},"voicemail":{"items":{"$ref":"#/components/schemas/ScriptStep"},"type":"array","title":"Voicemail"},"sms":{"anyOf":[{"items":{"$ref":"#/components/schemas/ScriptStep"},"type":"array"},{"type":"null"}],"title":"Sms"},"after_hours":{"anyOf":[{"items":{"$ref":"#/components/schemas/ScriptStep"},"type":"array"},{"type":"null"}],"title":"After Hours"}},"type":"object","required":["inbound","outbound","voicemail"],"title":"LLMScripts"},"MaterializeCampaignSourceRequest":{"properties":{"source_id":{"type":"string","title":"Source Id"}},"type":"object","required":["source_id"],"title":"MaterializeCampaignSourceRequest"},"Metadata":{"properties":{"destination":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Destination"}},"type":"object","title":"Metadata"},"MidCallAction":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"trigger_phrases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Trigger Phrases"},"similarity_threshold":{"type":"number","title":"Similarity Threshold","default":0.75},"processor_type":{"type":"string","title":"Processor Type"},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config"}},"type":"object","required":["processor_type"],"title":"MidCallAction","description":"Configuration for a mid-call action.\n\nTwo tracks:\n- Tool-call actions (kb_lookup, browser_task, amount_due_lookup): Only need\n  processor_type + config. The LLM decides when to invoke them via function calling.\n- Semantic-trigger actions (verification, transcript_lookup): Also need\n  trigger_phrases + similarity_threshold. Fired when bot utterance matches.\n\namount_due_lookup config:\n  {\"timeout\": 20, \"policy_field\": \"policy_number\"}\n  The full policy number (e.g. VGAL-18795-000) is resolved from the\n  per-contact personalization field named by \"policy_field\" (default\n  \"policy_number\"). If that field is missing, the bot asks the caller.\n  The lookup is sent to the Modotech context-service endpoint."},"MintCampaignTemplateRequest":{"properties":{"template_id":{"type":"string","title":"Template Id"},"pipecat_flows_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pipecat Flows Enabled"}},"type":"object","required":["template_id"],"title":"MintCampaignTemplateRequest"},"OutboundCallRequest":{"properties":{"campaign_contact_id":{"type":"string","title":"Campaign Contact Id"},"is_follow_up":{"type":"boolean","title":"Is Follow Up","default":false}},"type":"object","required":["campaign_contact_id"],"title":"OutboundCallRequest"},"OutboundConfig":{"properties":{"lead_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lead Type"},"caller_id_routing":{"anyOf":[{"items":{"$ref":"#/components/schemas/CallerIdRule"},"type":"array"},{"type":"null"}],"title":"Caller Id Routing"}},"type":"object","title":"OutboundConfig","description":"Configuration specific to outbound campaigns."},"OutcomeMetricAggregationFn":{"type":"string","enum":["count_contacts","sum","avg","min","max"],"title":"OutcomeMetricAggregationFn"},"OutcomeMetricContactFilter":{"properties":{"source_field":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Field"},"target_values":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Target Values"}},"type":"object","title":"OutcomeMetricContactFilter","description":"Restrict an operand to contacts whose ``source_field`` matches."},"OutcomeMetricFormat":{"type":"string","enum":["number","percent","currency"],"title":"OutcomeMetricFormat"},"OutcomeMetricFormulaNode":{"properties":{"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"},"opId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Opid"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"format":{"anyOf":[{"$ref":"#/components/schemas/OutcomeMetricFormat"},{"type":"null"}]},"op":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Op"},"left":{"anyOf":[{"$ref":"#/components/schemas/OutcomeMetricFormulaNode"},{"type":"null"}]},"right":{"anyOf":[{"$ref":"#/components/schemas/OutcomeMetricFormulaNode"},{"type":"null"}]}},"type":"object","title":"OutcomeMetricFormulaNode","description":"One node of a metric's formula tree.\n\nFlattened on purpose: ``kind`` names the variant (\"operand\", a literal, a\nbinary operation) but is NOT a pydantic discriminator, so the union of\nvariants can never reject a stored node. Only the fields relevant to a\nnode's ``kind`` are populated.\n\n``opId`` is camelCase in the stored JSON and is published as written."},"OutcomeMetricOperand":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"fn":{"anyOf":[{"$ref":"#/components/schemas/OutcomeMetricAggregationFn"},{"type":"null"}]},"field":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field"},"filter":{"anyOf":[{"$ref":"#/components/schemas/OutcomeMetricContactFilter"},{"type":"null"}]},"include_removed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Include Removed"}},"type":"object","title":"OutcomeMetricOperand","description":"One named aggregation, referenced from the formula tree by ``id``."},"OutcomeMetricRule":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"format":{"anyOf":[{"$ref":"#/components/schemas/OutcomeMetricFormat"},{"type":"null"}]},"operands":{"anyOf":[{"items":{"$ref":"#/components/schemas/OutcomeMetricOperand"},"type":"array"},{"type":"null"}],"title":"Operands"},"formula":{"anyOf":[{"$ref":"#/components/schemas/OutcomeMetricFormulaNode"},{"type":"null"}]},"source_field":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Field"},"target_values":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Target Values"},"include_removed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Include Removed"}},"type":"object","title":"OutcomeMetricRule","description":"One dashboard metric tile."},"PostProcessingConfig":{"properties":{"provider":{"$ref":"#/components/schemas/PostProcessingProvider","default":"openai"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"}},"type":"object","title":"PostProcessingConfig","description":"Configuration for post-processing LLM (classification, resolution, call quality analysis).\n\nWhen set, overrides the default OpenAI-based post-processing with the specified provider/model.\nThis allows campaigns to use Claude for tagging tasks where it shows better accuracy."},"PostProcessingProvider":{"type":"string","enum":["openai","anthropic"],"title":"PostProcessingProvider"},"PublishedFlowGraphVersionSelector":{"properties":{"graph_id":{"type":"string","title":"Graph Id"},"version_id":{"type":"string","title":"Version Id"},"version_hash":{"type":"string","title":"Version Hash"},"graph_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Graph Name"},"source_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Id"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"},"published_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Published At"},"kind":{"type":"string","const":"published","title":"Kind","default":"published"}},"type":"object","required":["graph_id","version_id","version_hash"],"title":"PublishedFlowGraphVersionSelector"},"RawVadOverride":{"properties":{"confidence":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Confidence"},"start_secs":{"anyOf":[{"type":"number","maximum":2.0,"minimum":0.0},{"type":"null"}],"title":"Start Secs"},"stop_secs":{"anyOf":[{"type":"number","maximum":5.0,"minimum":0.0},{"type":"null"}],"title":"Stop Secs"},"min_volume":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Min Volume"},"flux_eager_eot_threshold":{"anyOf":[{"type":"number","maximum":0.9,"minimum":0.3},{"type":"null"}],"title":"Flux Eager Eot Threshold"},"flux_eot_threshold":{"anyOf":[{"type":"number","maximum":0.9,"minimum":0.5},{"type":"null"}],"title":"Flux Eot Threshold"},"flux_eot_timeout_ms":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":500.0},{"type":"null"}],"title":"Flux Eot Timeout Ms"}},"type":"object","title":"RawVadOverride","description":"Internal escape hatch. Not advertised in the customer UI.\n\nAny non-``None`` field overrides the corresponding value produced by the\nresolver for a ``balanced`` baseline. Partial overrides are supported."},"ReattemptByOutcome":{"properties":{"voicemail_box_full":{"type":"integer","title":"Voicemail Box Full","default":48},"hangup":{"type":"integer","title":"Hangup","default":48},"voicemail_left":{"type":"integer","title":"Voicemail Left","default":48},"line_busy":{"type":"integer","title":"Line Busy","default":48}},"type":"object","title":"ReattemptByOutcome"},"ReattemptConfig":{"properties":{"by_outcome":{"$ref":"#/components/schemas/ReattemptByOutcome"},"cadence_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cadence Prompt","description":"Prompt for cadence configuration"},"cadence_context":{"anyOf":[{"$ref":"#/components/schemas/CadenceContextConfig"},{"type":"null"}],"description":"Raw contact fields to inject into cadence prompts"},"use_answer_rate_distribution":{"type":"boolean","title":"Use Answer Rate Distribution","description":"Render the full hourly answer-rate distribution in the reattempt scheduling prompt instead of the single Thompson point recommendation","default":false},"keep_cadence_on_after_human_connect":{"type":"boolean","title":"Keep Cadence On After Human Connect","description":"Keep using cadence_prompt scheduling even after a prior human connection","default":false},"max_voicemail_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Voicemail Count","description":"Maximum number of voicemails to leave per contact. -1 for unlimited, 0 to disable, None uses system default (no voicemail)"},"voicemail_mode":{"type":"string","enum":["default","specific_attempts"],"title":"Voicemail Mode","description":"Voicemail decision mode. 'default' keeps the existing distribution algorithm; 'specific_attempts' leaves voicemail only on the configured attempt numbers.","default":"default"},"voicemail_allowed_attempts":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Voicemail Allowed Attempts","description":"Allowed dial attempts for voicemail when voicemail_mode is 'specific_attempts'."}},"type":"object","title":"ReattemptConfig"},"ResolveTouchpointRequest":{"properties":{"campaign_id":{"type":"string","title":"Campaign Id"},"campaign_contact_id":{"type":"string","title":"Campaign Contact Id"},"local_date":{"type":"string","format":"date","title":"Local Date"},"earliest_local":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$","title":"Earliest Local"},"latest_local":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$","title":"Latest Local"},"channel":{"type":"string","pattern":"^(call|sms)$","title":"Channel","default":"call"}},"type":"object","required":["campaign_id","campaign_contact_id","local_date","earliest_local","latest_local"],"title":"ResolveTouchpointRequest"},"ResolveTouchpointResponse":{"properties":{"scheduled_utc":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled Utc"},"scheduled_local":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scheduled Local"},"channel":{"type":"string","title":"Channel"},"sampled_hour_local":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sampled Hour Local"},"eligible_hours_local":{"items":{"type":"integer"},"type":"array","title":"Eligible Hours Local","default":[]},"resolved":{"type":"boolean","title":"Resolved","default":false},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["channel"],"title":"ResolveTouchpointResponse"},"ResponseSpeedPreset":{"type":"string","enum":["eager","fast","balanced","patient","very_patient"],"title":"ResponseSpeedPreset"},"RetagGroupResult":{"properties":{"classification_name":{"type":"string","title":"Classification Name"},"outcome":{"type":"string","title":"Outcome"},"tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tag"},"confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Confidence"},"existing_tag":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Existing Tag"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["classification_name","outcome"],"title":"RetagGroupResult"},"RetagRequest":{"properties":{"classification_names":{"items":{"type":"string"},"type":"array","maxItems":10,"minItems":1,"title":"Classification Names"},"dry_run":{"type":"boolean","title":"Dry Run","default":true}},"additionalProperties":false,"type":"object","required":["classification_names"],"title":"RetagRequest","description":"Body for a single-interaction re-tag."},"RetagResponse":{"properties":{"interaction_id":{"type":"string","title":"Interaction Id"},"campaign_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Id"},"dry_run":{"type":"boolean","title":"Dry Run"},"results":{"items":{"$ref":"#/components/schemas/RetagGroupResult"},"type":"array","title":"Results"}},"type":"object","required":["interaction_id","dry_run","results"],"title":"RetagResponse"},"RuntimeFlowGraphSelector":{"properties":{"kind":{"type":"string","const":"runtime","title":"Kind","default":"runtime"},"source_id":{"type":"string","title":"Source Id"}},"type":"object","required":["source_id"],"title":"RuntimeFlowGraphSelector"},"ScheduleUploadResponse":{"properties":{"total_scheduled":{"type":"integer","title":"Total Scheduled"},"total_failed":{"type":"integer","title":"Total Failed"},"processing_time_seconds":{"type":"number","title":"Processing Time Seconds"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["total_scheduled","total_failed","processing_time_seconds"],"title":"ScheduleUploadResponse","description":"Response model for schedule upload endpoint."},"ScriptStep":{"properties":{"step":{"type":"string","title":"Step"},"content":{"type":"string","title":"Content"}},"type":"object","required":["step","content"],"title":"ScriptStep"},"SipConfig":{"properties":{"sip_provider":{"anyOf":[{"$ref":"#/components/schemas/SipProvider"},{"type":"null"}]},"percentage":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":0.0},{"type":"null"}],"title":"Percentage"}},"type":"object","title":"SipConfig","description":"SIP routing configuration for inbound calls.\n\nInbound calls default to Daily unless this config sets a provider\nexplicitly. Daily room pool allocation is independent of SIP provider, so\nany provider can use pooled Daily rooms when available. When\n``sip_provider`` is set and ``percentage`` is omitted, all inbound calls use\nthat provider."},"SipProvider":{"type":"string","enum":["signalwire","daily"],"title":"SipProvider"},"SuccessCriteriaChannelConfig":{"properties":{"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"insight_keys":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Insight Keys"},"tag_values":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Values"}},"type":"object","title":"SuccessCriteriaChannelConfig","description":"Success definition for one channel."},"SuccessCriteriaChannels":{"properties":{"outbound_call":{"anyOf":[{"$ref":"#/components/schemas/SuccessCriteriaChannelConfig"},{"type":"null"}]},"inbound_call":{"anyOf":[{"$ref":"#/components/schemas/SuccessCriteriaChannelConfig"},{"type":"null"}]},"sms":{"anyOf":[{"$ref":"#/components/schemas/SuccessCriteriaChannelConfig"},{"type":"null"}]}},"type":"object","title":"SuccessCriteriaChannels"},"SuccessCriteriaConfig":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"channels":{"anyOf":[{"$ref":"#/components/schemas/SuccessCriteriaChannels"},{"type":"null"}]}},"type":"object","title":"SuccessCriteriaConfig"},"TTSConfig":{"properties":{"provider":{"$ref":"#/components/schemas/TTSProvider","default":"elevenlabs"},"voice_id":{"type":"string","title":"Voice Id","default":"Lrd8QHYUxHOQgV6Kbgy4"},"model":{"type":"string","title":"Model","default":"eleven_turbo_v2_5"},"output_format":{"type":"string","title":"Output Format","default":"pcm_24000"},"params":{"anyOf":[{"$ref":"#/components/schemas/ElevenLabsTTSParams"},{"$ref":"#/components/schemas/CartesiaTTSParams"},{"$ref":"#/components/schemas/InworldTTSParams"}],"title":"Params"}},"type":"object","title":"TTSConfig"},"TTSProvider":{"type":"string","enum":["elevenlabs","cartesia","inworld"],"title":"TTSProvider"},"TagClassification":{"properties":{"name":{"type":"string","title":"Name"},"definition":{"type":"string","title":"Definition"},"options":{"items":{"$ref":"#/components/schemas/TagOption"},"type":"array","title":"Options"}},"type":"object","required":["name","definition","options"],"title":"TagClassification","description":"A classification dimension (e.g., 'theme' or 'category')."},"TagDefinitions":{"properties":{"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution"},"resolution_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Label"},"classifications":{"anyOf":[{"items":{"$ref":"#/components/schemas/TagClassification"},"type":"array"},{"type":"null"}],"title":"Classifications"},"enable_call_quality":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Call Quality","default":false}},"type":"object","title":"TagDefinitions","description":"Definitions for tags that can be applied to interactions (any campaign type)."},"TagOption":{"properties":{"name":{"type":"string","title":"Name"},"definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Definition"}},"type":"object","required":["name"],"title":"TagOption","description":"A single option within a classification."},"TransferConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"destinations":{"items":{"$ref":"#/components/schemas/TransferDestination"},"type":"array","title":"Destinations","default":[]},"is_blind_transfer":{"type":"boolean","title":"Is Blind Transfer","default":false},"background_transfer":{"type":"boolean","title":"Background Transfer","default":false},"payment_transfer":{"type":"boolean","title":"Payment Transfer","default":false},"payment_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Number"},"payment_definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Definition"},"transfer_definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Definition"},"handoff_phrase":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Handoff Phrase"},"provider":{"anyOf":[{"$ref":"#/components/schemas/TransferProvider"},{"type":"null"}]},"whisper":{"anyOf":[{"$ref":"#/components/schemas/TransferWhisperConfig"},{"type":"null"}]}},"type":"object","title":"TransferConfig"},"TransferDestination":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"phone_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone Number"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","title":"TransferDestination"},"TransferProvider":{"type":"string","enum":["media_alpha"],"title":"TransferProvider","description":"Vendor that resolves the transfer destination at call time.\n\nWhen set, the configured destinations[] are placeholders — the actual\nphone number is fetched from the vendor's auction/lookup endpoint using\na per-lead token in personalization_fields. When unset, transfer dials\ndestinations[] directly (default behavior)."},"TransferWhisperConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"message_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message Template"},"timeout_seconds":{"type":"number","title":"Timeout Seconds","default":180.0},"handoff_grace_seconds":{"type":"number","title":"Handoff Grace Seconds","default":20.0},"max_message_plays":{"type":"integer","minimum":1.0,"title":"Max Message Plays","default":3},"message_gap_seconds":{"type":"number","maximum":10.0,"minimum":0.5,"title":"Message Gap Seconds","default":1.0}},"type":"object","title":"TransferWhisperConfig","description":"Opt-in whisper step for non-blind transfers.\n\nThe human agent is dialed on a separate Vonage leg, listened to via\nVonage ASR until a live human is detected, briefed with a personalized\nwhisper message, then bridged into the live Daily room. Ignored for\nblind transfers. Any whisper failure falls back to the standard\ntransfer path."},"UpdateCampaignBindingsRequest":{"properties":{"bindings":{"additionalProperties":true,"type":"object","title":"Bindings"},"flow_graphs":{"anyOf":[{"$ref":"#/components/schemas/FlowGraphsConfig"},{"type":"null"}]},"pipecat_flows_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pipecat Flows Enabled"}},"type":"object","title":"UpdateCampaignBindingsRequest"},"UpdateDraftRequest":{"properties":{"canonical_graph":{"additionalProperties":true,"type":"object","title":"Canonical Graph"}},"type":"object","required":["canonical_graph"],"title":"UpdateDraftRequest"},"VadBehavior":{"properties":{"response_speed":{"anyOf":[{"$ref":"#/components/schemas/ResponseSpeedPreset"},{"type":"number","maximum":1.0,"minimum":0.0}],"title":"Response Speed","default":"balanced"},"interruption_sensitivity":{"anyOf":[{"$ref":"#/components/schemas/InterruptionSensitivityPreset"},{"type":"number","maximum":1.0,"minimum":0.0}],"title":"Interruption Sensitivity","default":"balanced"}},"type":"object","title":"VadBehavior","description":"Customer-facing VAD knobs."},"VadConfig":{"properties":{"mode":{"type":"string","enum":["behavior","advanced"],"title":"Mode","default":"behavior"},"behavior":{"$ref":"#/components/schemas/VadBehavior"},"advanced":{"anyOf":[{"$ref":"#/components/schemas/RawVadOverride"},{"type":"null"}]}},"type":"object","title":"VadConfig","description":"Top-level VAD configuration attached to ``CampaignConfig``.\n\nTwo modes:\n\n* ``mode=\"behavior\"`` (default): use the semantic ``behavior`` knobs.\n* ``mode=\"advanced\"``: engineer-only; overlay raw ``RawVadOverride`` on top\n  of the balanced baseline for the active STT provider.\n\nBackwards-compat for the flat pre-framework shape\n``{confidence, start_secs, stop_secs, min_volume}``:\n\n* If the values match one of the known stale-boilerplate templates\n  (values that prod never actually ran), we discard them and fall back\n  to balanced defaults. Rollout stays a no-op for those campaigns.\n* Otherwise we migrate the block to ``mode=\"advanced\"`` so the\n  hand-tuned values are honored."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VoicemailReconfigureRequest":{"properties":{"voicemail_input_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voicemail Input Text"}},"type":"object","title":"VoicemailReconfigureRequest"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}