Charter Boats
Charter Boats API

Authentication

How API keys work across the Charter Boats developer surfaces

Authentication depends on which surface you're calling:

SurfaceBaseAuth
Discovery API/api/ai/*None — public, rate-limited. A key is optional
MCP server/mcpNone — public. An operator's key adds the operator tools
Agent API/api/agent/*Logged-in agent session — not a keyed surface
Operator API — reads/api/* (GET)API key on every call; boats, pricing, fees and availability of your companies' boats only — every company your account is a member of
Operator API — writesPOST /import/boat, PATCH/DELETE /boats/:id, and your boats' prices, fees, photos and videos, calendar and discountsAPI key, plus membership of the boat's company
iCal feeds/calendar/:boatId/export.ics, /calendar/company/:companyId/export.icsNone — calendar apps can't send headers

The Discovery API, the MCP server and the iCal feeds need no credentials. Everything else under /api/* — boats, pricing, fees, locations, POIs, passages, sea routing, features, manufacturers — expects your key in the X-API-Key header on every request, reads included.

Which surface is built for you?

A keyless surface is not "the free tier" and a key is not "the partner tier". The split is whether your caller can hold a secret at all, and whether you are answering one question or pulling data in bulk.

You areUseKey
A person browsing charter.boatsThe website itselfNo — the site calls its own API same-origin
An AI assistant, Custom GPT or metasearch engine answering a travellerDiscovery API /api/ai/*No — optional, and worth sending
An MCP hostMCP server /mcpNo — optional: a key spends your own budget, and an operator's key adds the operator tools
A calendar app subscribing to a boat's bookingsiCal feedNo — calendar apps cannot send headers
A site embedding our search widgetWidget endpoints, GET /api/locationsNo — these answer cross-origin
An agent, broker or site showing other operators' boats to buyersDiscovery API /api/ai/*Optional — send it: your own budget and your affiliate ref on every link
An operator's server reading its own boats, pricing, fees or availabilityOperator & Data APIYes, on every call

Two things follow, and they are what people get wrong in both directions:

Don't reach for a key you don't need. If you are an AI agent, a Custom GPT or an MCP host answering one traveller at a time, the Discovery API is built for exactly that and needs no credential — many such callers cannot safely hold one. Sending a key is still worth it, because it credits bookings from your integration to your affiliate profile, but it is never required and an invalid one is ignored rather than refused.

Selling boats you don't operate goes through the Discovery API. The Operator API reads only the boats of companies you are a member of — what you entered, so you can check it. Another operator's boat answers 403 there. The Discovery API gives you every boat with the price the guest pays on charter.boats, and its links send the buyer to us with your affiliate ref. Send your key with it: without one the budget is shared per IP (or per Custom GPT end user); with one it is your own.

When do you actually need the key?

CallKey needed?
Any Operator API or Places & Data endpoint, from your serverYes — on every call
Import a boat (POST /import/boat)Yes — and the boat is created under your account
Delete a boat (DELETE /boats/:id)Yes — and you must be an admin or owner of the boat's company
Edit a boat, its prices, fees, photos, videos, calendar or your discountsYes — and you must be a member of the boat's company
iCal feedsNo
Discovery API (/api/ai/*) and /mcpNo — optional (see below)
# Reads carry the key
curl "https://charter.boats/api/boats?company_slug=your-company&limit=5" \
  -H "X-API-Key: YOUR_API_KEY"
 
# So do writes — with a JSON body, send the Content-Type too
curl -X POST https://charter.boats/api/import/boat \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

What happens without a valid key:

  • No key — our bot protection stops the request before it reaches the API and answers with an HTML 403 page, not JSON. If you see HTML where you expected JSON, check the header is being sent.
  • A key that isn't real — 401 Invalid API key. Keys are checked on every call, not just on writes.
  • A malformed key — treated like no key: bot protection answers the HTML 403.
  • A boat your company does not operate — 403 JSON naming the Discovery API. So is GET /boats without company_slug set to your own company.

Every keyed call is recorded against your account, so we can see your usage when you ask about it.

Browsers on other websites

Call the API from your server. Browser requests from another website are not supported: responses carry no CORS headers, so the browser refuses to hand them to your page — and a key in client-side code is a leaked key anyway. The single exception is GET /api/locations (the exact path — the location autocomplete index), which answers cross-origin so the embeddable search widget's location box works. Anything else: proxy it through your own backend.

The Discovery API

/api/ai/* and /mcp never refuse a caller over its key. Sending one is still worthwhile: a valid API key records the call against your account, the boat links in the response carry your affiliate ref when your account has an active affiliate profile, so bookings that start from your integration are credited to you — and it raises your rate limit substantially (see below). An invalid key is ignored — never a 401.

Rate limits

Your key buys one budget, spent across both keyed surfaces — the Discovery API and the keyed read API. Use it wherever you like.

CallerLimit
No key, on the Discovery API or /mcp60 requests / 10 min (30 per Custom GPT user), and 200 / day per IP, of which at most 50 / day are single-boat details
A valid API key, on /api/ai/*, /mcp or the Operator & Data API120 requests / minute and 500 / day, of which at most 150 / day are single-boat details (/ai/boats/{id}, its /standouts, and /ai/boats/compare) — higher on request
Claude and ChatGPT themselves (calls from Anthropic's and OpenAI's published address ranges)No per-IP limit — those servers carry every user of the assistant. Counted per platform instead: 20,000 requests / day, of which at most 2,000 are single-boat details

The daily budgets reset at 00:00 UTC. Every 429 names the limit it hit and links to the same search on charter.boats, so an assistant can send its user to the site.

Every keyed response carries its daily budget in the headers:

HeaderMeaning
X-RateLimit-LimitYour daily allowance
X-RateLimit-RemainingCalls left today
X-RateLimit-ResetSeconds until the budget resets

Past any limit you get 429 with a Retry-After header — seconds for the per-minute brake, seconds until midnight UTC for the daily ones. The detail limit refuses only detail calls: search keeps answering. Read X-RateLimit-Remaining and pace yourself rather than retrying into the wall.

Need higher limits? Contact us before building around them — we raise them per key.

What you can't do with a key

ActionWhy
Book and pay for a charterWebsite checkout only — session + Stripe Elements
Accept or decline a booking requestDashboard only — tied to a logged-in session

The key gives you your own fleet: read it — unpublished boats included, through List Your Fleet — import, update and delete boats, and set their prices, fees, photos and videos, calendar and your company's discounts. Transactional actions — booking, paying, answering a booking request — are tied to a logged-in session on charter.boats and are not exposed as keyed endpoints.

Which companies a key covers

A key belongs to your user account, not to one company. It works for every company your account is a member of: each call checks that you are a member of the boat's company, and deleting a boat needs an owner or admin role there. List Your Fleet without company_id returns the boats of all of them, each row with its company_id; pass company_id to read one. To connect several independent owners, each owner uses their own account and key.

Getting an API Key

Any registered user can generate an API key from the dashboard:

  1. Log in to charter.boats
  2. Go to Dashboard → Settings → API
  3. Read and accept the API usage terms
  4. Click Generate API Key
  5. Copy and save your key (it is only shown once)

Regenerating Your Key

If your key is compromised, you can regenerate it from the same settings page. This will immediately invalidate your old key. If the API terms have changed since you accepted them, the page asks you to accept them again before issuing a new key.

Security Best Practices

Never expose your API key in client-side code, public repositories, or anywhere it could be accessed by unauthorized parties.

Recommendations

DoDon't
Store API keys in environment variablesCommit API keys to version control
Use server-side code to make API callsInclude keys in client-side JavaScript
Rotate keys periodicallyShare keys across different applications
Use different keys for dev and production

Error Responses

Errors are JSON with the status in statusCode and the reason in message (see Response Format). The one exception is a request with no key at all: that is stopped by bot protection and comes back as an HTML 403 page.

401 Unauthorized

MessageWhen
Invalid API keyA key that doesn't belong to any account
Invalid API key formatA malformed key reached the API (from outside, bot protection usually stops it first with the HTML 403)
API key required for external requests. Include X-API-Key header.A request from outside charter.boats reached the API with no key (normally bot protection answers first with the HTML 403)
API key required. Include X-API-Key header.POST /import/boat without a key
Authentication requiredAn Operator API write (other than the import) with neither a key nor a logged-in charter.boats session
{
  "error": true,
  "url": "https://charter.boats/api/boats?limit=1",
  "statusCode": 401,
  "statusMessage": "Server Error",
  "message": "Invalid API key"
}

403 Forbidden

MessageWhen
This key reads only boats your company operates…Reading a boat, its pricing, fees or availability — or listing GET /boats with a company_slug — when you are not a member of that company — use the Discovery API
This key lists only your own fleet…GET /boats without company_slug
Not a company memberWriting to a boat, or to discounts, of a company you don't belong to
Admin access requiredDeleting a boat in a company where you are a plain member (admin or owner required)
API key owner is not a member of the specified companyImporting with a company_id you don't belong to
(HTML page)No key sent — bot protection, not the API