Charter Boats
Charter Boats API
Pricing

Resolve Pricing

Get the resolved price for each day in a date range

GET/boats/:id/pricing

Resolve the effective daily price for each day in a date range. Each day is matched against the boat's seasonal pricing rules. Days with no season coverage come back with no price. This is a pricing lookup, not an availability check -- see the note under Response Fields.

Only sellable seasons take part: those of the boat's active pricing source (pricing_source on Get Boat — a boat listed on two platforms is priced from the one it is booked through), excluding quotes we can't sell (one-way delivery legs, weeks quoted from another base, implausible partner-side prices).

Authentication

Send your API key in the X-API-Key header, as on every Operator API call — see Authentication.

Path Parameters

ParameterTypeDescription
idstringBoat ID (UUID). A slug is not accepted

Query Parameters

ParameterTypeRequiredDescription
startstringYesStart date (YYYY-MM-DD)
endstringYesEnd date (YYYY-MM-DD)
productstringNoPrice one product variant (e.g. Bareboat, Crewed — see mmk_products on Get Boat). Seasons with no product stay in play. Without it, the seasons of every product compete for each day under the rules below, so pass it whenever the boat sells more than one package

The range is exclusive of the end date (i.e., start up to but not including end).

Request

curl "https://charter.boats/api/boats/3a121be0-c1f8-4432-8e18-4a125b46da65/pricing?start=2026-08-01&end=2026-08-08" \
  -H "X-API-Key: YOUR_API_KEY"

Response

{
  "prices": [
    {
      "date": "2026-08-01",
      "price": 213.31,
      "source": "season",
      "seasonName": "High Season 2026",
      "isPriced": true,
      "originalPrice": 355.5,
      "discountPercentage": 43,
      "discountName": "43% discount"
    },
    {
      "date": "2026-08-02",
      "price": 0,
      "source": "season",
      "isPriced": false
    },
    {
      "date": "2026-08-03",
      "price": 0,
      "source": "season",
      "isPriced": false
    },
    {
      "date": "2026-08-04",
      "price": 0,
      "source": "season",
      "isPriced": false
    },
    {
      "date": "2026-08-05",
      "price": 0,
      "source": "season",
      "isPriced": false
    },
    {
      "date": "2026-08-06",
      "price": 0,
      "source": "season",
      "isPriced": false
    },
    {
      "date": "2026-08-07",
      "price": 0,
      "source": "season",
      "isPriced": false
    }
  ],
  "summary": {
    "totalDays": 7,
    "pricedDays": 1,
    "unpricedDays": 6,
    "subtotal": 213.31,
    "minPrice": 213.31,
    "maxPrice": 213.31,
    "avgPrice": 213.31
  }
}

Response Fields

prices array

FieldTypeDescription
datestringDate (YYYY-MM-DD)
pricenumberResolved price for this day; 0 when no season covers it (isPriced: false)
sourcestringAlways season
seasonNamestringName of the matching season (only present for priced days)
isPricedbooleanA season covers this date, so it has a price. Not an availability check -- see the note below
originalPricenumber | nullPre-discount price (if a seasonal discount applies)
discountPercentagenumber | nullActive discount percentage
discountNamestring | nullName of the discount

summary object

FieldTypeDescription
totalDaysintegerTotal days in the range
pricedDaysintegerNumber of days a season covers
unpricedDaysintegerNumber of days no season covers
subtotalnumberSum of prices for priced days
minPricenumberLowest daily price among priced days
maxPricenumberHighest daily price among priced days
avgPricenumberAverage daily price among priced days

This endpoint does not check availability. It reads seasonal pricing only -- it never looks at bookings, blocks or synced calendar events, so a fully booked week still comes back with every day priced. To find out whether a boat is free, call GET /api/boats/availability and treat its blockedDates as nights: the checkout day is handed back in the morning and is never occupied.

Renamed on 2026-08-05 from isAvailable / availableDays / unavailableDays, which read as an availability check and were used as one.

Price Sources

  • season: The day is priced by a seasonal pricing rule. The matching season's name is included in seasonName.

Pricing Waterfall

  1. Season -- a matching season sets the price for the day. Where several seasons cover the same day, they are resolved in this order:
    1. The day's own week. A season that starts on the week-start the day falls in, counted in 7-day steps from the request's start, wins. Partner feeds return one quote per bookable week, so a boat with two changeover days has two overlapping seasons across almost every night; this picks the one quoted for the week the day actually sits in. A 14-day range therefore takes days 8-14 from week two's own season, not week one's.
    2. Priority -- higher priority wins.
    3. Narrower range -- on equal priority, the season covering fewer days wins, since a week-scoped quote is a fresher figure than the season-wide one it overlaps.
  2. No coverage -- if no season covers the day it has no price (isPriced: false, price: 0, no seasonName)

Step 1.1 only breaks ties between seasons that already cover the day -- it never stretches a season or invents a price. A range longer than its own week's season falls through to the remaining rules for the days outside it.

Errors

StatusMessage
400Boat ID must be a UUID
400start and end dates are required
400Dates must be in YYYY-MM-DD format
404Boat not found
500Failed to fetch seasons

An id that is not UUID-shaped — a slug, for instance — answers 400 without touching the database; a well-formed UUID no boat carries answers 404. Both used to be 500 with Boat not found in the message, so an integration written before 2026-09-15 that keys on the message keeps working.

Use Cases

Calculate Booking Total

Price the stay, then add the required fees. Fees are costed per stay the way charter.boats costs them — a percentage fee applies once, to its base for the whole stay, multiplied only by guests — and they split into what is paid online with the booking and what is settled at the base.

const API = 'https://charter.boats/api'
const headers = { 'X-API-Key': process.env.CHARTER_BOATS_API_KEY }
const get = (path) => fetch(`${API}${path}`, { headers }).then((r) => r.json())
 
const range = `start=${checkIn}&end=${checkOut}&product=${encodeURIComponent(product)}`
const { summary } = await get(`/boats/${boatId}/pricing?${range}`)
if (summary.unpricedDays > 0) throw new Error('Not sold for these dates')
 
const fees = await get(`/boats/${boatId}/fees?${range}&guests=${guests}`)
const nights = summary.totalDays
const weeks = Math.ceil(nights / 7)
const charter = summary.subtotal
 
function feeCost(f) {
  if (f.amount_is_percentage) {
    const base = f.percentage_base === 'DAILY_PRICE' ? charter / nights : charter
    const amount = (base * f.amount) / 100
    return f.period.startsWith('per_person') ? amount * guests : amount
  }
  switch (f.period) {
    case 'per_day': return f.amount * nights
    case 'per_week': return f.amount * weeks
    case 'per_person': return f.amount * guests
    case 'per_person_per_day':
    case 'per_person_per_night': return f.amount * guests * nights
    case 'per_person_per_week': return f.amount * guests * weeks
    default: return f.amount // per_booking, one_way
  }
}
 
const required = fees.filter((f) => f.required && f.calculation_type !== 'included_in_price')
const online = required.filter((f) => f.calculation_type === 'advance_payment')
const atBase = required.filter((f) => f.calculation_type !== 'advance_payment')
 
const SERVICE_FEE = 45 // flat €45 per booking
const dueOnline = charter + online.reduce((t, f) => t + feeCost(f), 0) + SERVICE_FEE
const dueAtBase = atBase.reduce((t, f) => t + feeCost(f), 0)

Fees settled at the base (separate_payment, or no calculation_type) are real costs of the charter but are not part of the online payment. Confirm the dates are free with Boat Availability before presenting a total — this endpoint prices booked weeks too.

Display Calendar Prices

curl "https://charter.boats/api/boats/3a121be0-c1f8-4432-8e18-4a125b46da65/pricing?start=2026-07-01&end=2026-08-01" \
  -H "X-API-Key: YOUR_API_KEY"

On this page