{"openapi":"3.1.0","info":{"title":"Robotkong Tour Engine API","description":"AI-accessible booking infrastructure for free walking tours. This API exposes MCP (Model Context Protocol) tools via a JSON-RPC endpoint. Use the /mcp endpoint with JSON-RPC 2.0 format to invoke tools.","version":"1.0.0","contact":{"email":"api@robotkong.com","url":"https://www.robotkong.com"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://www.robotkong.com","description":"Production server"}],"paths":{"/mcp":{"post":{"operationId":"invokeMcpTool","summary":"Invoke an MCP tool","description":"JSON-RPC 2.0 endpoint for invoking MCP tools. Use method \"tools/call\" with the tool name and arguments.","security":[{"bearerAuth":[]},{}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"},"examples":{"search_tours":{"summary":"Search for tours","value":{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_tours","arguments":{"location":"Madrid","date_from":"2026-02-01","limit":10}}}},"create_booking":{"summary":"Create a booking","value":{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"create_booking","arguments":{"offering_id":"12345","name":"John Doe","email":"john@example.com","adults":2,"external_provider":"getyourguide","external_provider_identifier":"GYG-ABC-123","bypass_availability":false,"source_subchannel":"workflow:booking-sync","source_idempotency_key":"booking-sync:getyourguide:GYG-ABC-123:12345","operation_id":"3d0c4f7b-32c0-4ec5-8e7a-8f9fd54fd13d"}}}},"find_booking_strict":{"summary":"Strict booking match","value":{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"find_booking","arguments":{"mode":"strict","query":"Danny Jackson dania@gmail.com","company_id":1,"offering_id":"65","status":"all"}}}}}}}},"responses":{"200":{"description":"Tool execution result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}}}}}}},"/.well-known/mcp.json":{"get":{"operationId":"getMcpDiscovery","summary":"MCP discovery file","description":"Returns MCP server metadata including available tools and authentication requirements.","responses":{"200":{"description":"MCP discovery metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpDiscovery"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key in format: rk_{uuid}. Supports three scope levels: company (single company), organisation (all companies in org), and platform (all companies). Optional for public tools."}},"schemas":{"JsonRpcRequest":{"type":"object","required":["jsonrpc","method","params"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"oneOf":[{"type":"string"},{"type":"number"}]},"method":{"type":"string","enum":["tools/call","tools/list","resources/list","resources/read"]},"params":{"type":"object","properties":{"name":{"type":"string","description":"Tool name to invoke"},"arguments":{"type":"object","description":"Tool-specific arguments"}}}}},"JsonRpcResponse":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"oneOf":[{"type":"string"},{"type":"number"}]},"result":{"type":"object","properties":{"content":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"text":{"type":"string"}}}},"structuredContent":{"type":"object","description":"Typed response data"},"isError":{"type":"boolean"}}},"error":{"type":"object","properties":{"code":{"type":"number"},"message":{"type":"string"}}}}},"McpDiscovery":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"version":{"type":"string"},"endpoints":{"type":"object","properties":{"mcp":{"type":"object","properties":{"url":{"type":"string"},"transport":{"type":"string"}}},"openapi":{"type":"object","properties":{"url":{"type":"string"}}}}},"tools":{"type":"array","items":{"type":"string"}},"authentication":{"type":"object"}}},"ToursSearchInput":{"type":"object","properties":{"mode":{"type":"string","enum":["locations","search","details"]},"offering_id":{"type":"string","description":"Get full details for a specific offering"},"location":{"type":"string","description":"City/country/location keyword"},"locations":{"type":"array","items":{"type":"string"}},"date":{"type":"string","format":"date","description":"Specific date (YYYY-MM-DD)"},"date_from":{"type":"string","format":"date","description":"Start of date range"},"date_to":{"type":"string","format":"date","description":"End of date range"},"company_id":{"type":"integer"},"company_ids":{"type":"array","items":{"type":"integer"}},"company_name":{"type":"string"},"company_names":{"type":"array","items":{"type":"string"}},"tour_id":{"type":"integer"},"tour_ids":{"type":"array","items":{"type":"integer"}},"limit":{"type":"number","minimum":1,"maximum":50,"default":10},"cursor":{"type":"string"}}},"ToursSearchOutput":{"type":"object","properties":{"tours":{"type":"array","items":{"$ref":"#/components/schemas/Tour"}},"tour":{"type":"object"},"booking_ready":{"type":"boolean"},"locations":{"type":"array","items":{"type":"object"}},"count":{"type":"number"}}},"Tour":{"type":"object","properties":{"offering_id":{"type":"string"},"tour_id":{"type":"string","nullable":true},"title":{"type":"string"},"location":{"type":"string","nullable":true},"date":{"type":"string","format":"date"},"time":{"type":"string"},"duration_minutes":{"type":"number","nullable":true},"language":{"type":"string"},"meeting_point":{"type":"object","properties":{"description":{"type":"string","nullable":true},"address":{"type":"string","nullable":true},"map_link":{"type":"string","nullable":true}}},"availability":{"type":"object","properties":{"total_seats":{"type":"number"},"booked_seats":{"type":"number"},"available_seats":{"type":"number"}}},"company_name":{"type":"string"},"is_free":{"type":"boolean"},"price":{"type":"number","nullable":true},"currency":{"type":"string","nullable":true}}},"BookingsCreateInput":{"type":"object","required":["offering_id","name"],"properties":{"offering_id":{"type":"string","description":"The offering ID to book"},"name":{"type":"string","description":"Guest name"},"email":{"type":"string","format":"email","description":"Guest email (optional). If provided, must be a valid email."},"phone":{"type":"string","description":"Guest phone number"},"adults":{"type":"number","minimum":1,"maximum":40,"default":1},"children":{"type":"number","minimum":0,"maximum":20,"default":0},"country":{"type":"string","description":"Guest country (2-letter code)"},"comments":{"type":"string","description":"Special requests"},"company_id":{"type":"integer","description":"Optional company guard; offering must belong to this company"},"company_ids":{"type":"array","items":{"type":"integer"},"description":"Optional multi-company guard; offering must belong to one of these companies"},"validate_only":{"type":"boolean","default":false,"description":"Dry run only: validate input + availability without creating a booking"},"bypass_availability":{"type":"boolean","default":false,"description":"Force-create booking even when requested adults exceed available spots. Use cautiously."},"bypass_duplicate_check":{"type":"boolean","default":false,"description":"Allow booking creation even when strict duplicate hard matches are detected."},"include_cancelled_duplicates":{"type":"boolean","default":true,"description":"When true, cancelled bookings are also treated as hard duplicate matches."},"external_provider_identifier":{"type":"string","description":"External booking identifier from external provider; pair with external_provider"},"external_provider":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"External provider key/alias (string) or provider id (number); pair with external_provider_identifier"},"source_subchannel":{"type":"string","description":"Optional MCP source subchannel label (for example workflow:booking-sync)."},"source_origin":{"type":"string","description":"Optional source origin label. Defaults to mcp:create_booking and is ignored for unauthenticated requests."},"source_idempotency_key":{"type":"string","description":"Optional idempotency key for replay safety. If omitted, server infers a deterministic key."},"operation_id":{"type":"string","format":"uuid","description":"Optional operation correlation ID for linking related external workflow actions."}}},"BookingsCreateOutput":{"type":"object","properties":{"booking_id":{"type":"string","format":"uuid"},"status":{"type":"string"},"message":{"type":"string"},"availability":{"type":"object","nullable":true},"details":{"type":"object","nullable":true}}},"Booking":{"type":"object","properties":{"booking_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["confirmed","cancelled"]},"check_in_status":{"type":"string","enum":["checked_in","no_show","pending"]},"guest":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"}}},"tour":{"type":"object","properties":{"offering_id":{"type":"string"},"tour_id":{"type":"string"},"company":{"type":"string"},"title":{"type":"string"},"date":{"type":"string","format":"date"},"time":{"type":"string"},"language":{"type":"string"}}}}},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"x-mcp-tools":[{"name":"search_tours","description":"Search tours by location/date, fetch details by offering_id, or list available locations.","inputSchema":{"$ref":"#/components/schemas/ToursSearchInput"},"outputSchema":{"$ref":"#/components/schemas/ToursSearchOutput"},"authentication":"optional","scopes":["tours:read"]},{"name":"find_booking","description":"Find bookings by booking UUID lookup, date manifest, or search signals (name/query/email/external pair). Strict mode returns 0 or 1 deterministic match.","inputSchema":{"type":"object","properties":{"mode":{"type":"string","enum":["search","lookup","manifest","strict"]},"query":{"type":"string","description":"Legacy name signal. Ignored when name is provided."},"name":{"type":"string"},"booking_id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email","description":"Search signal. Also required for public lookup mode."},"external_provider_identifier":{"type":"string"},"external_provider":{"oneOf":[{"type":"string"},{"type":"integer"}],"description":"External provider key/alias string or provider id. Must be paired with external_provider_identifier."},"date":{"type":"string","format":"date"},"company_id":{"type":"integer"},"company_ids":{"type":"array","items":{"type":"integer"}},"tour_id":{"type":"integer"},"tour_ids":{"type":"array","items":{"type":"integer"}},"offering_id":{"type":"string"},"offering_ids":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["all","confirmed","cancelled"],"default":"all"},"limit":{"type":"number","minimum":1,"maximum":100},"cursor":{"type":"string"}}},"outputSchema":{"type":"object","properties":{"bookings":{"type":"array","items":{"$ref":"#/components/schemas/Booking"}},"count":{"type":"number"},"date":{"type":"string","nullable":true},"summary":{"type":"object","nullable":true},"details":{"type":"object","nullable":true}}},"authentication":"optional","scopes":["bookings:read"],"notes":"external_provider_identifier and external_provider must both be provided if either is present. Strict mode requires company_id + offering_id + at least one search signal, returns 0 or 1 result, and includes details.match_analysis diagnostics (hard matches, near overlaps, confidence)."},{"name":"create_booking","description":"Create a booking for a specific offering. Supports optional external provider linkage via external_provider + external_provider_identifier.","inputSchema":{"$ref":"#/components/schemas/BookingsCreateInput"},"outputSchema":{"$ref":"#/components/schemas/BookingsCreateOutput"},"authentication":"optional","scopes":["bookings:write"],"notes":"external_provider_identifier and external_provider must both be provided if either is present. external_provider accepts provider id (number) or provider key/alias (string). bypass_availability and bypass_duplicate_check are authenticated override flags. include_cancelled_duplicates controls whether cancelled bookings can hard-block duplicate checks. Source attribution is MCP-first: source_channel is forced to mcp, and source_subchannel/source_origin/source_idempotency_key/operation_id are optional inputs."},{"name":"update_booking","description":"Update guest/group fields for an existing booking.","inputSchema":{"type":"object","required":["booking_id"],"properties":{"booking_id":{"type":"string","format":"uuid"},"company_id":{"type":"integer"},"company_ids":{"type":"array","items":{"type":"integer"}},"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"adults":{"type":"number","minimum":1,"maximum":40},"children":{"type":"number","minimum":0,"maximum":20},"country":{"type":"string"},"comments":{"type":"string"},"validate_only":{"type":"boolean"}}},"authentication":"required","scopes":["bookings:write"]},{"name":"cancel_booking","description":"Cancel an existing booking by booking_id.","inputSchema":{"type":"object","required":["booking_id"],"properties":{"booking_id":{"type":"string","format":"uuid"},"company_id":{"type":"integer"},"company_ids":{"type":"array","items":{"type":"integer"}},"reason":{"type":"string"},"validate_only":{"type":"boolean"}}},"authentication":"required","scopes":["bookings:write"]},{"name":"get_report","description":"Generate business report metrics and analytics.","inputSchema":{"type":"object","properties":{"date_from":{"type":"string","format":"date"},"date_to":{"type":"string","format":"date"},"group_by":{"type":"string","enum":["none","day","month","year"]},"include_checkins":{"type":"boolean"},"tour_id":{"type":"string"},"tour_ids":{"type":"array","items":{"type":"integer"}},"company_id":{"type":"integer"},"company_ids":{"type":"array","items":{"type":"integer"}},"offering_id":{"type":"string"},"offering_ids":{"type":"array","items":{"type":"string"}},"location":{"type":"string"},"locations":{"type":"array","items":{"type":"string"}},"company_name":{"type":"string"},"company_names":{"type":"array","items":{"type":"string"}},"compare_previous":{"type":"boolean"}}},"authentication":"required","scopes":["analytics:read"]}]}