{"openapi":"3.1.0","info":{"title":"Yoteiko AI Integration API","description":"Production-ready API for AI assistants to interact with Yoteiko, the travel planning platform.\n\n## Supported AI Platforms\n- **ChatGPT Actions** — Native integration via OAuth 2.0\n- **OpenAI Apps** — Bearer token authentication\n- **Claude** — OpenAPI-compatible endpoints\n- **Google Gemini** — REST API with structured responses\n- **Microsoft Copilot** — OpenAPI 3.1 compliant\n- **Perplexity** — Direct API access\n- **MCP Clients** — Model Context Protocol compatible\n\n## Authentication\nThis API supports two authentication methods:\n1. **Cookie Auth** — For web-based users (JWT in httpOnly cookies)\n2. **Bearer Token** — For AI agents (JWT in Authorization header)\n\n## Rate Limits\n- **Read operations**: 100 requests per minute\n- **Write operations**: 30 requests per minute\n\n## Base URL\n```\nhttps://api.yoteiko.com/api/ai\n```","version":"2.0.0","contact":{"name":"Yoteiko API Support","email":"info@yoteiko.com","url":"https://yoteiko.com/ai"},"license":{"name":"Proprietary","url":"https://yoteiko.com/terms"}},"servers":[{"url":"https://api.yoteiko.com/api/ai","description":"Production"},{"url":"https://staging-api.yoteiko.com/api/ai","description":"Staging"},{"url":"http://localhost:8002/api/ai","description":"Local Development"}],"tags":[{"name":"Itinerary","description":"Create, modify, retrieve, fork, publish, and share travel itineraries"},{"name":"Search","description":"Search destinations, hotels, restaurants, attractions, events, and community itineraries"},{"name":"OAuth","description":"OAuth 2.0 authorization for AI agents"},{"name":"Health","description":"API health check and capabilities discovery"}],"paths":{"/health":{"get":{"tags":["Health"],"summary":"Health check","description":"Returns the health status and capabilities of the AI API.","operationId":"getHealth","responses":{"200":{"description":"Healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/itineraries":{"post":{"tags":["Itinerary"],"summary":"Create itinerary","description":"Create a new travel itinerary. The itinerary is created as a draft in the user's account.","operationId":"createItinerary","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateItineraryRequest"},"examples":{"tokyoTrip":{"summary":"5-day Tokyo trip","value":{"title":"Tokyo Adventure","destination":"Tokyo","country":"Japan","countryCode":"JP","city":"Tokyo","totalDays":5,"budget":"mid-range","travelType":"couple","bestSeason":"spring","tags":["cherry-blossom","food","culture"],"days":[{"dayNumber":1,"places":[{"name":"Shibuya Crossing","latitude":35.6595,"longitude":139.7004},{"name":"Meiji Shrine","latitude":35.6764,"longitude":139.6993}]}]}}}}}},"responses":{"201":{"description":"Itinerary created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItinerarySuccessResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimitExceeded"}}},"get":{"tags":["Itinerary"],"summary":"List itineraries","description":"List the authenticated user's itineraries with pagination.","operationId":"listItineraries","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"page","in":"query","schema":{"type":"integer","default":1,"minimum":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":20,"minimum":1,"maximum":100}},{"name":"status","in":"query","schema":{"type":"string","enum":["draft","published"]}},{"name":"destination","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of itineraries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItineraryListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/itineraries/{id}":{"get":{"tags":["Itinerary"],"summary":"Retrieve itinerary","description":"Get full details of a specific itinerary.","operationId":"getItinerary","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Itinerary details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItinerarySuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Itinerary"],"summary":"Modify itinerary via natural language","description":"Update an itinerary using a natural language instruction. Supported instructions: \"change title to X\", \"add day\", \"set destination to X\", \"set budget to luxury\", \"add tag X\".","operationId":"modifyItinerary","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyItineraryRequest"},"examples":{"changeTitle":{"summary":"Change title","value":{"instruction":"change title to \"Kyoto Spring Trip\""}},"addDay":{"summary":"Add a day","value":{"instruction":"add day"}},"setBudget":{"summary":"Set budget tier","value":{"instruction":"set budget to luxury"}}}}}},"responses":{"200":{"description":"Itinerary modified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItinerarySuccessResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/UnprocessableEntity"}}},"delete":{"tags":["Itinerary"],"summary":"Delete itinerary","description":"Permanently delete an itinerary. Only the creator can delete. This action cannot be undone.","operationId":"deleteItinerary","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Itinerary ID to delete"}],"responses":{"200":{"description":"Itinerary deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"null"},"message":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/itineraries/{id}/fork":{"post":{"tags":["Itinerary"],"summary":"Fork itinerary","description":"Create a copy of a community itinerary in your account.","operationId":"forkItinerary","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForkItineraryRequest"}}}},"responses":{"201":{"description":"Itinerary forked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItinerarySuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/itineraries/{id}/publish":{"post":{"tags":["Itinerary"],"summary":"Publish itinerary","description":"Publish an itinerary to the community, making it publicly visible.","operationId":"publishItinerary","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Itinerary published","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ItinerarySuccessResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/itineraries/{id}/share":{"post":{"tags":["Itinerary"],"summary":"Share itinerary","description":"Generate a shareable link for an itinerary.","operationId":"shareItinerary","security":[{"CookieAuth":[]},{"BearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareItineraryRequest"}}}},"responses":{"200":{"description":"Share link generated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareItineraryResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/search/destinations":{"get":{"tags":["Search"],"summary":"Search destinations","description":"Search for travel destinations worldwide using Mapbox.","operationId":"searchDestinations","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search query"},{"name":"limit","in":"query","schema":{"type":"integer","default":10,"minimum":1,"maximum":50}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"city","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResultsResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/search/hotels":{"get":{"tags":["Search"],"summary":"Search hotels","description":"Search for hotels at a destination.","operationId":"searchHotels","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"city","in":"query","schema":{"type":"string"}},{"name":"minRating","in":"query","schema":{"type":"number","minimum":0,"maximum":5}},{"name":"maxPrice","in":"query","schema":{"type":"number","minimum":0}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResultsResponse"}}}}}}},"/search/restaurants":{"get":{"tags":["Search"],"summary":"Search restaurants","description":"Search for restaurants at a destination.","operationId":"searchRestaurants","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"city","in":"query","schema":{"type":"string"}},{"name":"cuisine","in":"query","schema":{"type":"string"}},{"name":"priceLevel","in":"query","schema":{"type":"integer","minimum":1,"maximum":4}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResultsResponse"}}}}}}},"/search/attractions":{"get":{"tags":["Search"],"summary":"Search attractions","description":"Search for tourist attractions at a destination.","operationId":"searchAttractions","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"city","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResultsResponse"}}}}}}},"/search/events":{"get":{"tags":["Search"],"summary":"Search events","description":"Search for events at a destination.","operationId":"searchEvents","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"city","in":"query","schema":{"type":"string"}},{"name":"startDate","in":"query","schema":{"type":"string","format":"date"}},{"name":"endDate","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResultsResponse"}}}}}}},"/search/communities":{"get":{"tags":["Search"],"summary":"Search community itineraries","description":"Search published community itineraries.","operationId":"searchCommunities","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","default":10}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"city","in":"query","schema":{"type":"string"}},{"name":"travelType","in":"query","schema":{"type":"string","enum":["solo","couple","family","friends","business"]}},{"name":"budget","in":"query","schema":{"type":"string","enum":["budget","mid-range","luxury"]}},{"name":"bestSeason","in":"query","schema":{"type":"string","enum":["spring","summer","autumn","winter","any"]}},{"name":"sortBy","in":"query","schema":{"type":"string","enum":["popular","recent","rating"],"default":"popular"}}],"responses":{"200":{"description":"Community search results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunitySearchResultsResponse"}}}}}}},"/oauth/authorize":{"get":{"tags":["OAuth"],"summary":"Authorize","description":"OAuth 2.0 authorization endpoint. Redirects to the callback URL with an authorization code.","operationId":"oauthAuthorize","security":[{"CookieAuth":[]}],"parameters":[{"name":"response_type","in":"query","required":true,"schema":{"type":"string","enum":["code"]}},{"name":"client_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"redirect_uri","in":"query","required":true,"schema":{"type":"string","format":"uri"}},{"name":"scope","in":"query","schema":{"type":"string","default":"read write"}},{"name":"state","in":"query","schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect to redirect_uri with authorization code"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/oauth/token":{"post":{"tags":["OAuth"],"summary":"Token exchange","description":"Exchange an authorization code or refresh token for an access token.","operationId":"oauthToken","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenRequest"}}}},"responses":{"200":{"description":"Token issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthTokenResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/oauth/revoke":{"post":{"tags":["OAuth"],"summary":"Revoke token","description":"Revoke an access or refresh token.","operationId":"oauthRevoke","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRevokeRequest"}}}},"responses":{"200":{"description":"Token revoked"},"400":{"$ref":"#/components/responses/BadRequest"}}}}},"components":{"securitySchemes":{"CookieAuth":{"type":"apiKey","in":"cookie","name":"accessToken","description":"JWT access token in httpOnly cookie (for web users)"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT access token in Authorization header (for AI agents)"}},"responses":{"BadRequest":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Authentication required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"Insufficient permissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"UnprocessableEntity":{"description":"Instruction could not be processed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"RateLimitExceeded":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[false]},"error":{"type":"object","properties":{"type":{"type":"string","description":"Error type identifier"},"title":{"type":"string","description":"Human-readable error title"},"status":{"type":"integer","description":"HTTP status code"},"detail":{"type":"string","description":"Detailed error message"},"instance":{"type":"string","description":"Request path that caused the error"}},"required":["type","title","status","detail"]}},"required":["success","error"]},"Pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"hasNext":{"type":"boolean"},"hasPrev":{"type":"boolean"}}},"Place":{"type":"object","properties":{"name":{"type":"string"},"address":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"mapboxPlaceId":{"type":"string"},"notes":{"type":"string"},"time":{"type":"string"},"order":{"type":"integer"}},"required":["name","latitude","longitude"]},"Day":{"type":"object","properties":{"dayNumber":{"type":"integer","minimum":1},"places":{"type":"array","items":{"$ref":"#/components/schemas/Place"}}},"required":["dayNumber","places"]},"CreateItineraryRequest":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200},"description":{"type":"string","maxLength":2000},"destination":{"type":"string","minLength":1},"country":{"type":"string","minLength":1},"countryCode":{"type":"string","maxLength":2},"city":{"type":"string"},"region":{"type":"string"},"totalDays":{"type":"integer","minimum":1,"maximum":30},"budget":{"type":"string","enum":["budget","mid-range","luxury"]},"budgetAmount":{"type":"number","minimum":0},"currency":{"type":"string","default":"USD"},"travelType":{"type":"string","enum":["solo","couple","family","friends","business"]},"bestSeason":{"type":"string","enum":["spring","summer","autumn","winter","any"]},"tags":{"type":"array","items":{"type":"string"},"maxItems":20},"days":{"type":"array","items":{"$ref":"#/components/schemas/Day"}}},"required":["title","destination","country","totalDays"]},"ModifyItineraryRequest":{"type":"object","properties":{"instruction":{"type":"string","minLength":1,"maxLength":2000,"description":"Natural language instruction to modify the itinerary"}},"required":["instruction"]},"ForkItineraryRequest":{"type":"object","properties":{"title":{"type":"string","description":"Optional custom title for the forked itinerary"}}},"ShareItineraryRequest":{"type":"object","properties":{"expiresIn":{"type":"integer","description":"Link expiry in hours (default: 72)","default":72}}},"Itinerary":{"type":"object","properties":{"_id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"destination":{"type":"string"},"country":{"type":"string"},"countryCode":{"type":"string"},"city":{"type":"string"},"region":{"type":"string"},"totalDays":{"type":"integer"},"budget":{"type":"string"},"budgetAmount":{"type":"number"},"currency":{"type":"string"},"travelType":{"type":"string"},"bestSeason":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"coverImage":{"type":"string"},"createdBy":{"type":"string"},"visibility":{"type":"string"},"status":{"type":"string"},"days":{"type":"array","items":{"$ref":"#/components/schemas/Day"}},"totalPlaces":{"type":"integer"},"analytics":{"type":"object","properties":{"views":{"type":"integer"},"likes":{"type":"integer"},"saves":{"type":"integer"},"copies":{"type":"integer"},"shares":{"type":"integer"},"ratingSum":{"type":"number"},"ratingCount":{"type":"integer"}}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ItinerarySuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/Itinerary"},"message":{"type":"string"}}},"ItineraryListResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Itinerary"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}},"ShareItineraryResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"shareUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"},"token":{"type":"string"}}},"message":{"type":"string"}}},"SearchResult":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"address":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"category":{"type":"string"},"rating":{"type":"number"},"imageUrl":{"type":"string"},"metadata":{"type":"object"}}},"SearchResultsResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/SearchResult"}}}},"CommunitySearchResult":{"type":"object","properties":{"_id":{"type":"string"},"title":{"type":"string"},"destination":{"type":"string"},"country":{"type":"string"},"totalDays":{"type":"integer"},"budget":{"type":"string"},"travelType":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"coverImage":{"type":"string"},"analytics":{"type":"object","properties":{"views":{"type":"integer"},"likes":{"type":"integer"},"saves":{"type":"integer"},"copies":{"type":"integer"},"ratingCount":{"type":"integer"},"ratingSum":{"type":"number"}}},"createdBy":{"type":"object","properties":{"_id":{"type":"string"},"name":{"type":"string"},"username":{"type":"string"}}}}},"CommunitySearchResultsResponse":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"$ref":"#/components/schemas/CommunitySearchResult"}}}},"OAuthTokenRequest":{"type":"object","oneOf":[{"type":"object","properties":{"grant_type":{"type":"string","enum":["authorization_code"]},"code":{"type":"string"},"redirect_uri":{"type":"string","format":"uri"},"client_id":{"type":"string"},"client_secret":{"type":"string"}},"required":["grant_type","code","redirect_uri","client_id","client_secret"]},{"type":"object","properties":{"grant_type":{"type":"string","enum":["refresh_token"]},"refresh_token":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"}},"required":["grant_type","refresh_token","client_id","client_secret"]}]},"OAuthTokenResponse":{"type":"object","properties":{"access_token":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer"},"refresh_token":{"type":"string"},"scope":{"type":"string"}}},"OAuthRevokeRequest":{"type":"object","properties":{"token":{"type":"string"},"token_type_hint":{"type":"string","enum":["access_token","refresh_token"]}},"required":["token"]},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"]},"version":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"capabilities":{"type":"array","items":{"type":"string"}},"rateLimit":{"type":"object","properties":{"read":{"type":"object","properties":{"max":{"type":"integer"},"windowMs":{"type":"integer"}}},"write":{"type":"object","properties":{"max":{"type":"integer"},"windowMs":{"type":"integer"}}}}}}}}}}