# TheTripMap > Plan, discover, and share trip itineraries on an interactive map. Users create canoe, hiking, biking, and alpine expeditions with GPS pins, routes, notes, and expenses. TheTripMap is a web app for planning and sharing outdoor trip itineraries. Users place pins on a satellite map for campsites, portages, points of interest, parking, and water access points. Routes connect pins with waypoints and distance tracking. Notes and expenses can be attached to any pin or the trip itself. ## Public API TheTripMap has a public REST API that AI assistants can use to search for existing trips, get full trip details, and create new temporary trips without authentication. ### API Documentation - Human-readable docs: https://thetripmap.com/docs - OpenAPI 3.1 spec (machine-readable): https://thetripmap.com/openapi.json - AI plugin manifest: https://thetripmap.com/.well-known/ai-plugin.json - MCP server (for ChatGPT connectors): https://zxhsfhqcnssugzymapbb.supabase.co/functions/v1/mcp - Plain-text API info page (no JavaScript): https://thetripmap.com/ai-info.html ### Base URL https://thetripmap.com/functions/v1/api ### Authentication All API requests require a Bearer token in the Authorization header. Use the public anon key below -- it is safe to expose and has read-only access to public trip data plus the ability to create temporary trips. Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp4aHNmaHFjbnNzdWd6eW1hcGJiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzE2OTE3NjYsImV4cCI6MjA4NzI2Nzc2Nn0.bnpxlvQIFV1PwggQ1aYkrZol_a6KP9p56mcrGpdk23E ### Key Endpoints - GET /api/trips -- search public trips (params: q, category, min_lat, max_lat, min_lng, max_lng, min_route_count, limit, offset) - GET /api/trips/:id -- get full public trip detail with all pins, paths, notes, expenses, and images - POST /api/trips -- create a temporary trip (no auth required, auto-deletes after 3 days, max 200 items, supports pin/path/note/expense/image types) - POST /api/trips/:id/claim -- claim a temporary trip (requires user authentication) - GET /api/temporary/:id -- get a temporary trip for preview - POST /api/route-path -- compute a routed path between two coordinates (params: start, end, profile) - GET /api/health -- health check and endpoint listing ### Geographic Search Pass all four bounding box parameters (min_lat, max_lat, min_lng, max_lng) to filter trips by location. For example, to find trips near Ottawa, Canada: GET /api/trips?min_lat=44.5&max_lat=46.5&min_lng=-79&max_lng=-75&category=hiking ### Trip Categories - unclassified: Default category when none is specified. Use for trips that don't fit a specific activity type. - hiking: Walking, backpacking, or trekking trips on trails or off-trail. - river: Canoe, kayak, or raft trips on rivers. Includes put-in/take-out pins and portage points. - lake: Canoe, kayak, or boat trips on lakes. May include portage pins between connected lakes. - biking: Mountain biking, road cycling, or bikepacking trips. - motor: Motorized vehicle trips -- car, motorcycle, or off-road. - alpine: Mountaineering, ski touring, or high-altitude expeditions. ### Pin Categories - general: Default pin type. Use for generic waypoints, meeting points, landmarks, or turn-around points. - parking: Parking locations. Use for trailheads, access points, and vehicle parking. - campsite: Overnight camping locations. Use for designated campsites or backcountry camping spots. - poi: Point of Interest. Use for viewpoints, waterfalls, historical markers, or scenic lookouts. - portage: Canoe/kayak carry-over points between water bodies. Specific to river and lake trips. - water: Water source or access point. Use for springs, streams, or lakes where water can be collected. ### Item Types and Fields #### pin -- A GPS Location Required fields: type ("pin"), title, latitude, longitude Optional fields: description, address, pin_category (defaults to "general"), is_optional (defaults to false) - title: Short name (e.g. "Trailhead Parking", "Campsite 1", "Lookout Point") - description: Longer description of terrain, difficulty, amenities, or what to expect - address: Real address or landmark name - latitude/longitude: WGS84 decimal degrees (-90 to 90, -180 to 180) - pin_category: One of general, parking, campsite, poi, portage, water - is_optional: If true, pin is marked optional (for alternate campsites, optional side trips) #### path -- A Route Connecting Two Pins Path items have three independent concepts that control how a path is drawn, routed, and connected: 1. **Path geometry** (waypoints): Explicit, point-by-point route shape. Always required (min 2 coordinate pairs). For waterways, portages, off-trail travel, or routes without reliable mapped routing networks, provide verified waypoint geometry rather than relying on automatic road or trail routing. 2. **Routing engine** (geometry_mode, routing_profile): Whether the application should calculate a route along mapped networks. Set geometry_mode to "routed" and provide a routing_profile (auto, pedestrian, bicycle, none) to indicate the travel mode. Routed paths render as solid lines following roads/trails. Set geometry_mode to "manual" (or omit) to use the waypoints as-is with no automatic routing -- the path renders as a dashed straight-line shape. The legacy boolean is_precision_route is still accepted (true = routed, false = manual) but geometry_mode is preferred. 3. **Timeline connection** (start_pin_index, end_pin_index): Whether the path connects two pins and appears between them in the timeline as a connection card with distance label. Omit both for a standalone drawn route. Required fields: type ("path"), title, waypoints Optional fields: description, start_pin_index, end_pin_index, distance_km, is_optional, geometry_mode, routing_profile, is_precision_route - title: Short name (e.g. "Paddle to Campsite", "Hike to Summit") - description: Terrain details, difficulty, estimated time, navigation notes - waypoints: Array of [latitude, longitude] pairs defining the route shape (minimum 2). Include intermediate points to trace curves, river bends, or trail switchbacks. Example: [[45.589, -78.637], [45.590, -78.638], [45.591, -78.640]] - start_pin_index: Zero-based index of the start pin in the items array. When both start and end are provided, the path appears as a connection between the two pins in the timeline. - end_pin_index: Zero-based index of the end pin in the items array - distance_km: Estimated distance in kilometers. Contributes to trip total_distance_km. - is_optional: If true, route is excluded from total distance calculation. Use for alternate routes or side trips. - geometry_mode: "manual" (default -- use waypoints as-is, dashed line) or "routed" (application calculates route along mapped networks, solid line). For waterways, portages, off-trail travel, use "manual" with verified waypoints. - routing_profile: Routing profile used when geometry_mode is "routed": "auto" (driving), "pedestrian" (walking/hiking), "bicycle" (cycling), or "none" (straight line). Indicates the travel mode. - is_precision_route: Legacy field. true is equivalent to geometry_mode="routed", false to "manual". Prefer geometry_mode. How paths connect to pins: The start_pin_index and end_pin_index use zero-based indexing into the items array. For example, if the first pin in the items array is the start, use 0. If omitted, the path is a standalone route. When both start and end pin indices are provided, the path is automatically treated as a connection between those pins and will appear in the timeline between them. #### note -- A Text Note Required fields: type ("note"), title Optional fields: description, url, parent_index - title: Short title (e.g. "Water Levels", "Bear Safety", "Permit Info") - description: Full text of the note (safety warnings, weather notes, permit requirements, etc.) - url: A valid http or https URL related to the note - parent_index: Zero-based index of the parent pin in the items array. If omitted or null, the note is trip-level. #### expense -- A Cost Item Required fields: type ("expense"), title, cost Optional fields: description, currency (defaults to "USD"), parent_index - title: Short description (e.g. "Park Permit", "Canoe Rental", "Gas") - cost: Cost amount, number >= 0 - currency: ISO 4217 currency code (USD, CAD, EUR, GBP, AUD, JPY, etc.) - parent_index: Zero-based index of the parent pin in the items array. If omitted or null, expense is trip-level. #### image -- An External Image Required fields: type ("image"), image_url Optional fields: title, source_url, caption, parent_index, latitude, longitude - image_url: External http or https URL to an image file. The image is displayed on the trip's map and timeline. - source_url: URL of the original webpage where the image was found, for attribution (optional). Separate from image_url, which is the direct image file URL. - caption: Caption text for the image (used as the display title if title is omitted). Include the image description and source or photographer attribution when available. - title: Optional title (if omitted, caption is used instead) - parent_index: Zero-based index of the parent pin to attach the image to. If omitted or null, the image is trip-level. - latitude/longitude: Optional GPS coordinates for the image marker on the map. - image_status: Server-populated, read-only field returned in the create_trip response. Values: "verified" (URL serves an image), "unverified" (URL reachable but not confirmed as image), "failed" (URL unreachable). Lets AI clients identify broken image links. Not set on input. Use image items to enrich trips with visual context -- photos of trailheads, campsites, scenic viewpoints, or water crossings. Images must be hosted externally (e.g. on a CDN, photo sharing site, or any public web server). Images do not need to come from Wikimedia Commons or any specific source. ### Response Fields (TripSummary) - id: UUID of the trip - title: Trip title - description: Trip description - address: Location address (nullable) - category: Trip category (one of the categories above) - latitude, longitude: Center point of the trip's pins (nullable if no pins with coordinates) - owner_handle: Owner's URL handle for constructing public URLs - owner_username: Owner's display username - pin_count: Number of pins in the trip - route_count: Number of routes (sub-projects) in the trip - total_distance_km: Total distance of all non-optional routes in kilometers - public_url: Relative URL to view the trip (e.g. /username/trip-slug) ### Trip Detail Response Fields (GET /api/trips/:id) The response contains a "trip" object with an "items" array. Each item has: - id: UUID - type: pin, path, note, expense, or image - sort_order: Integer display order in the timeline - title: Item title (may be null) - description: Item description (may be null) - address: Address or landmark name (pins only, may be null) - url: URL associated with the item (notes only, may be null) - pin_category: Pin category (pins only, may be null) - is_optional: Boolean, whether item is optional (pins and paths) - latitude, longitude: WGS84 coordinates (pins only, may be null for other types) - data: Type-specific structured data object (see below) - parent_id: UUID of parent item (for notes/expenses attached to pins, null otherwise) ### Data Field by Item Type - path items (PathData): { waypoints: [[lat,lng],...], distance_km: number, travel_time: string, start_pin_id: uuid, end_pin_id: uuid, auto_connection: boolean, parent_child_connection: boolean, intermediate_waypoints: [[lat,lng],...], routed_waypoints: [[lat,lng],...], routing_profile: string, is_precision_route: boolean, precision_route_pin_positions: { start: [lat,lng], end: [lat,lng] } } - expense items (ExpenseData): { cost: number, currency: string } - image items (ImageData): { storage_path: string, image_url: string, source_url: string, is_external: boolean, thumbnail_path: string, width: number, height: number, caption: string, image_status: string } - pin and note items: data is typically empty object or null ### Item Ordering and Parent Relationships When creating a trip via POST /api/trips, items are processed in array order. The zero-based array index is used for cross-referencing: - start_pin_index / end_pin_index on paths: position of the start/end pin in the items array - parent_index on notes and expenses: position of the parent pin in the items array (null = trip-level) When reading a trip via GET /api/trips/:id, the response uses parent_id (UUID) instead of array indices. ### Temporary Trip Lifecycle - Created without an owner via POST /api/trips - Viewable by anyone at /trip/:tripId - Auto-delete after 3 days if not claimed - Claimed by a registered user via POST /api/trips/:id/claim - Never appear in public search results or community feeds ### MCP Server for ChatGPT and AI Assistants TheTripMap provides an MCP (Model Context Protocol) server that lets AI assistants like ChatGPT directly search, retrieve, and create trips without manually constructing HTTP requests. MCP Server URL: https://zxhsfhqcnssugzymapbb.supabase.co/functions/v1/mcp To connect in ChatGPT: Settings > Connectors > Advanced > Developer Mode > Add custom connector > paste https://zxhsfhqcnssugzymapbb.supabase.co/functions/v1/mcp No authentication required. The server implements MCP JSON-RPC 2.0 over HTTP (protocol version 2025-06-18). Available MCP tools: - search_trips: Search public trips by text query, category, or geographic bounding box. Parameters: q, category, min_lat, max_lat, min_lng, max_lng, min_route_count, limit, offset. - get_trip: Retrieve full trip detail including all pins, paths, notes, expenses, and images. Parameter: trip_id (UUID). - create_trip: Create a temporary trip from a title, description, and items array. Items can be pins, paths, notes, expenses, or images (external image URLs). Paths support optional geometry_mode (manual/routed), routing_profile, and the legacy is_precision_route fields. Parameters: title, description, items. Returns preview URL and trip ID. Auto-deletes after 3 days. - get_temporary_trip: Retrieve a temporary trip by ID. Parameter: trip_id (UUID). ### Example: Search for hiking trips near Ottawa GET https://thetripmap.com/functions/v1/api/trips?category=hiking&min_lat=44.5&max_lat=46.5&min_lng=-79&max_lng=-75&limit=10 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp4aHNmaHFjbnNzdWd6eW1hcGJiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzE2OTE3NjYsImV4cCI6MjA4NzI2Nzc2Nn0.bnpxlvQIFV1PwggQ1aYkrZol_a6KP9p56mcrGpdk23E ### Example: Create a multi-day canoe trip POST https://thetripmap.com/functions/v1/api/trips Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp4aHNmaHFjbnNzdWd6eW1hcGJiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzE2OTE3NjYsImV4cCI6MjA4NzI2Nzc2Nn0.bnpxlvQIFV1PwggQ1aYkrZol_a6KP9p56mcrGpdk23E Content-Type: application/json { "project": { "title": "Algonquin 3-Day Canoe Trip", "description": "A 3-day canoe journey through Algonquin Provincial Park, starting at Canoe Lake and camping on Tom Thompson Lake and Burnt Island Lake." }, "items": [ {"type": "pin", "title": "Canoe Lake Access Point", "latitude": 45.589, "longitude": -78.637, "pin_category": "parking", "address": "Canoe Lake, Algonquin Park", "description": "Access Point 5. Parking available. Permit required."}, {"type": "pin", "title": "Portage to Tom Thompson Lake", "latitude": 45.593, "longitude": -78.641, "pin_category": "portage", "description": "Short 200m portage over flat ground."}, {"type": "path", "title": "Paddle to Portage", "start_pin_index": 0, "end_pin_index": 1, "waypoints": [[45.589, -78.637], [45.591, -78.639], [45.593, -78.641]], "distance_km": 2.1, "is_precision_route": true, "routing_profile": "pedestrian"}, {"type": "pin", "title": "Campsite on Tom Thompson Lake", "latitude": 45.596, "longitude": -78.645, "pin_category": "campsite", "description": "Designated campsite #412. Good swimming. Flat ground for 2 tents."}, {"type": "path", "title": "Portage to Campsite", "start_pin_index": 1, "end_pin_index": 3, "waypoints": [[45.593, -78.641], [45.595, -78.643], [45.596, -78.645]], "distance_km": 1.5}, {"type": "pin", "title": "Scenic Lookout", "latitude": 45.598, "longitude": -78.648, "pin_category": "poi", "is_optional": true, "description": "Short side trail to a cliff-top view of Tom Thompson Lake. Optional side trip."}, {"type": "path", "title": "Side Trip to Lookout", "start_pin_index": 3, "end_pin_index": 5, "waypoints": [[45.596, -78.645], [45.598, -78.648]], "distance_km": 0.8, "is_optional": true}, {"type": "note", "title": "Water Levels", "description": "Water levels in late summer can be low. The portage trail may be muddy. Check with the park office before departure.", "parent_index": 1}, {"type": "note", "title": "Bear Safety", "description": "This is bear country. Store all food in the provided bear hangs at each campsite. Keep a clean camp.", "parent_index": 3}, {"type": "note", "title": "Permit Info", "description": "Backcountry permits required for all overnight stays. Reserve online at algonquinpark.ca.", "url": "https://www.algonquinpark.ca/"}, {"type": "expense", "title": "Backcountry Permit", "cost": 24.50, "currency": "CAD", "parent_index": 0}, {"type": "expense", "title": "Canoe Rental", "cost": 65.00, "currency": "CAD"}, {"type": "expense", "title": "Gas", "cost": 30.00, "currency": "CAD", "parent_index": 0}, {"type": "image", "image_url": "https://example.com/canoe-lake-put-in.jpg", "caption": "Canoe Lake put-in point", "parent_index": 0} ] } ### Example: Hiking trip with automatic routing (geometry_mode="routed") POST https://thetripmap.com/functions/v1/api/trips Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp4aHNmaHFjbnNzdWd6eW1hcGJiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzE2OTE3NjYsImV4cCI6MjA4NzI2Nzc2Nn0.bnpxlvQIFV1PwggQ1aYkrZol_a6KP9p56mcrGpdk23E Content-Type: application/json { "title": "Gatineau Park Summit Hike", "description": "A scenic hike to a lookout", "items": [ {"type":"pin","title":"Trailhead","latitude":45.5,"longitude":-75.8,"pin_category":"parking"}, {"type":"pin","title":"Lookout","latitude":45.52,"longitude":-75.82,"pin_category":"poi"}, {"type":"path","title":"Hike to lookout","start_pin_index":0,"end_pin_index":1,"waypoints":[[45.5,-75.8],[45.52,-75.82]],"distance_km":3.5,"geometry_mode":"routed","routing_profile":"pedestrian"}, {"type":"image","image_url":"https://example.com/trailhead.jpg","caption":"Trailhead parking area","parent_index":0}, {"type":"expense","title":"Parking","cost":10,"currency":"CAD","parent_index":0} ] } ### Example: Canoe route with manually traced geometry (geometry_mode="manual", no automatic routing) POST https://thetripmap.com/functions/v1/api/trips Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp4aHNmaHFjbnNzdWd6eW1hcGJiIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzE2OTE3NjYsImV4cCI6MjA4NzI2Nzc2Nn0.bnpxlvQIFV1PwggQ1aYkrZol_a6KP9p56mcrGpdk23E Content-Type: application/json { "title": "Bonnechere River Canoe", "description": "A weekend canoe trip down the Bonnechere River", "items": [ {"type":"pin","title":"Put-in","latitude":45.58,"longitude":-77.35,"pin_category":"water"}, {"type":"pin","title":"Campsite","latitude":45.55,"longitude":-77.42,"pin_category":"campsite"}, {"type":"path","title":"Paddle to campsite","start_pin_index":0,"end_pin_index":1,"waypoints":[[45.58,-77.35],[45.57,-77.37],[45.56,-77.39],[45.555,-77.41],[45.55,-77.42]],"distance_km":8.2,"geometry_mode":"manual"}, {"type":"note","title":"Portage notes","description":"Short portage around the old dam at waypoint 2","parent_index":0} ] } ### Creating rich trips with images and routes When creating a trip, aim to include real geographic pins, meaningful connections, and relevant photographs where available. **Images:** - Search the web for photographs relevant to the trip's destinations. - Use direct, publicly accessible HTTPS image URLs in image_url. - Use source_url for the original webpage where the image was found (optional). - Attach each image to its corresponding pin using parent_index. - Include the image description and source or photographer attribution in caption when available. - Images do not need to come from Wikimedia Commons or any specific source. - Prefer images that are publicly embeddable and permitted for reuse. Do not assume search visibility grants republication rights. - If a photograph is illustrative rather than from the exact location, say so in its caption. - The server validates each image_url after creation and returns image_status (verified, unverified, or failed) so you can identify broken links. **Routes:** - For established roads and trails, use geometry_mode: "routed" with the appropriate routing_profile when network routing is desired. - For canoe routes, portages, waterways, and unmarked trails, use geometry_mode: "manual" and provide manually traced waypoints. - Use start_pin_index and end_pin_index to connect paths between pins in the itinerary timeline. - Never invent exact route geometry or represent approximate routes as navigation-ready. **Before finishing:** - After creating the trip, retrieve it to verify that pins, paths, images, captions, and parent relationships were saved correctly. - Check the returned image_status for each image to confirm the URL is valid. ### Complete example: canoe trip with images, notes, and expenses { "title": "Bonnechere River Canoe", "description": "A weekend canoe trip down the Bonnechere River with two portages", "items": [ {"type":"pin","title":"Put-in at Douglas","latitude":45.58,"longitude":-77.35,"pin_category":"water"}, {"type":"pin","title":"Rapids campsite","latitude":45.55,"longitude":-77.42,"pin_category":"campsite"}, {"type":"path","title":"Paddle to campsite","start_pin_index":0,"end_pin_index":1,"waypoints":[[45.58,-77.35],[45.57,-77.37],[45.56,-77.39],[45.555,-77.41],[45.55,-77.42]],"distance_km":8.2,"geometry_mode":"manual"}, {"type":"image","image_url":"https://example.com/river-putin.jpg","source_url":"https://example.com/bonnechere-guide","caption":"The put-in at Douglas -- Photo by Ottawa Riverkeeper","parent_index":0}, {"type":"image","image_url":"https://example.com/campsite-rapids.jpg","caption":"Rapids campsite above the old dam","parent_index":1}, {"type":"note","title":"Portage notes","description":"Short 200m portage around the old dam at waypoint 2. Watch for swift current in spring.","parent_index":0}, {"type":"expense","title":"Canoe rental","cost":65,"currency":"CAD","parent_index":0} ] }