Get POI
Get full details for a specific point of interest
Endpoint
Description
Retrieve full details for a point of interest, including nearby marina locations, other POIs grouped by category, images, content references, and special offers (for claimed businesses).
Authentication
Send X-API-Key: YOUR_API_KEY on every call from outside charter.boats — without it Cloudflare bot protection answers with an HTML 403 page, not JSON. Call it from your server: this route sends no CORS headers. See Authentication.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | POI ID (UUID format) |
Example Request
Example Response
special_offers is only populated for claimed businesses; it is an empty array otherwise. POIs carry no rating or rating_count — the fields were withdrawn and then removed, because they were scraped from a search engine with no check that the result was this business. Ratings on nearby_locations are unaffected: those are marinas, and a knowledge panel for a named marina is answering about that marina.
Response Fields
| Field | Type | Description |
|---|---|---|
id | string | POI ID (UUID) |
osm_id | number|null | OpenStreetMap ID |
osm_type | string|null | OSM type (node, way, relation) |
name | string | Name (local language), or the POI's type where OSM gave it no name ("Parking", "Pharmacy"). Never null — use category + subcategory to render your own label instead. |
name_en | string|null | English name |
category | string | POI category |
subcategory | string|null | More specific category |
lat | number | Latitude |
lon | number | Longitude |
address | string|null | Street address |
city | string|null | City |
country | string|null | Country |
country_code | string|null | ISO country code (lowercase when present) |
phone | string|null | Phone number |
website | string|null | Website URL |
email | string|null | Email address |
opening_hours | string|null | Opening hours (OSM format) |
seasonal_hours | string|null | Seasonal opening hours |
is_seasonal | boolean|null | Whether the business is seasonal |
description | string|null | Description (markdown) |
cuisine | string|null | Cuisine type (restaurants) |
wikidata_id | string|null | Wikidata entity ID |
wikipedia_url | string|null | Wikipedia page URL |
image_url | string|null | Primary image URL |
image_attribution | string|null | Attribution for image_url |
image_source / image_source_url | string|null | Source label / source page for the primary image |
enriched_at | string|null | Timestamp of last AI enrichment |
osm_tags | object|null | Raw OpenStreetMap tags |
last_updated / created_at | string | Row timestamps |
social_links | object|null | Social media links (when known) |
claimed_by / claimed_at | string|null | Set when a business owner has claimed the POI |
images | array | Active POI images, sorted by sort_order (url, source, source_url, attribution, is_primary, storage_path). Our own copies are served from https://media.charter.boats/; if you receive one on another storage host, request the same path from media.charter.boats. Third-party image URLs are returned as-is |
nearby_locations | array | Up to 4 closest published charter locations (marinas/harbours/bays), nearest first |
nearby_locations[].slug | string|null | Location slug — pass it to Get Location |
nearby_locations[].name | string|null | The location's stored name. Can be null for a place with no name — unlike Get Location, which substitutes the type label; render the type yourself |
nearby_locations[].state / .municipality | string|null | Region fields on each neighbor |
nearby_locations[].capacity / .max_draft / .vhf_channel | mixed|null | Marina facility fields |
nearby_locations[].distance_meters | number | Distance from the POI |
nearby_locations[].walking_time_minutes | number | Estimated walking time |
pois_by_category | object | Other POIs at the nearest location (nearby_locations[0]), grouped by category, nearest to that location first; each carries id, name (never null — the type where unnamed), name_en, category, subcategory, image_url, distance_meters, walking_time_minutes. At most 100 in total, across all categories (a flat cap, not per category) — for the full set of one category use /pois/search?location_id=…&category=… |
references | array | Content sources and attributions (title, url, source_domain) |
special_offers | array | Active offers from claimed businesses (empty unless claimed) |
Special Offer Fields
| Field | Type | Description |
|---|---|---|
id | string | Offer ID |
title | string | Offer title |
description | string|null | Offer description |
discount_type | string|null | Type of discount (percentage, fixed, etc.) |
discount_value | number|null | Discount amount |
start_date | string|null | Start date (YYYY-MM-DD) |
end_date | string|null | End date (YYYY-MM-DD) |
coupon_code | string|null | Coupon code |
redeem_url | string|null | URL to redeem the offer |
terms_conditions | string|null | Terms and conditions |
cta_type | string|null | Call-to-action type: book, order, learn_more, get_offer, call, shop or sign_up |
cta_url | string|null | Call-to-action link |
media_url | string|null | Image or video attached to the offer |
Error Responses
400 Bad Request
404 Not Found
Also returned for a POI that has been retired (for example a duplicate car park folded into its neighbour) — a retired POI is not served, even by its id.