{"openapi":"3.1.0","info":{"title":"Twiddy Chatbot API","version":"0.1.0"},"paths":{"/widget/v1/chat.js":{"get":{"summary":"Widget Js","description":"Serve the chat widget loader stub with short cache and open CORS.","operationId":"widget_js_widget_v1_chat_js_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/widget/v1/chat.main.{bundle_hash}.js":{"get":{"summary":"Widget Main Js","description":"Serve the hashed main widget bundle (immutable, long-cached).","operationId":"widget_main_js_widget_v1_chat_main__bundle_hash__js_get","parameters":[{"name":"bundle_hash","in":"path","required":true,"schema":{"type":"string","title":"Bundle Hash"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/widget/v1/chat.track.{bundle_hash}.js":{"get":{"summary":"Widget Track Js","description":"Serve the hashed Tier 3 tracking bundle (immutable, long-cached).","operationId":"widget_track_js_widget_v1_chat_track__bundle_hash__js_get","parameters":[{"name":"bundle_hash","in":"path","required":true,"schema":{"type":"string","title":"Bundle Hash"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/widget/v1/chat.replay.{bundle_hash}.js":{"get":{"summary":"Widget Replay Js","description":"Serve the hashed Tier 3b replay bundle (immutable, long-cached).\n\nLoaded by the loader stub on every pageload when remote-config\n.replayEnabled is true. Wraps rrweb (~75 KB, ~25 KB gzipped) so it's\nintentionally split off from chat.track.","operationId":"widget_replay_js_widget_v1_chat_replay__bundle_hash__js_get","parameters":[{"name":"bundle_hash","in":"path","required":true,"schema":{"type":"string","title":"Bundle Hash"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/widget/v1/chat.voice.{bundle_hash}.js":{"get":{"summary":"Widget Voice Js","description":"Serve the hashed voice (Gemini Live) bundle (immutable, long-cached).\n\nLoaded lazily by the main widget bundle when the user clicks the mic\nbutton, so the ~50-70KB @google/genai SDK stays out of the main bundle.","operationId":"widget_voice_js_widget_v1_chat_voice__bundle_hash__js_get","parameters":[{"name":"bundle_hash","in":"path","required":true,"schema":{"type":"string","title":"Bundle Hash"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/slack/events":{"post":{"summary":"Slack Events","operationId":"slack_events_slack_events_post","parameters":[{"name":"x-slack-request-timestamp","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Slack-Request-Timestamp"}},{"name":"x-slack-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Slack-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/avochato/webhook":{"post":{"summary":"Avochato Webhook","operationId":"avochato_webhook_avochato_webhook_post","parameters":[{"name":"x-avochato-signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Avochato-Signature"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/chat":{"post":{"tags":["public-api"],"summary":"V1 Chat","description":"Stream a chat response as Server-Sent Events.\n\nReturns text/event-stream with JSON payloads:\n  - {\"type\": \"status\", \"message\": \"...\"}       — status updates\n  - {\"type\": \"narration\", \"content\": \"...\"}     — narration text\n  - {\"type\": \"content\", \"content\": \"...\"}       — assistant response\n  - {\"type\": \"properties\", \"properties\": [...]} — property cards\n  - {\"type\": \"result_set\", ...}                 — result set metadata\n  - {\"type\": \"escalation\", ...}                 — escalation to agent\n  - {\"type\": \"callback_form\", ...}              — callback form data\n  - data: [DONE]                                — stream complete","operationId":"v1_chat_v1_chat_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/escalation":{"get":{"tags":["public-api"],"summary":"V1 Escalation Messages","description":"Poll for new messages from a Slack escalation thread.\n\n`active` lets the widget restore polling on page reload — without it,\nagent replies that arrive while the chat is closed wouldn't surface.","operationId":"v1_escalation_messages_v1_conversations__conversation_id__escalation_get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO timestamp — only return messages after this","title":"After"},"description":"ISO timestamp — only return messages after this"},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/reply":{"post":{"tags":["public-api"],"summary":"V1 Escalation Reply","description":"Relay a user's message to the active escalation provider.","operationId":"v1_escalation_reply_v1_conversations__conversation_id__reply_post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1EscalationReply"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/attachments":{"post":{"tags":["public-api"],"summary":"V1 Attachment Upload","description":"Guest uploads an image from the widget (multipart ``file``).\n\nStored in the analytics DB; served publicly from ``/api/attachments/{id}``\n(unguessable id) so the link works from the transcript, Slack, and Avochato\nnotes. The widget puts ``[Guest attached a photo: <url>]`` into the\nconversation history so the assistant and any human agent know it exists.","operationId":"v1_attachment_upload_v1_conversations__conversation_id__attachments_post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_v1_attachment_upload_v1_conversations__conversation_id__attachments_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/avochato-started":{"post":{"tags":["public-api"],"summary":"V1 Avochato Started","description":"Widget pings after Avochato's iframe form is submitted. We correlate\nthe just-created live-chat ticket via Avochato's REST API and attach the\npre-loaded AI conversation summary as an agent-only note. Best-effort.","operationId":"v1_avochato_started_v1_conversations__conversation_id__avochato_started_post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/avochato-live-session":{"post":{"tags":["public-api"],"summary":"V1 Avochato Live Session","description":"Widget sends the live_session after Avochato's saveSession postMessage.\nFrom this point, the backend proxies all messaging natively.","operationId":"v1_avochato_live_session_v1_conversations__conversation_id__avochato_live_session_post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1AvochatoSessionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/avochato-events":{"get":{"tags":["public-api"],"summary":"V1 Avochato Events","description":"Poll Avochato events.json for agent messages.","operationId":"v1_avochato_events_v1_conversations__conversation_id__avochato_events_get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/avochato-state":{"get":{"tags":["public-api"],"summary":"V1 Avochato State","description":"Lightweight state poll for the native chat UI: are we still waiting on\na real human agent, has the system sent an auto-greeting, or is a named\nagent actually engaged? And how many guests are ahead in line?\n\nReturns:\n  {\n    status: 'connecting' | 'auto_greeted' | 'connected',\n    agent_name: str | None,\n    queue_ahead: int,\n    ticket_id: str | None,\n  }","operationId":"v1_avochato_state_v1_conversations__conversation_id__avochato_state_get","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/conversations/{conversation_id}/avochato-send":{"post":{"tags":["public-api"],"summary":"V1 Avochato Send","description":"Send a guest message to the active Avochato conversation.","operationId":"v1_avochato_send_v1_conversations__conversation_id__avochato_send_post","parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1AvochatoSendRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/callback":{"post":{"tags":["public-api"],"summary":"V1 Callback","description":"Submit a callback request (posted to Slack and Salesforce).","operationId":"v1_callback_v1_callback_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1CallbackRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/config":{"get":{"tags":["public-api"],"summary":"V1 Config","description":"Return widget configuration (card customizations, branding, etc.).","operationId":"v1_config_v1_config_get","parameters":[{"name":"pageType","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pagetype"}},{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/result-set":{"post":{"tags":["public-api"],"summary":"V1 Result Set","description":"Fetch batch property details for the result set viewer.","operationId":"v1_result_set_v1_result_set_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ResultSetRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/property-context":{"post":{"tags":["public-api"],"summary":"V1 Property Context","description":"Fetch full property details for page-context hydration.","operationId":"v1_property_context_v1_property_context_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1PropertyContextRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/analytics":{"post":{"tags":["public-api"],"summary":"V1 Analytics","description":"Forward an analytics batch to the analytics Cloud Run service.","operationId":"v1_analytics_v1_analytics_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1AnalyticsBatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/feedback":{"post":{"tags":["public-api"],"summary":"V1 Feedback","description":"Forward a message-level thumbs up/down vote to the analytics service.\n\nMirrors the /v1/analytics proxy but targets /analytics/feedback, which\nstores ONE current-state `message_feedback` row per message in `events`\n(vote changes upsert in place; a null vote removes the row).","operationId":"v1_feedback_v1_feedback_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1FeedbackRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/interactions":{"post":{"tags":["public-api"],"summary":"V1 Interactions","description":"Forward a behavioral-tracking batch to the analytics service.\n\nMirrors the /v1/analytics proxy but targets /tracking/ingest so pre-chat\nvisitors (who have no conversation_id) can be recorded.","operationId":"v1_interactions_v1_interactions_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1InteractionsBatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/replay/chunk":{"post":{"tags":["public-api"],"summary":"V1 Replay Chunk","description":"Forward an rrweb replay chunk to the analytics service.\n\nSame auth model as /v1/interactions — the widget hits this with its\nX-Api-Key, we forward to /replay/chunk on twiddy-analytics-read using\nthe bearer token. Failures are non-fatal so the widget never throws\ninto the host page.","operationId":"v1_replay_chunk_v1_replay_chunk_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1ReplayChunk"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/nudge":{"post":{"tags":["public-api"],"summary":"V1 Nudge","description":"Generate a proactive nudge suggestion based on conversation context.\n\nCurrently returns shouldNudge=false as a placeholder.\nThe full nudge pipeline (search, availability check, template generation)\nwill be ported from the Next.js implementation in a follow-up.","operationId":"v1_nudge_v1_nudge_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1NudgeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/nudge/checkin":{"post":{"tags":["public-api"],"summary":"V1 Nudge Checkin","description":"Return (and claim) the pending offer for this anon id, if any.\n\nGated client-side by the widget config's ``recoveryNudgeEnabled`` flag;\nfail-soft — any error returns no offer and never disturbs the page.","operationId":"v1_nudge_checkin_v1_nudge_checkin_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1NudgeCheckinRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/nudge/ack":{"post":{"tags":["public-api"],"summary":"V1 Nudge Ack","description":"Record the outcome of a shown offer.","operationId":"v1_nudge_ack_v1_nudge_ack_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1NudgeAckRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/voice/ephemeral-token":{"post":{"tags":["public-api"],"summary":"V1 Voice Ephemeral Token","description":"Mint a single-use Gemini Live ephemeral token plus voice config.","operationId":"v1_voice_ephemeral_token_v1_voice_ephemeral_token_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1VoiceTokenRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/voice/tool":{"post":{"tags":["public-api"],"summary":"V1 Voice Tool","description":"Execute a Gemini-requested tool call using the shared chat handlers.","operationId":"v1_voice_tool_v1_voice_tool_post","parameters":[{"name":"k","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"K"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-api-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1VoiceToolRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/attachments/{attachment_id}":{"get":{"summary":"Api Attachment","description":"Serve a guest-uploaded image. Public by design: ids are unguessable and\nthe link must open from Slack / Avochato / the analytics viewer.","operationId":"api_attachment_api_attachments__attachment_id__get","parameters":[{"name":"attachment_id","in":"path","required":true,"schema":{"type":"string","title":"Attachment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/healthz":{"get":{"summary":"Healthcheck","operationId":"healthcheck_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Response Healthcheck Healthz Get"}}}}}}},"/status":{"get":{"summary":"Status ","description":"Liveness/observability endpoint that survives the Cloud Run frontend.\n\nGoogle Front End intercepts /healthz on *.run.app URLs for its own health\nchecks, so a request to /healthz never reaches the container (see the smoke\ncomment in scripts/deploy_cloud_run.sh). /status does reach the app, so it\ncan report what's actually running: the live revision, process uptime, and\nthe model from the GCS agent settings the widget actually uses.","operationId":"status__status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Status  Status Get"}}}}}}},"/chat":{"post":{"summary":"Chat","description":"SSE endpoint matching the Next.js /api/twiddy/chat contract.","operationId":"chat_chat_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"x-twiddy-request-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Request-Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/escalation/messages":{"get":{"summary":"Escalation Messages","description":"Poll for new messages from the active escalation channel.\n\nResponse also surfaces the provider-specific external reference\n(Avochato ticket_id / Slack thread_ts). The chat widget renders this\nin debug mode so testers can verify the chat session is bound to the\nexpected ticket without grepping logs.","operationId":"escalation_messages_escalation_messages_get","parameters":[{"name":"conversation_id","in":"query","required":true,"schema":{"type":"string","title":"Conversation Id"}},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"After"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/escalation/reply":{"post":{"summary":"Escalation Reply","description":"Relay a user's chat message to the active escalation provider.","operationId":"escalation_reply_escalation_reply_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationReplyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/escalation/avochato/started":{"post":{"summary":"Escalation Avochato Started","description":"Widget pings this after Avochato's iframe transitions to chatting mode\n(i.e., the user has submitted the in-iframe form, so a ticket exists).\n\nWe look up the AI summary that was stashed when the AI tool fired,\ncorrelate the just-created live-chat ticket via Avochato's REST API\n(origin=live-chat + matching IP + recent created_at), and attach the\nsummary as an agent-only note. Idempotent and best-effort: if the\ncorrelation misses, the agent picks up the chat without the pre-loaded\nAI context — not a hard failure.","operationId":"escalation_avochato_started_escalation_avochato_started_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvochatoStartedRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/escalation/end":{"post":{"summary":"Escalation End","description":"End an active escalation: closes the Avochato ticket / posts a Slack notice.\n\nIdempotent — returns ok even if the session is already ended or missing,\nso beforeunload beacons can fire repeatedly without producing errors.","operationId":"escalation_end_escalation_end_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationEndRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/callback/submit":{"post":{"summary":"Callback Submit","description":"Accept the off-hours human-handoff form and notify the team via Slack\nand create a Salesforce Case (existing customer) or Lead (new contact).","operationId":"callback_submit_callback_submit_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackSubmitRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api-keys":{"get":{"summary":"List Api Keys","description":"List all API keys (active + revoked).","operationId":"list_api_keys_api_keys_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"summary":"Create Api Key","description":"Create a new API key.  The raw key is returned ONCE.","operationId":"create_api_key_api_keys_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api-keys/{key_id}":{"delete":{"summary":"Revoke Api Key","description":"Revoke an API key by id.","operationId":"revoke_api_key_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"integer","title":"Key Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/voice/ephemeral-token":{"post":{"summary":"Voice Ephemeral Token","description":"Mint a Gemini Live ephemeral token + voice bootstrap for the dashboard.","operationId":"voice_ephemeral_token_voice_ephemeral_token_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceTokenRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/voice/tool":{"post":{"summary":"Voice Tool","description":"Execute a Gemini-requested tool call for the dashboard voice client.","operationId":"voice_tool_voice_tool_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-twiddy-chatbot-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Twiddy-Chatbot-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceToolRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AvochatoStartedRequest":{"properties":{"conversation_id":{"type":"string","minLength":1,"title":"Conversation Id"}},"type":"object","required":["conversation_id"],"title":"AvochatoStartedRequest"},"Body_v1_attachment_upload_v1_conversations__conversation_id__attachments_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_v1_attachment_upload_v1_conversations__conversation_id__attachments_post"},"CallbackSubmitRequest":{"properties":{"name":{"type":"string","minLength":1,"title":"Name"},"phone":{"type":"string","minLength":1,"title":"Phone"},"email":{"type":"string","minLength":1,"title":"Email"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"}},"type":"object","required":["name","phone","email"],"title":"CallbackSubmitRequest"},"ChatRequest":{"properties":{"message":{"type":"string","minLength":1,"title":"Message"},"conversationHistory":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Conversationhistory"},"pageContext":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pagecontext"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"enabledTools":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Enabledtools"},"agentName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agentname"},"personalityPrompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personalityprompt"},"searchApiBackend":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Searchapibackend"},"availabilityPriceDisplayMode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Availabilitypricedisplaymode"},"resultCardCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Resultcardcount"},"maxTokensInitial":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxtokensinitial"},"maxTokensFinal":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maxtokensfinal"},"temperature":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature"},"topP":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Topp"},"conversationId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversationid"}},"type":"object","required":["message"],"title":"ChatRequest"},"CreateApiKeyRequest":{"properties":{"name":{"type":"string","maxLength":200,"title":"Name","default":""}},"type":"object","title":"CreateApiKeyRequest"},"EscalationEndRequest":{"properties":{"conversation_id":{"type":"string","minLength":1,"title":"Conversation Id"}},"type":"object","required":["conversation_id"],"title":"EscalationEndRequest"},"EscalationReplyRequest":{"properties":{"conversation_id":{"type":"string","minLength":1,"title":"Conversation Id"},"message":{"type":"string","minLength":1,"title":"Message"}},"type":"object","required":["conversation_id","message"],"title":"EscalationReplyRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"V1AnalyticsBatch":{"properties":{"conversation":{"additionalProperties":true,"type":"object","title":"Conversation"},"messages":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Messages"},"events":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Events"}},"type":"object","required":["conversation"],"title":"V1AnalyticsBatch"},"V1AvochatoSendRequest":{"properties":{"message":{"type":"string","minLength":1,"title":"Message"}},"type":"object","required":["message"],"title":"V1AvochatoSendRequest"},"V1AvochatoSessionRequest":{"properties":{"live_session":{"type":"string","minLength":1,"title":"Live Session"},"widget_id":{"type":"string","title":"Widget Id","default":""},"ticket_id":{"type":"string","title":"Ticket Id","default":""}},"type":"object","required":["live_session"],"title":"V1AvochatoSessionRequest"},"V1CallbackCriteria":{"properties":{"year":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Year"},"arrival_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrival Date"},"departure_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Departure Date"},"min_bedrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Bedrooms"},"max_bedrooms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Bedrooms"},"min_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Price"},"max_price":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Price"},"towns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Towns"},"distance_to_beach":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Distance To Beach"},"amenities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Amenities"},"search_results_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search Results Url"}},"type":"object","title":"V1CallbackCriteria","description":"Guest's property-search criteria, captured onto the Salesforce record."},"V1CallbackRequest":{"properties":{"name":{"type":"string","minLength":1,"title":"Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"criteria":{"anyOf":[{"$ref":"#/components/schemas/V1CallbackCriteria"},{"type":"null"}]}},"type":"object","required":["name"],"title":"V1CallbackRequest"},"V1ChatMessage":{"properties":{"role":{"type":"string","title":"Role","description":"'user' or 'assistant'"},"content":{"type":"string","title":"Content"},"properties":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Properties"},"result_set_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result Set Id"},"result_set_property_ids":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Result Set Property Ids"},"result_set_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Result Set Count"}},"type":"object","required":["role","content"],"title":"V1ChatMessage"},"V1ChatRequest":{"properties":{"message":{"type":"string","minLength":1,"title":"Message","description":"The user's message as sent to the LLM (may include page-context prefix)"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id","description":"Unique conversation ID. Generated server-side if omitted."},"conversation_history":{"items":{"$ref":"#/components/schemas/V1ChatMessage"},"type":"array","title":"Conversation History","description":"Prior messages in this conversation"},"page_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Page Context","description":"Optional context about the page the user is viewing"},"user_message_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Message Id","description":"UUID the client is using for this user message; server reuses it for analytics."},"assistant_message_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assistant Message Id","description":"UUID the client is using for the upcoming assistant message; server reuses it for analytics."},"raw_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Message","description":"The user's message without page-context enrichment. Preferred for analytics storage."}},"type":"object","required":["message"],"title":"V1ChatRequest"},"V1EscalationReply":{"properties":{"message":{"type":"string","minLength":1,"title":"Message"}},"type":"object","required":["message"],"title":"V1EscalationReply"},"V1FeedbackRequest":{"properties":{"conversation_id":{"type":"string","title":"Conversation Id","description":"Analytics conversation UUID"},"message_id":{"type":"string","title":"Message Id","description":"Analytics UUID of the assistant message being rated"},"vote":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vote","description":"'up' | 'down' | null (null removes an existing vote)"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At","description":"Client ISO timestamp of the vote (optional)"}},"type":"object","required":["conversation_id","message_id"],"title":"V1FeedbackRequest"},"V1InteractionsBatch":{"properties":{"session":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Session"},"interactions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Interactions"},"activeSecondsDelta":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Activesecondsdelta"}},"type":"object","title":"V1InteractionsBatch"},"V1NudgeAckRequest":{"properties":{"id":{"type":"string","maxLength":64,"minLength":8,"title":"Id"},"status":{"type":"string","title":"Status","description":"'engaged' (teaser clicked) or 'dismissed'"}},"type":"object","required":["id","status"],"title":"V1NudgeAckRequest"},"V1NudgeCheckinRequest":{"properties":{"anon_user_id":{"type":"string","maxLength":64,"minLength":8,"title":"Anon User Id"},"page_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Page Context"}},"type":"object","required":["anon_user_id"],"title":"V1NudgeCheckinRequest","description":"Page-load check-in from the widget loader: does this browser have a\npending proactive offer (e.g. an outage-recovery nudge)?"},"V1NudgeRequest":{"properties":{"conversation_history":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Conversation History"},"exclude_property_ids":{"items":{"type":"integer"},"type":"array","title":"Exclude Property Ids"}},"type":"object","title":"V1NudgeRequest"},"V1PropertyContextRequest":{"properties":{"property_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Property Id"},"property_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Property Number"}},"type":"object","title":"V1PropertyContextRequest"},"V1ReplayChunk":{"properties":{"session":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Session"},"chunkIndex":{"type":"integer","minimum":0.0,"title":"Chunkindex"},"events":{"items":{},"type":"array","title":"Events"},"triggerReason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Triggerreason"}},"type":"object","required":["chunkIndex"],"title":"V1ReplayChunk"},"V1ResultSetRequest":{"properties":{"property_ids":{"items":{"type":"integer"},"type":"array","maxItems":48,"minItems":1,"title":"Property Ids"}},"type":"object","required":["property_ids"],"title":"V1ResultSetRequest"},"V1VoiceTokenRequest":{"properties":{"conversation_history":{"items":{"$ref":"#/components/schemas/V1ChatMessage"},"type":"array","title":"Conversation History"},"page_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Page Context"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"navigation_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Navigation Enabled"}},"type":"object","title":"V1VoiceTokenRequest"},"V1VoiceToolRequest":{"properties":{"tool_name":{"type":"string","title":"Tool Name","description":"Name of the tool Gemini asked to call"},"args":{"additionalProperties":true,"type":"object","title":"Args"},"conversation_history":{"items":{"$ref":"#/components/schemas/V1ChatMessage"},"type":"array","title":"Conversation History"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"page_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Page Context"},"navigation_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Navigation Enabled"},"user_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Message","description":"Latest user utterance (used by request_human_agent, etc.)"}},"type":"object","required":["tool_name"],"title":"V1VoiceToolRequest"},"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"},"VoiceTokenRequest":{"properties":{"conversationHistory":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Conversationhistory"},"pageContext":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pagecontext"},"conversationId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversationid"},"navigationEnabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Navigationenabled"}},"type":"object","title":"VoiceTokenRequest"},"VoiceToolRequest":{"properties":{"toolName":{"type":"string","minLength":1,"title":"Toolname"},"args":{"additionalProperties":true,"type":"object","title":"Args"},"conversationHistory":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Conversationhistory"},"conversationId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversationid"},"pageContext":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Pagecontext"},"navigationEnabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Navigationenabled"},"userMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Usermessage"}},"type":"object","required":["toolName"],"title":"VoiceToolRequest"}}}}