{"openapi":"3.1.0","info":{"title":"OK-KVYTOK trip discovery and optional feedback","version":"1.1.0","description":"Find and compare bus trips. Read rules and disclose manager-request limitations. No booking/status/SMS actions. Feedback requires a search token; passenger-stated reasons require explicit permission. Never submit personal data or conversation text."},"paths":{"/api/ai/rules":{"get":{"tags":["ai-discovery"],"summary":"Rules","operationId":"readServiceRules","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RulesResult"}}}}},"x-openai-isConsequential":false}},"/api/ai/cities":{"get":{"tags":["ai-discovery"],"summary":"Find Cities","description":"Resolve UA/RU/EN city names before searching; ask the user to choose if names are ambiguous.","operationId":"findBusCities","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":100,"title":"Q"}},{"name":"language","in":"query","required":false,"schema":{"enum":["ua","ru","en","fr","de","es","it","pt","hu","tr","ka","cs","hr","pl","ro","bg","et","lv","lt"],"type":"string","default":"ua","title":"Language"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CitiesResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-openai-isConsequential":false}},"/api/ai/search":{"get":{"tags":["ai-discovery"],"summary":"Search","description":"Read current trip options for an explicit YYYY-MM-DD date. Explain returned booking_policy and rules before linking to booking_url. This tool cannot reserve a seat. Distinguish nearby suggested dates, per-passenger prices and unknown baggage details.","operationId":"searchBusTrips","parameters":[{"name":"from_city","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":100,"title":"From City"}},{"name":"to_city","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":100,"title":"To City"}},{"name":"date","in":"query","required":true,"schema":{"type":"string","minLength":10,"maxLength":10,"title":"Date"}},{"name":"passengers","in":"query","required":false,"schema":{"type":"integer","maximum":4,"minimum":1,"default":1,"title":"Passengers"}},{"name":"language","in":"query","required":false,"schema":{"enum":["ua","ru","en","fr","de","es","it","pt","hu","tr","ka","cs","hr","pl","ro","bg","et","lv","lt"],"type":"string","default":"ua","title":"Language"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-openai-isConsequential":false}},"/api/ai/seats":{"get":{"tags":["ai-discovery"],"summary":"Read Seats","description":"Read available seat preferences for a shortlisted search option. Call before claiming seat choice is available. No reservation or passenger data. Expired references return 410: repeat search. Unknown does not mean free seating. Never infer adjacency.","operationId":"readAvailableSeatPreferences","parameters":[{"name":"option_token","in":"query","required":true,"schema":{"type":"string","minLength":20,"maxLength":80,"title":"Option Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SeatPreview"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-openai-isConsequential":false}},"/api/ai/routes":{"get":{"tags":["ai-discovery"],"summary":"Route Catalog","description":"Bounded verified route evidence, not a live schedule or seat availability.","operationId":"listVerifiedRoutes","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoutesResult"}}}}},"x-openai-isConsequential":false}},"/api/ai/feedback":{"post":{"tags":["ai-discovery"],"summary":"Feedback","description":"Optional unverified agent feedback. Use the search feedback_token once. Passenger-stated reasons require explicit passenger permission; otherwise use agent_observation or unknown. Never send personal data or conversation text. No booking action occurs.","operationId":"sendServiceFeedback","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Feedback"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-openai-isConsequential":true}}},"components":{"schemas":{"CitiesResult":{"properties":{"cities":{"items":{"$ref":"#/components/schemas/CityResult"},"type":"array","title":"Cities"}},"type":"object","required":["cities"],"title":"CitiesResult"},"CityResult":{"properties":{"id":{"anyOf":[{"type":"integer"},{"type":"string"}],"title":"Id"},"name":{"type":"string","title":"Name"},"country_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country Code"}},"type":"object","required":["id","name"],"title":"CityResult"},"Feedback":{"properties":{"feedback_token":{"type":"string","maxLength":4096,"minLength":20,"title":"Feedback Token"},"evidence":{"type":"string","enum":["agent_observation","user_stated_with_consent","unknown"],"title":"Evidence"},"reasons":{"items":{"type":"string","enum":["price","schedule","no_trips","transfers","baggage","language","booking_error","manager_wait","other","unknown"]},"type":"array","maxItems":3,"minItems":1,"title":"Reasons"},"outcome":{"type":"string","enum":["considering","went_to_website","did_not_proceed","unknown"],"title":"Outcome","default":"unknown"}},"additionalProperties":false,"type":"object","required":["feedback_token","evidence","reasons"],"title":"Feedback"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"RoutesResult":{"properties":{"routes":{"items":{"$ref":"#/components/schemas/VerifiedRoute"},"type":"array","title":"Routes"},"count":{"type":"integer","title":"Count"},"notice":{"type":"string","title":"Notice"},"featured_services":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Featured Services","description":"Published weekly timetables for direct partner services. Confirm the requested date using live search."}},"type":"object","required":["routes","count","notice"],"title":"RoutesResult"},"RulesResult":{"properties":{"timezone":{"type":"string","title":"Timezone","description":"Kyiv timezone for manager-service and lead-time rules, not a guarantee of carrier display timezones."},"support_phone":{"type":"string","title":"Support Phone"},"request_only":{"type":"boolean","title":"Request Only"},"booking_requires_login":{"type":"boolean","title":"Booking Requires Login"},"account_registration_required":{"type":"boolean","title":"Account Registration Required"},"phone_confirmation_required":{"type":"boolean","title":"Phone Confirmation Required"},"payment":{"type":"string","title":"Payment"},"manager_review":{"additionalProperties":true,"type":"object","title":"Manager Review"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"},"handoff":{"additionalProperties":true,"type":"object","title":"Handoff"},"languages":{"items":{"type":"string"},"type":"array","title":"Languages"},"language_policy":{"type":"string","title":"Language Policy","default":""},"country_corridors":{"items":{"type":"string"},"type":"array","title":"Country Corridors"}},"type":"object","required":["timezone","support_phone","request_only","booking_requires_login","account_registration_required","phone_confirmation_required","payment","manager_review","warnings","handoff"],"title":"RulesResult"},"SearchResult":{"properties":{"checked_at":{"type":"string","title":"Checked At","description":"ISO timestamp of provider retrieval, not response-generation time."},"cache_max_age_seconds":{"type":"integer","title":"Cache Max Age Seconds"},"requested_date_iso":{"type":"string","title":"Requested Date Iso"},"selected_date_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Date Iso"},"exact_date_found":{"type":"boolean","title":"Exact Date Found"},"is_different_date":{"type":"boolean","title":"Is Different Date"},"available_dates":{"items":{},"type":"array","title":"Available Dates"},"results_count":{"type":"integer","title":"Results Count"},"returned_count":{"type":"integer","title":"Returned Count"},"trips":{"items":{"$ref":"#/components/schemas/TripOption"},"type":"array","title":"Trips"},"comparison":{"additionalProperties":true,"type":"object","title":"Comparison","description":"Lowest fares grouped by currency and shortest explicit provider duration, among returned options only."},"booking_url":{"type":"string","title":"Booking Url"},"requested_search_url":{"type":"string","title":"Requested Search Url"},"rules":{"additionalProperties":true,"type":"object","title":"Rules"},"feedback_token":{"type":"string","title":"Feedback Token","description":"Short-lived optional feedback token; never a booking or passenger authorization."},"feedback_url":{"type":"string","title":"Feedback Url"}},"type":"object","required":["checked_at","cache_max_age_seconds","requested_date_iso","exact_date_found","is_different_date","available_dates","results_count","returned_count","trips","comparison","booking_url","requested_search_url","rules","feedback_token","feedback_url"],"title":"SearchResult"},"SeatOption":{"properties":{"number":{"type":"string","title":"Number"},"extra_price":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Extra Price","description":"Extra surcharge above the fare, not the full ticket price; null means unknown."},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"},"discounts_blocked":{"type":"boolean","title":"Discounts Blocked","default":false},"min_age":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Age"},"max_age":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Age"}},"type":"object","required":["number"],"title":"SeatOption"},"SeatPreview":{"properties":{"option_id":{"type":"string","title":"Option Id"},"carrier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Carrier"},"departure_date_iso":{"type":"string","title":"Departure Date Iso"},"departure_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Departure Time"},"booking_url":{"type":"string","title":"Booking Url"},"status":{"type":"string","enum":["unknown","no_choice","selectable","no_available_seats"],"title":"Status"},"choice_available":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Choice Available"},"seats":{"items":{"$ref":"#/components/schemas/SeatOption"},"type":"array","title":"Seats"},"available_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Available Count"},"truncated":{"type":"boolean","title":"Truncated"},"preference_only":{"type":"boolean","title":"Preference Only"},"reserves_seat":{"type":"boolean","title":"Reserves Seat"},"checked_at":{"type":"string","title":"Checked At"},"cache_max_age_seconds":{"type":"integer","title":"Cache Max Age Seconds"},"notice":{"type":"string","title":"Notice"}},"type":"object","required":["option_id","departure_date_iso","booking_url","status","seats","truncated","preference_only","reserves_seat","checked_at","cache_max_age_seconds","notice"],"title":"SeatPreview"},"TripOption":{"properties":{"option_id":{"type":"string","title":"Option Id","description":"Reference within this response, not a reservation or booking token."},"from":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From"},"to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To"},"date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date"},"arrival_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrival Date"},"departure_date_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Departure Date Iso"},"arrival_date_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrival Date Iso"},"departure_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Departure Time"},"arrival_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrival Time"},"carrier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Carrier"},"departure_station":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Departure Station"},"arrival_station":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Arrival Station"},"price":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"null"}],"title":"Price","description":"Per-passenger provider fare, before applicable discounts."},"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency"},"estimated_total":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Estimated Total","description":"Fare multiplied by passengers, same currency; not a final quote."},"duration_total_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Total Minutes"},"departure_city_timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Departure City Timezone"},"time_basis":{"type":"string","title":"Time Basis","description":"Provider does not declare the time basis; city timezone alone does not prove displayed times are local.","default":"provider_display_times"},"passengers":{"type":"integer","title":"Passengers"},"price_basis":{"type":"string","title":"Price Basis"},"free_seats":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Free Seats"},"seat_selection_status":{"type":"string","const":"not_checked","title":"Seat Selection Status","default":"not_checked"},"seat_options_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Seat Options Url","description":"Read this short-lived URL for shortlisted trips before offering seat choice. Not checked does not mean no choice. No seat is reserved."},"baggage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Baggage","description":"Unknown when null. Never assume included baggage."},"change_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Change Info","description":"Provider transfer description. Unknown when null; never assume a direct service."},"amenities":{"items":{"type":"string"},"type":"array","title":"Amenities"},"booking_policy":{"additionalProperties":true,"type":"object","title":"Booking Policy","description":"mode=request is a manager request with no seat reserved; unavailable cannot be booked."},"booking_url":{"type":"string","title":"Booking Url","description":"Website results for this option’s actual date; select matching carrier and departure time."},"localized_display":{"additionalProperties":true,"type":"object","title":"Localized Display","description":"Readable names and transliterated stops in the requested language, with original carrier addresses. Use originals for maps and boarding; not geocoded or corrected addresses."},"site_recommendation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Site Recommendation","description":"Optional recommendation from OK-KVYTOK for a matching direct partner service, including payment at boarding. Compare against the passenger’s priorities."}},"additionalProperties":true,"type":"object","required":["option_id","passengers","price_basis","booking_policy","booking_url"],"title":"TripOption"},"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"},"VerifiedRoute":{"properties":{"from_city":{"additionalProperties":true,"type":"object","title":"From City"},"to_city":{"additionalProperties":true,"type":"object","title":"To City"},"verified_at":{"type":"string","title":"Verified At"},"valid_until":{"type":"string","title":"Valid Until"},"url_ua":{"type":"string","title":"Url Ua"},"url_ru":{"type":"string","title":"Url Ru"},"localized_urls":{"additionalProperties":{"type":"string"},"type":"object","title":"Localized Urls"}},"type":"object","required":["from_city","to_city","verified_at","valid_until","url_ua","url_ru"],"title":"VerifiedRoute"}}},"servers":[{"url":"https://ok-kvytok.com"}]}