{"openapi":"3.1.0","info":{"title":"Book&Eat Public Agent Reservation API","version":"1.0.0","description":"Public API for agents to check restaurant availability and create reservations through Book&Eat."},"servers":[{"url":"https://www.bookandeat.eu/functions/v1","description":"Book&Eat public functions endpoint"}],"paths":{"/public-agent-reservations":{"post":{"operationId":"bookandeatPublicAgentReservation","summary":"Check availability, create, modify, or cancel a restaurant reservation","description":"Use check_availability first. Use create_reservation only after collecting guest consent and final reservation details. Use check_modification_availability before modify_reservation. Use modify_reservation or cancel_reservation only with the cancellation_token returned by create_reservation or present in the guest booking confirmation. Always send a unique idempotency_key for create_reservation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CheckAvailabilityRequest"},{"$ref":"#/components/schemas/CreateReservationRequest"},{"$ref":"#/components/schemas/CheckModificationAvailabilityRequest"},{"$ref":"#/components/schemas/ModifyReservationRequest"},{"$ref":"#/components/schemas/CancelReservationRequest"}]}}}},"responses":{"200":{"description":"Availability result, successful reservation, modification, cancellation, pending reservation, or card-required reservation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentReservationResponse"}}}},"400":{"description":"Invalid request."},"409":{"description":"Idempotency conflict or request still processing."},"429":{"description":"Rate limited. Retry after retry_after_seconds."}}}},"/public-agent-discovery":{"get":{"operationId":"bookandeatPublicAgentDiscovery","summary":"Get OpenAPI schema or restaurant-specific agent manifest","parameters":[{"name":"mode","in":"query","required":false,"schema":{"type":"string","enum":["openapi","directory","manifest"]}},{"name":"restaurant_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"slug","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Discovery document."},"404":{"description":"Restaurant not found."}}}},"/get-widget-settings":{"get":{"operationId":"bookandeatSearchPublicRestaurants","summary":"Search public Book&Eat restaurants","description":"Find public restaurants by name, city, cuisine, country, or address before checking availability or creating a reservation.","parameters":[{"name":"mode","in":"query","required":true,"schema":{"type":"string","const":"public_restaurants"},"description":"Must be public_restaurants."},{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Optional search text, for example restaurant name, city, cuisine, or address."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":500,"default":20}}],"responses":{"200":{"description":"Public restaurant search results with restaurant_id, public page URLs, reservation URLs and widget URLs where enabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicRestaurantSearchResponse"}}}}}}}},"components":{"schemas":{"PublicRestaurantSearchResponse":{"type":"object","properties":{"restaurants":{"type":"array","items":{"type":"object","properties":{"restaurant_id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":"string"},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"cuisine_type":{"type":["string","null"]},"reservation_enabled":{"type":"boolean"},"reserve_url":{"type":["string","null"]},"public_booking_url":{"type":["string","null"]},"widget_url":{"type":["string","null"]}}}},"count":{"type":"integer"}}},"CheckAvailabilityRequest":{"type":"object","required":["action","restaurant_id","booking_date","party_size"],"properties":{"action":{"type":"string","const":"check_availability"},"restaurant_id":{"type":"integer"},"booking_date":{"type":"string","format":"date"},"booking_time":{"type":"string","pattern":"^\\d{2}:\\d{2}$"},"party_size":{"type":"integer","minimum":1,"maximum":20},"agent_source":{"type":"string","description":"Agent provider name, for example chatgpt, muse, claude, gemini."}}},"CreateReservationRequest":{"type":"object","required":["action","restaurant_id","booking_date","booking_time","party_size","customer_name","customer_email","idempotency_key"],"properties":{"action":{"type":"string","const":"create_reservation"},"restaurant_id":{"type":"integer"},"booking_date":{"type":"string","format":"date"},"booking_time":{"type":"string","pattern":"^\\d{2}:\\d{2}$"},"party_size":{"type":"integer","minimum":1,"maximum":20},"customer_name":{"type":"string","minLength":1},"customer_email":{"type":"string","format":"email"},"customer_phone":{"type":"string"},"special_requests":{"type":"string"},"language":{"type":"string","default":"en"},"idempotency_key":{"type":"string","description":"Unique per final reservation attempt. Reuse only to retry exactly the same reservation."},"agent_source":{"type":"string","description":"Agent provider name, for example chatgpt, muse, claude, gemini."}}},"CancelReservationRequest":{"type":"object","required":["action","cancellation_token"],"properties":{"action":{"type":"string","const":"cancel_reservation"},"cancellation_token":{"type":"string","description":"Secure token from the reservation confirmation or create_reservation response."},"booking_id":{"type":"integer","description":"Optional extra verification. Must match the cancellation token if provided."},"restaurant_id":{"type":"integer","description":"Optional extra verification. Must match the cancellation token if provided."},"customer_email":{"type":"string","format":"email","description":"Optional extra verification. Must match the booking email if provided."},"cancellation_reason":{"type":"string"},"language":{"type":"string","default":"en"},"idempotency_key":{"type":"string","description":"Optional client retry key. Cancellation is token-idempotent server-side."},"agent_source":{"type":"string","description":"Agent provider name, for example chatgpt, muse, claude, gemini."}}},"CheckModificationAvailabilityRequest":{"type":"object","required":["action","cancellation_token","new_booking_date","new_booking_time","new_party_size"],"properties":{"action":{"type":"string","const":"check_modification_availability"},"cancellation_token":{"type":"string","description":"Secure token from the reservation confirmation or create_reservation response."},"booking_id":{"type":"integer","description":"Optional extra verification. Must match the cancellation token if provided."},"restaurant_id":{"type":"integer","description":"Optional extra verification. Must match the cancellation token if provided."},"customer_email":{"type":"string","format":"email","description":"Optional extra verification. Must match the booking email if provided."},"new_booking_date":{"type":"string","format":"date"},"new_booking_time":{"type":"string","pattern":"^\\d{2}:\\d{2}$"},"new_party_size":{"type":"integer","minimum":1,"maximum":20},"new_special_requests":{"type":"string"},"language":{"type":"string","default":"en"},"agent_source":{"type":"string","description":"Agent provider name, for example chatgpt, muse, claude, gemini."}}},"ModifyReservationRequest":{"type":"object","required":["action","cancellation_token","new_booking_date","new_booking_time","new_party_size"],"properties":{"action":{"type":"string","const":"modify_reservation"},"cancellation_token":{"type":"string","description":"Secure token from the reservation confirmation or create_reservation response."},"booking_id":{"type":"integer","description":"Optional extra verification. Must match the cancellation token if provided."},"restaurant_id":{"type":"integer","description":"Optional extra verification. Must match the cancellation token if provided."},"customer_email":{"type":"string","format":"email","description":"Optional extra verification. Must match the booking email if provided."},"new_booking_date":{"type":"string","format":"date"},"new_booking_time":{"type":"string","pattern":"^\\d{2}:\\d{2}$"},"new_party_size":{"type":"integer","minimum":1,"maximum":20},"new_special_requests":{"type":"string"},"language":{"type":"string","default":"en"},"idempotency_key":{"type":"string","description":"Optional client retry key. Modification is guarded by the reservation token and table conflict checks."},"agent_source":{"type":"string","description":"Agent provider name, for example chatgpt, muse, claude, gemini."}}},"AgentReservationResponse":{"type":"object","properties":{"success":{"type":"boolean"},"action":{"type":"string","enum":["check_availability","create_reservation","cancel_reservation","check_modification_availability","modify_reservation"]},"status":{"type":"string","enum":["available","unavailable","confirmed","modification_available","modification_unavailable","modified","cancelled","already_cancelled","pending","card_required","rate_limited","reservations_unavailable","idempotency_conflict","request_processing","error"]},"restaurant_id":{"type":["integer","null"]},"restaurant_name":{"type":["string","null"]},"date":{"type":["string","null"]},"time":{"type":["string","null"]},"party_size":{"type":["integer","null"]},"customer_name":{"type":["string","null"]},"customer_email":{"type":["string","null"]},"booking_id":{"type":["integer","null"]},"message":{"type":"string"},"error":{"type":["string","null"]},"next_action":{"type":["object","null"],"additionalProperties":true},"confirmation":{"type":"object","description":"Stable human-readable confirmation payload for agents to show the guest.","properties":{"status":{"type":"string"},"restaurant_name":{"type":["string","null"]},"date":{"type":["string","null"]},"time":{"type":["string","null"]},"party_size":{"type":["integer","null"]},"customer_name":{"type":["string","null"]},"customer_email":{"type":["string","null"]},"booking_id":{"type":["integer","null"]},"summary":{"type":"string"}}},"retry_after_seconds":{"type":"integer"},"idempotent_replay":{"type":"boolean"},"cancellation_token":{"type":"string"},"cancellation_url":{"type":"string"},"cancellation":{"type":["object","null"],"additionalProperties":true},"previous_reservation":{"type":["object","null"],"additionalProperties":true},"modification":{"type":["object","null"],"additionalProperties":true}}}}},"x-bookandeat-agent-instructions":{"flow":["Find the restaurant through /get-widget-settings?mode=public_restaurants&q={query} or the public restaurant page.","Resolve the restaurant from the public page or manifest.","Call check_availability for the requested date and party size.","Ask the user to confirm the exact time and guest details.","Call create_reservation with a unique idempotency_key.","For later cancellation, keep the returned cancellation_token with the guest confirmation.","For later modification, keep the returned cancellation_token and call check_modification_availability before modify_reservation.","Call cancel_reservation only after the user explicitly asks to cancel and confirms the exact reservation.","Report confirmed, pending, card_required, modification_available, modified, cancelled, already_cancelled, unavailable, or rate_limited exactly as returned."],"safety":{"idempotency_required_for_create_reservation":true,"create_reservation_is_rate_limited":true,"cancel_reservation_requires_cancellation_token":true,"modify_reservation_requires_cancellation_token":true,"do_not_create_without_user_confirmation":true,"do_not_cancel_without_user_confirmation":true,"do_not_modify_without_user_confirmation":true}}}