AI Integrations Overview
Use Charter Boats data through Custom GPTs, MCP servers, and direct API calls
Charter Boats exposes a set of AI-optimized endpoints under /api/ai/* designed for use by LLM-based integrations. The read endpoints are public (no key), and the same endpoints are surfaced three ways:
- MCP Server -- A Model Context Protocol server at
https://charter.boats/mcpthat works in Claude.ai, Claude Desktop, ChatGPT Apps, Cursor, and any MCP-compatible client. Provides rich UI widgets for boats and locations. - Custom GPT -- A ChatGPT Action that uses an OpenAPI schema to search boats, locations, POIs, routes, trips, and content.
- In-browser agents (WebMCP) -- When an AI agent loads a charter.boats page, the site registers the same ten tools on
navigator.modelContext, so browser-based agents (Chrome's built-in AI, ChatGPT Atlas, Claude in Chrome, Gemini) can call them directly. Nothing to install -- it's served by the page.
All three call the same underlying /api/ai/* endpoints, which are optimized for AI consumption: fuzzy location matching, compact response shapes, an explained answer whenever a search comes back empty, and rate limiting tuned for conversational use. You can also call the endpoints directly over HTTP.
Building for an LLM crawler instead of a tool-calling agent? https://charter.boats/llms.txt gives a plain-text map of the site for model consumption.
Base URL
All AI endpoints are relative to:
Authentication
No authentication required. The read endpoints below are open to any caller, with or without a key.
A key is optional. If you send your API key in the X-API-Key header (see identifying yourself), the call is recorded against your account, and boat links in the response — boats[].url from /ai/boats and url from /ai/boats/{id} — carry your affiliate ref when your account has an active affiliate profile, so bookings that start from your integration are credited to you. Nothing else about the response changes. A missing or invalid key is served exactly like an anonymous call — never a 401.
Rate Limits
All /api/ai/* endpoints draw on one shared budget per client — a boat search and a location lookup count against the same allowance.
| Source | Limit |
|---|---|
| Custom GPT requests (counted per OpenAI user) | 30 requests / 10 minutes |
| All other clients (counted per IP) | 60 requests / 10 minutes |
Rate-limited responses return 429 Too Many Requests with a Retry-After header (seconds). Treat the figures as a ceiling to stay under rather than an exact allowance.
Available Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /ai/boats | Search boats by location, type, dates, budget |
GET | /ai/boats/{id} | Full details, bookable dates and fees for one boat |
GET | /ai/locations | Search marinas, harbours and anchorages -- by name, by popularity in an area, or by reach from a place |
GET | /ai/locations/{id} | Full details and observed traffic for one location |
GET | /ai/pois | Find restaurants, fuel, shops near a location |
GET | /ai/pois/{id} | Full details for one point of interest |
GET | /ai/routes | Find sailing passages with distance and difficulty |
GET | /ai/trips | Search curated multi-day itineraries |
GET | /ai/trips/{id} | Day-by-day detail for one itinerary |
GET | /ai/content | Search articles, guides, and FAQ answers |
Zero results
A search that finds nothing never comes back as a bare empty array. /ai/boats, /ai/locations, /ai/pois, /ai/routes, /ai/trips and /ai/content all add the same block beside their (empty) result list:
| Field | Description |
|---|---|
no_results.searched | What was actually run, after resolution -- the interpretation of your input, not the raw string you sent. |
no_results.why | Which constraint emptied it -- the place, the dates, a filter, or nothing indexed. Different causes want different retries. |
no_results.try_next | Concrete next calls, most likely to work first, written in tool terms. |
note | One sentence generated from the three fields above, for clients that only skim. It never says anything the block does not. |
searched is the interpretation, not the input: a place is resolved first (by the one resolver behind boat search), and the line names what it resolved to.
Where a term could not be resolved at all, the endpoint also names it under its own key -- location_unresolved (boats, POIs, trips, and an unusable location_id on routes), region_unresolved and from_unresolved (locations, routes). An unresolved place is never silently widened into a worldwide search: no search is run at all.
Custom GPT
The Custom GPT uses an OpenAPI 3.1 schema that exposes the endpoints above as ChatGPT Actions, pointed at https://charter.boats/api/ai.
To set up your own Custom GPT using Charter Boats data:
- Create a new GPT in ChatGPT
- Add a new Action
- Paste in the OpenAPI schema -- it is not published as a file, so request it through the contact page
- No authentication is needed
GPT Conversation Handoff
When requests come from a Custom GPT, the server reads the openai-conversation-id header and uses it to hand the conversation over to charter.boats:
- Link tagging -- links on
https://charter.boats/...in the response (search_url, location, POI, route, trip and article URLs) get?oid=<conversation_id>appended. Boat share links (https://chrtr.me/...) are left as they are. - Context handoff -- boat searches made from the GPT are stored against that conversation. When the guest follows an
?oid=link, the on-site chat reads the latest boat search back (location, boat type, guests, dates, budget) and continues from it instead of starting cold. This lookup (GET /ai/gpt-context?oid=…) exists for the site's own chat; it is not a tool for the GPT to call.
MCP Server
The MCP Server provides the same data through the Model Context Protocol with rich HTML widgets for boat and location results. See the dedicated page for details.