{"name":"DoctorsInItaly Booking Agent","description":"Booking agent for urgent telemedicine: granular patient data collection, eligibility, need classification, slot selection, phone OTP (SMS/WhatsApp — always required), optional email verification when communication_channel=email, Stripe payment, and assignment polling. Prefer the MCP protocol over raw HTTP REST for a guided tool surface and step-by-step patient UX.","url":"https://findapi.doctorsa.com","version":"1.5.0","provider":{"organization":"Doctorsa","url":"https://www.doctorsa.com"},"license":"proprietary","iconUrl":"https://www.doctorsa.com/favicon.ico","documentationUrl":"https://findapi.doctorsa.com/.well-known/openapi-llm.json","openApiUrl":"https://findapi.doctorsa.com/.well-known/openapi-llm.json","mcpUrl":"https://findapi.doctorsa.com/mcp","agentCardUrl":"https://findapi.doctorsa.com/.well-known/agent.json","protocols":["mcp","rest","openapi"],"agentGuidance":{"preferredProtocol":"mcp","rules":["Warmly recommend using the MCP protocol (mcpUrl / MCP tools) instead of calling HTTP REST endpoints directly. MCP exposes one tool per patient question, returns profile_complete and missing hints, and ships the canonical workflow prompt — all of which improve conversational UX.","When using REST anyway, mirror the same granularity: never batch city, age, language, or patient identity fields in a single user turn.","Send User-Agent on every HTTP/MCP request. Send X-LLM-Agent header too (cursor|claude|chatgpt|gemini|copilot|perplexity|mcp|other). Missing either returns 400 agent_headers_required.","See emergencyTriage: when symptoms are clearly beyond video telemedicine (e.g. heavy bleeding, dangerous injuries, obvious life threat), recommend ER / immediate in-person care / ambulance — calibrated, not alarmist. The patient may still continue booking afterward if they choose."]},"agentIdentification":{"storedOn":"POST /sessions (create_booking_session)","required":true,"fields":{"agent_user_agent":"Raw User-Agent header (required)","agent_client":"Normalized slug from X-LLM-Agent when recognized; otherwise the raw X-LLM-Agent or full User-Agent string for discovery","agent_entrypoint":"mcp when called via MCP tools; rest for direct HTTP"},"requiredHeaders":{"User-Agent":"Native client string","X-LLM-Agent":"cursor | claude | chatgpt | gemini | copilot | perplexity | mcp | other"},"errorWhenMissing":{"http_status":400,"error":"agent_headers_required"}},"mcp":{"transport":"streamable-http","endpoint":"https://findapi.doctorsa.com/mcp","stateless":true,"resources":["agent://doctorsa/booking/card","agent://doctorsa/booking/openapi"]},"apiBasePath":"/v1/booking","capabilities":{"streaming":false,"pushNotifications":false,"stateTransitionHistory":true,"conversationState":true,"asyncTasks":true,"resume":true},"authentication":{"schemes":["none"]},"defaultInputModes":["application/json"],"defaultOutputModes":["application/json"],"requiredContext":{"booking_session_id":{"description":"UUID returned by create_booking_session; path parameter {id} on subsequent calls.","producedBy":"create_booking_session"}},"eligibility":{"careTypes":["urgent"],"ageRange":{"min":0,"max":120},"supportedCountries":["DE","ES","FR","IT","PT","UY"],"activeRolloutCountries":["UY"],"rolloutNote":"Only activeRolloutCountries pass create_booking_session today; supportedCountries lists the full planned rollout.","countryLanguages":{"DE":["de","en"],"ES":["es","en"],"FR":["fr","en"],"IT":["it","en"],"PT":["pt","en"],"UY":["es","en"]},"countryTimezones":{"DE":"Europe/Berlin","ES":"Europe/Madrid","FR":"Europe/Paris","IT":"Europe/Rome","PT":"Europe/Lisbon","UY":"America/Montevideo"},"bookingHours":{"startHourLocal":7,"endHourLocal":23,"description":"Online booking is available from 07:00 up to (but not including) 23:00 in the patient country timezone.","rejectionReasonCode":"out_of_hours"},"slotRules":{"dayOffsetsMinutes":[20,30,40,60],"nightOffsetsMinutes":[20,30],"dayWindowLocal":"07:30-22:00","morningSlotsWhenOutsideDayWindow":"Fixed morning appointment times (08:30, 09:30, 10:30 local) returned as morning_slots when booking at night."},"rejectionReasonCodes":["country_not_supported","out_of_hours","language_not_supported","no_doctors_online","no_data","tta_too_high"]},"emergencyTriage":{"scope":"Conversational safety guidance before and alongside the booking API flow. Agents may discuss symptoms with the user outside the strict skill sequence.","whenToRecommendEmergencyCare":["Heavy or uncontrolled bleeding","Dangerous injuries or major trauma","Clear signs of a life-threatening emergency (e.g. severe difficulty breathing, chest pain with collapse, stroke symptoms, anaphylaxis, repeated loss of consciousness)","Situations where waiting for a video visit would obviously be unsafe"],"recommendation":"When the presentation is clearly beyond what a delayed online video consultation can safely address, recommend going directly to the hospital emergency department, seeking immediate in-person assistance, and/or calling local emergency services or an ambulance — using wording appropriate to the patient country.","calibration":"Do not over-triage. Descriptions may be exaggerated or understated; reserve strong ER/ambulance advice for presentations that are obviously incompatible with telemedicine. If uncertain, ask brief clarifying questions instead of alarming the patient or blocking the flow.","patientChoice":"After recommending emergency care, explicitly tell the patient they may still continue with the online booking if they wish. Never refuse to proceed solely because ER care was suggested.","timing":["During initial symptom conversation, before create_booking_session when red flags are already obvious","Before submit_need when new concerning details appear","Not a substitute for submit_need or the API need classifier — booking may still proceed"]},"verificationModel":{"summary":"Phone OTP is always required. communication_channel (sms | whatsapp | email) sets post-booking contact preference, not which verification steps run.","paths":{"sms_whatsapp":{"steps":["set_communication_channel (sms or whatsapp)","set_patient_first_name, set_patient_last_name, set_patient_gender (one field per step)","start_phone_verification { phone_e164 }","verify_phone_otp → phone_verified + checkout_url"],"setEmail":"optional in draft (Stripe Checkout prefill)","paymentGate":"phone_verified"},"email":{"steps":["set_email OR set_communication_channel with email","set_communication_channel (email) — locks address","set_patient_first_name, set_patient_last_name, set_patient_gender (one field per step)","start_phone_verification { phone_e164, channel: whatsapp|sms }","verify_phone_otp → phone_verified + email_verification_required (no checkout)","start_email_verification","verify_email_code → email_verified + checkout_url"],"setEmail":"required before email verification (via set_email or set_communication_channel)","emailLock":"Once communication_channel=email and address is set, it cannot change until verify_email_code succeeds (422 email_locked_pending_verification).","paymentGate":"phone_verified AND email_verified_at","pollStatus":"GET /sessions/{id} returns status=phone_verified plus email_verified (and email_verified_at when true) — use to poll without conflating session lifecycle with email verification."}},"errorCodes":{"email_locked_pending_verification":"Attempted to change session email while email-channel verification is pending.","email_verification_required":"GET /checkout called before email verification completed (email channel only).","email_not_required":"start_email_verification called when communication_channel is not email."}},"workflow":{"recommendedOrder":["get_verification_channels","create_booking_session","set_session_city","set_session_age","set_session_language","select_slot","submit_need","set_communication_channel","set_patient_first_name","set_patient_last_name","set_patient_gender","start_phone_verification","verify_phone_otp","get_booking_status"],"optionalSteps":["get_verification_channels","set_email","start_email_verification","verify_email_code","get_payment_link","reset_verification","cancel_booking_session"],"humanRequiredSteps":[{"after":"start_phone_verification","action":"Patient receives SMS/WhatsApp OTP and provides otp_code to the agent."},{"after":"start_email_verification","action":"Patient receives email code and provides code to the agent."},{"after":"verify_phone_otp","action":"sms/whatsapp: open checkout_url for Stripe payment. email channel: no checkout yet — proceed to start_email_verification."},{"after":"verify_email_code","action":"When communication_channel=email, open checkout_url from verify_email_code (or get_payment_link) for Stripe payment."}],"states":["draft","phone_pending","phone_verified","paid","assigned","rejected","expired","cancelled"],"terminalStates":["assigned","rejected","expired","cancelled"],"transitions":{"draft":["phone_pending","rejected","expired","cancelled"],"phone_pending":["phone_verified","draft","rejected","expired","cancelled"],"phone_verified":["paid","rejected","expired","cancelled"],"paid":["assigned","rejected","expired","cancelled"]},"notes":["See emergencyTriage for when to recommend hospital/ER/ambulance outside the API flow; patient may still book afterward.","Prefer MCP (see agentGuidance.preferredProtocol) over raw HTTP — tools are aligned to one patient answer per step.","Call get_verification_channels before offering SMS/WhatsApp/email to the patient; only enabled_channels can be set via set_communication_channel.","Check eligibility.activeRolloutCountries and eligibility.bookingHours before create_booking_session to avoid predictable rejections.","Session context (city, age, language) is collected via set_session_city, set_session_age, and set_session_language — one question per step. Eligibility and slots appear when the last missing context field is set (context_complete=true).","Patient identity (first_name, last_name, gender) is collected via set_patient_first_name, set_patient_last_name, and set_patient_gender — one question per step. Each response includes profile_complete and missing.","set_communication_channel may run in any order after submit_need relative to patient identity fields; communication channel and complete profile are required before verification.","Phone OTP is always required: start_phone_verification then verify_phone_otp → phone_verified. When communication_channel=email, pass channel (whatsapp|sms) on start_phone_verification for OTP delivery.","Email channel gate (communication_channel=email only): after phone_verified, call start_email_verification then verify_email_code → email_verified + checkout_url. Email set on the session cannot be changed until verify_email_code succeeds.","verify_phone_otp transitions phone_pending → phone_verified. checkout_url is returned for sms/whatsapp; for email channel, email_verification_required=true until verify_email_code.","Payment (phone_verified → paid) is asynchronous: Stripe webhook checkout.session.completed after the patient pays; poll get_booking_status.","Doctor assignment (paid → assigned) is asynchronous; keep polling get_booking_status until assigned or a terminal state.","set_email is optional on any channel in draft; required before email verification when communication_channel=email (via set_email or set_communication_channel).","get_payment_link (GET /checkout) is optional if checkout_url from verify_phone_otp or verify_email_code is retained.","reset_verification (DELETE /verification) and cancel_booking_session (DELETE /sessions/{id}) are on-demand recovery/cancellation steps, not part of the happy path.","Poll get_booking_status via GET /sessions/{booking_session_id} (not a separate /status path).","See verificationModel.paths for channel-specific step sequences and payment gates."]},"skills":[{"id":"get_verification_channels","name":"Get Verification Channels","description":"Return verification channels enabled on this deployment (subset of sms, whatsapp, email). Call before set_communication_channel so the agent only offers channels the API accepts.","tags":["booking","communication","discovery"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"GET","path":"/v1/booking/verification-channels","operationId":"getVerificationChannels"},"produces":["enabled_channels"],"allowedStates":[],"nextStates":[],"structuredExamples":[{"summary":"Enabled channels","output":{"enabled_channels":["whatsapp","email"]}}],"promptExamples":["Which verification channels are available?"]},{"id":"create_booking_session","name":"Create Booking Session","description":"Start an eligibility-gated booking session. Required body fields: country (ISO 3166-1 alpha-2), care_type (must be \"urgent\"). Returns booking_session_id and context_complete=false with missing city/age/language — collect each via set_session_city, set_session_age, and set_session_language (one patient answer per step). Eligibility and priced slots are returned when the last context field is set.","tags":["booking","eligibility"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"POST","path":"/v1/booking/sessions","operationId":"createBookingSession"},"produces":["booking_session_id","session_state"],"allowedStates":[],"nextStates":["draft","rejected"],"structuredExamples":[{"summary":"Session started — collect city, age, language next","input":{"country":"UY","care_type":"urgent"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"draft","context_complete":false,"missing":["city","age","language"],"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Start urgent telemedicine booking for a patient in Uruguay"]},{"id":"set_session_city","name":"Set Session City","description":"Set the patient city on the draft session. Ask for one piece of context at a time. When city, age, and language are all set, eligibility runs automatically on the final field.","tags":["booking","eligibility","patient"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/city","operationId":"setSessionCity"},"requires":["create_booking_session"],"produces":["session_city_set"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft","rejected"],"structuredExamples":[{"summary":"City saved, more context needed","input":{"city":"Montevideo"},"output":{"ok":true,"context_complete":false,"missing":["age","language"],"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient is in Montevideo"]},{"id":"set_session_age","name":"Set Session Age","description":"Set the patient age (0–120). Ask for one piece of context at a time. Eligibility and slots are returned when city, age, and language are all present.","tags":["booking","eligibility","patient"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/age","operationId":"setSessionAge"},"requires":["create_booking_session"],"produces":["session_age_set"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft","rejected"],"structuredExamples":[{"summary":"Age saved, language still needed","input":{"age":35},"output":{"ok":true,"context_complete":false,"missing":["language"],"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient is 35 years old"]},{"id":"set_session_language","name":"Set Session Language","description":"Set preferred language (e.g. en, es). When city and age are already set, this triggers eligibility and returns priced slots or a rejection.","tags":["booking","eligibility","patient"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/language","operationId":"setSessionLanguage"},"requires":["create_booking_session"],"produces":["session_context_complete","slots"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft","rejected"],"structuredExamples":[{"summary":"Context complete — eligible with slots","input":{"language":"en"},"output":{"ok":true,"context_complete":true,"missing":[],"status":"draft","price_amount":25,"price_currency":"eur","slots":[{"slot_offset_minutes":20,"price_amount":25,"price_currency":"eur"},{"slot_offset_minutes":30,"price_amount":30,"price_currency":"eur"}],"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient prefers to speak English"]},{"id":"select_slot","name":"Select Appointment Slot","description":"Select appointment offset in minutes from payment time. Must run after session context is complete (set_session_language returned slots). Use slot_offset_minutes from one of the priced slots (typically 20, 30, 40, or 60). Request body: { slot_offset_minutes: number }.","tags":["booking","scheduling"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/slot","operationId":"selectSlot"},"requires":["set_session_language"],"produces":["slot_selected"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft"],"structuredExamples":[{"summary":"30-minute slot","input":{"slot_offset_minutes":30},"output":{"ok":true,"selected_slot_offset_minutes":30,"price_amount":30,"price_currency":"eur","expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient prefers an appointment in about 30 minutes"]},{"id":"submit_need","name":"Submit Medical Need","description":"Classify the patient medical need. Must run after select_slot while session is draft. Before calling, apply emergencyTriage if red flags are obvious — recommend ER/ambulance when clearly appropriate, but allow the patient to continue if they insist. Request body: { need: string }. Response allowed_check_outcome may be allowed, clarification_required, or not_allowed; status may become rejected.","tags":["booking","need-classification"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"POST","path":"/v1/booking/sessions/{booking_session_id}/need","operationId":"submitNeed"},"requires":["select_slot"],"produces":["need_submitted"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft","rejected"],"structuredExamples":[{"summary":"Need approved","input":{"need":"Headache and mild fever for two days"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"draft","allowed_check_outcome":"allowed","allowed":true,"next_step":"phone_verification","message_to_user":"Thank you. We can proceed with your booking."}}],"promptExamples":["Patient reports headache and fever for two days"]},{"id":"set_communication_channel","name":"Set Communication Channel","description":"Set how the patient receives post-booking communications. Call get_verification_channels first. When communication_channel=email, provide email in this request or via set_email first; the address is then locked until email verification completes. Phone OTP is still required separately via start_phone_verification. Request body: { communication_channel, email? }.","tags":["booking","communication"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/communication-channel","operationId":"setCommunicationChannel"},"requires":["get_verification_channels","submit_need"],"produces":["communication_channel_set"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft"],"structuredExamples":[{"summary":"SMS channel","input":{"communication_channel":"sms"},"output":{"ok":true,"communication_channel":"sms","phone_verification_path":"sms","email_verification_required":false,"expires_at":"2026-06-10T12:20:00.000Z"}},{"summary":"WhatsApp channel","input":{"communication_channel":"whatsapp"},"output":{"ok":true,"communication_channel":"whatsapp","phone_verification_path":"whatsapp","email_verification_required":false,"expires_at":"2026-06-10T12:20:00.000Z"}},{"summary":"Email channel (email in same request)","input":{"communication_channel":"email","email":"patient@example.com"},"output":{"ok":true,"communication_channel":"email","email_verification_required":true,"expires_at":"2026-06-10T12:20:00.000Z"}},{"summary":"Email channel (email pre-set via set_email)","input":{"communication_channel":"email"},"output":{"ok":true,"communication_channel":"email","email_verification_required":true,"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient wants SMS notifications","Patient prefers WhatsApp OTP","Patient wants email as contact channel after booking"]},{"id":"set_patient_first_name","name":"Set Patient First Name","description":"Set patient first name. Collect identity one field at a time — ask the patient for a single answer per step. Response includes profile_complete and missing remaining fields.","tags":["booking","patient"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/patient-info/first-name","operationId":"setPatientFirstName"},"requires":["submit_need"],"produces":["patient_first_name_set"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft"],"structuredExamples":[{"summary":"First name saved","input":{"first_name":"Maria"},"output":{"ok":true,"profile_complete":false,"missing":["last_name","gender"],"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient first name is Maria"]},{"id":"set_patient_last_name","name":"Set Patient Last Name","description":"Set patient last name. Collect identity one field at a time. Response includes profile_complete and missing remaining fields.","tags":["booking","patient"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/patient-info/last-name","operationId":"setPatientLastName"},"requires":["submit_need"],"produces":["patient_last_name_set"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft"],"structuredExamples":[{"summary":"Last name saved","input":{"last_name":"Garcia"},"output":{"ok":true,"profile_complete":false,"missing":["gender"],"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient last name is Garcia"]},{"id":"set_patient_gender","name":"Set Patient Gender","description":"Set patient gender (M, F, male, or female). Collect identity one field at a time. When profile_complete=true, proceed to phone verification.","tags":["booking","patient"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/patient-info/gender","operationId":"setPatientGender"},"requires":["submit_need"],"produces":["patient_profile_complete"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft"],"structuredExamples":[{"summary":"Profile complete","input":{"gender":"F"},"output":{"ok":true,"profile_complete":true,"missing":[],"expires_at":"2026-06-10T12:20:00.000Z"}}],"promptExamples":["Patient identifies as female"]},{"id":"set_email","name":"Set Patient Email","description":"Attach patient email for confirmation and Stripe prefill. Optional on any channel in draft (e.g. sms/whatsapp for Stripe prefill). When communication_channel=email, set email here or in set_communication_channel; it cannot be changed until verify_email_code succeeds. Request body: { email: string }.","tags":["booking","contact"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"PUT","path":"/v1/booking/sessions/{booking_session_id}/email","operationId":"setEmail"},"requires":["submit_need"],"produces":["email_attached"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["draft"],"structuredExamples":[{"summary":"Optional email on whatsapp channel (Stripe prefill)","input":{"email":"patient@example.com"},"output":{"ok":true,"expires_at":"2026-06-10T12:20:00.000Z"}},{"summary":"Email locked after email channel selected (422)","input":{"email":"other@example.com"},"output":{"error":"email_locked_pending_verification","message":"Email cannot be changed while email-channel verification is pending."}}],"promptExamples":["Add patient@example.com for Stripe prefill","Set email before choosing email communication channel"]},{"id":"start_phone_verification","name":"Start Phone Verification","description":"Send a 6-digit OTP via SMS or WhatsApp outbox. Requires draft session with slot, need approved, and profile complete. When communication_channel=email, pass channel (whatsapp|sms) for OTP delivery. Request body: { phone_e164, channel? } — phone_e164 in E.164 format (e.g. +393331234567).","tags":["booking","verification","otp"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"POST","path":"/v1/booking/sessions/{booking_session_id}/phone-verification","operationId":"startPhoneVerification"},"requires":["set_communication_channel","set_patient_gender"],"produces":["otp_sent"],"requiredContext":["booking_session_id"],"allowedStates":["draft"],"nextStates":["phone_pending"],"structuredExamples":[{"summary":"Send OTP (sms/whatsapp channel)","input":{"phone_e164":"+393331234567"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_pending","retry_after_seconds":30}},{"summary":"Send OTP when communication_channel=email (channel required)","input":{"phone_e164":"+59899123456","channel":"whatsapp"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_pending","retry_after_seconds":30}}],"promptExamples":["Send verification code to +393331234567","Patient chose email channel — send phone OTP via WhatsApp"]},{"id":"verify_phone_otp","name":"Verify Phone OTP","description":"Validate the OTP received by SMS or WhatsApp. On success status becomes phone_verified. For sms/whatsapp channel, response includes checkout_url (server redirect to Stripe). For email channel, response sets email_verification_required=true instead (no checkout until verify_email_code). Request body: { otp_code: string }. Field name is otp_code (not otp).","tags":["booking","verification","otp","payment"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"POST","path":"/v1/booking/sessions/{booking_session_id}/phone-verification/confirm","operationId":"verifyPhoneOtp"},"requires":["start_phone_verification"],"produces":["phone_verified","checkout_url","email_verification_required"],"requiredContext":["booking_session_id"],"allowedStates":["phone_pending"],"nextStates":["phone_verified","phone_pending"],"structuredExamples":[{"summary":"OTP accepted (sms/whatsapp)","input":{"otp_code":"482910"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_verified","checkout_url":"https://findapi.doctorsa.com/v1/booking/payment/open-checkout/cs_test_...","stripe_checkout_session_id":"cs_test_...","price_amount":55,"price_currency":"eur"}},{"summary":"OTP accepted (email channel — verify email before payment)","input":{"otp_code":"482910"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_verified","email_verification_required":true,"email":"patient@example.com","message_to_user":"Your phone is verified. Please verify your email address before proceeding to payment."}},{"summary":"Invalid OTP","input":{"otp_code":"000000"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_pending","error":"invalid_otp","message_to_user":"The code is incorrect or has expired. Please try again."}}],"promptExamples":["Patient entered OTP 482910"]},{"id":"start_email_verification","name":"Start Email Verification","description":"Send a 5-digit email verification code when communication_channel=email. Requires phone_verified status (after verify_phone_otp). Uses session email if body omits email; email cannot be changed while pending. Request body: { email?: string }. Returns status email_code_sent; does not change llm_booking_status.","tags":["booking","verification","email"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"POST","path":"/v1/booking/sessions/{booking_session_id}/email-verification","operationId":"startEmailVerification"},"requires":["verify_phone_otp"],"produces":["email_code_sent"],"requiredContext":["booking_session_id"],"allowedStates":["phone_verified"],"nextStates":["phone_verified"],"structuredExamples":[{"summary":"Send email code (body email)","input":{"email":"patient@example.com"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"email_code_sent","retry_after_seconds":120}},{"summary":"Send email code (session email, empty body)","input":{},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"email_code_sent","retry_after_seconds":120}}],"promptExamples":["Send email verification code to the locked session address"]},{"id":"verify_email_code","name":"Verify Email Code","description":"Validate the 5-digit code sent by email. On success returns status email_verified and checkout_url (payment gate cleared); llm_booking_status stays phone_verified. Email must match the locked session address. Request body: { code: string, email?: string }.","tags":["booking","verification","email"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"POST","path":"/v1/booking/sessions/{booking_session_id}/email-verification/confirm","operationId":"verifyEmailCode"},"requires":["start_email_verification"],"produces":["email_verified","checkout_url"],"requiredContext":["booking_session_id"],"allowedStates":["phone_verified"],"nextStates":["phone_verified"],"structuredExamples":[{"summary":"Code accepted","input":{"code":"48291","email":"patient@example.com"},"output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"email_verified","email":"patient@example.com","checkout_url":"https://findapi.doctorsa.com/v1/booking/payment/open-checkout/cs_test_...","stripe_checkout_session_id":"cs_test_...","price_amount":55,"price_currency":"eur"}}],"promptExamples":["Patient entered email code 48291"]},{"id":"get_payment_link","name":"Get Payment Link","description":"Re-fetch checkout_url when payment is allowed (phone_verified, and email verified when communication_channel=email). checkout_url is a server redirect (GET /v1/booking/payment/open-checkout/{stripe_checkout_session_id} → 302 to Stripe). Post-payment redirects use LLM_BOOKING_BASE_URL (/v1/booking/payment/success|cancel). No request body.","tags":["booking","payment"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"GET","path":"/v1/booking/sessions/{booking_session_id}/checkout","operationId":"getPaymentLink"},"requires":["verify_phone_otp"],"produces":["checkout_url"],"requiredContext":["booking_session_id"],"allowedStates":["phone_verified"],"nextStates":["phone_verified"],"structuredExamples":[{"summary":"Refresh checkout URL","output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_verified","checkout_url":"https://findapi.doctorsa.com/v1/booking/payment/open-checkout/cs_test_...","stripe_checkout_session_id":"cs_test_...","price_amount":55,"price_currency":"eur"}}],"promptExamples":["Patient lost the payment link — send it again"]},{"id":"reset_verification","name":"Reset Phone Verification","description":"Reset phone verification when the patient entered a wrong number. Allowed only in phone_pending. Clears phone_e164 and returns session to draft.","tags":["booking","verification"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"DELETE","path":"/v1/booking/sessions/{booking_session_id}/verification","operationId":"resetVerification"},"requires":["start_phone_verification"],"produces":["verification_reset"],"requiredContext":["booking_session_id"],"allowedStates":["phone_pending"],"nextStates":["draft"],"structuredExamples":[{"summary":"Reset to draft","output":{"ok":true,"status":"draft"}}],"promptExamples":["Wrong phone number — restart verification"]},{"id":"get_booking_status","name":"Get Booking Status","description":"Poll session status (`llm_booking_status`). When communication_channel=email, response also includes email_verified (and email_verified_at when true) so agents can distinguish phone_verified awaiting email vs ready for payment. Use after payment until assigned or a terminal state. Terminal: assigned, cancelled, rejected, expired.","tags":["booking","status"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"GET","path":"/v1/booking/sessions/{booking_session_id}","operationId":"getBookingStatus"},"requires":["create_booking_session"],"produces":["session_status"],"requiredContext":["booking_session_id"],"allowedStates":["draft","phone_pending","phone_verified","paid","assigned","rejected","expired","cancelled"],"nextStates":[],"structuredExamples":[{"summary":"Phone verified, email channel — awaiting email verification","output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_verified","email_verified":false,"price_amount":55,"price_currency":"eur","selected_slot_offset_minutes":30}},{"summary":"Phone verified, email channel — ready for payment","output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"phone_verified","email_verified":true,"email_verified_at":"2026-06-10T12:05:00.000Z","price_amount":55,"price_currency":"eur","selected_slot_offset_minutes":30}},{"summary":"Paid, awaiting doctor","output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"paid","price_amount":55,"price_currency":"eur","selected_slot_offset_minutes":30}},{"summary":"Doctor assigned","output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"assigned","appointment_time":"2026-06-10T13:00:00.000Z","doctor_name":"Dr. Rossi","video_url":"https://..."}}],"promptExamples":["Has a doctor been assigned yet?"]},{"id":"cancel_booking_session","name":"Cancel Booking Session","description":"Cancel at any non-terminal stage. If paid and unassigned, a Stripe refund is attempted. Response may include refund_status.","tags":["booking","cancellation","refund"],"inputModes":["application/json"],"outputModes":["application/json"],"endpoint":{"method":"DELETE","path":"/v1/booking/sessions/{booking_session_id}","operationId":"cancelBookingSession"},"requires":["create_booking_session"],"produces":["session_cancelled"],"requiredContext":["booking_session_id"],"allowedStates":["draft","phone_pending","phone_verified","paid"],"nextStates":["cancelled"],"structuredExamples":[{"summary":"Cancel before payment","output":{"booking_session_id":"550e8400-e29b-41d4-a716-446655440000","status":"cancelled","cancel_reason":"user_cancelled_pre_payment"}}],"promptExamples":["Patient wants to cancel the booking"]}]}