v1

API

Free, read-only JSON for every boat, region and operator in the index. No key, no rate limits, CORS enabled.

Overview

The whole index is published as static JSON files over HTTPS. There is no key, no sign-up and no rate limit, and CORS is open, so you can call it straight from a browser.

Files are regenerated every time the index is updated. All endpoints are GET and live under:

Base URL
https://liveaboardindex.com/api/v1

Quick start

Find a boat by IMO, then fetch its full record:

Shell
curl https://liveaboardindex.com/api/v1/lookup/imo/8978930.json
# {"id":"lvb_7k2m9q"}

curl https://liveaboardindex.com/api/v1/boats/lvb_7k2m9q.json

The same in JavaScript. A lookup that doesn't exist returns HTTP 404:

JavaScript
const base = 'https://liveaboardindex.com/api/v1'

const res = await fetch(`${base}/lookup/imo/8978930.json`)
if (res.status === 404) throw new Error('Not in the index')
const { id } = await res.json()

const boat = await fetch(`${base}/boats/${id}.json`).then((r) => r.json())

For search or filtering, download /boats.json once and filter it locally. It holds every active boat:

JavaScript
const boats = await fetch('https://liveaboardindex.com/api/v1/boats.json').then((r) => r.json())
const big = boats.filter((b) => b.guests >= 16 && b.region === 'galapagos')

Endpoints

PathReturns
/boats.jsonEvery active boat, compact
/boats/{id}.jsonOne boat, full record
/lookup/imo/{imo}.jsonBoat ID by IMO
/lookup/mmsi/{mmsi}.jsonBoat ID by MMSI
/regions.jsonEvery region
/regions/{id}.jsonBoats in a region
/operators.jsonEvery active operator
/operators/{id}.jsonOne operator, full record

List boats

GET /api/v1/boats.json

Every active boat in a compact form, sorted by name. Merged duplicates are left out.

Example: /api/v1/boats.json

Response
[
  {
    "id": "lvb_7y50yc",
    "name": "Aqua",
    "url": "/boats/lvb_7y50yc/aqua",
    "imo": null,
    "mmsi": null,
    "flag": null,
    "region": "galapagos",
    "operator": "op_kmy8",
    "hull": null,
    "loa_m": 26,
    "guests": 16,
    "cabins": 9,
    "status": "active"
  },
  {
    "id": "lvb_7k2m9q",
    "name": "Calipso",
    "url": "/boats/lvb_7k2m9q/calipso",
    "imo": 8978930,
    "mmsi": 735023481,
    "flag": "EC",
    "region": "galapagos",
    "operator": "op_snng",
    "hull": "steel_motor",
    "loa_m": 36,
    "guests": 16,
    "cabins": 8,
    "status": "active"
  },
  … 7 more
]

Get a boat

GET /api/v1/boats/{id}.json

The full record. Exists for every ID ever issued, including merged ones; see merges.

Example: /api/v1/boats/lvb_7k2m9q.json

Response
{
  "id": "lvb_7k2m9q",
  "names": [
    {
      "name": "Calipso",
      "from": null,
      "to": null
    }
  ],
  "hull": "steel_motor",
  "built": {
    "year": 1991,
    "yard": null
  },
  "imo": 8978930,
  "mmsi": 735023481,
  "call_sign": "HC-2081",
  "flag": "EC",
  "loa_m": 36,
  "beam_m": 8,
  "gt": 249,
  "refit_year": 2019,
  "guests": 16,
  "cabins": 8,
  "bathrooms": 9,
  "max_speed_kn": 11,
  "cruising_speed_kn": 9,
  "engines": {
    "count": 2,
    "make": "cummins",
    "model": "NTA855-M",
    "power_hp": 400
  },
  "tenders": 2,
  "fuel_l": 27255,
  "water_l": 18927,
  "watermaker_lpd": null,
  "cabin_types": [
    {
      "name": "Upper Deck Cabins",
      "count": null,
      "max_guests": 2,
      "beds": {
        "single": 0,
        "double": 1,
        "bunk": 0,
        "convertible": true
      },
      "size_m2": {
        "min": 11,
        "max": 13
      },
      "deck": "upper",
      "window": "panoramic",
      "bathroom": "ensuite",
      "aircon": true,
      "external_ids": {
        "liveaboard_com": 9461
      }
    },
    {
      "name": "Main Deck Cabins",
      "count": null,
      "max_guests": 2,
      "beds": {
        "single": 0,
        "double": 1,
        "bunk": 0,
        "convertible": true
      },
      "size_m2": {
        "min": 11,
        "max": 13
      },
      "deck": "main",
      "window": "panoramic",
      "bathroom": "ensuite",
      "aircon": true,
      "external_ids": {
        "liveaboard_com": 9462
      }
    }
  ],
  "amenities": [
    "ensuite_bathrooms",
    "aircon_cabins",
    "seaview_cabins",
    "non_smoking_cabins",
    "tv_in_cabins",
    "hot_showers",
    "outside_showers",
    "indoor_saloon",
    "aircon_saloon",
    "outdoor_dining",
    "bar",
    "bbq",
    "sun_deck",
    "leisure_deck",
    "jacuzzi",
    "library",
    "entertainment",
    "internet",
    "charging_stations",
    "camera_station",
    "camera_rinse",
    "housekeeping",
    "purpose_built_dive",
    "private_charter"
  ],
  "dive_facilities": [
    "dive_deck",
    "shaded_dive_area",
    "dive_tenders",
    "rinse_hoses",
    "nitrox",
    "din_adaptors",
    "sidemount",
    "gear_rental"
  ],
  "safety": [
    "radar",
    "gps",
    "vhf_dsc_ssb",
    "satellite_phone",
    "depth_sounder",
    "searchlight",
    "epirb",
    "flares",
    "life_rafts",
    "life_vests",
    "fire_suppression",
    "bilge_alarm",
    "engine_room_cctv",
    "oxygen",
    "first_aid_kit",
    "crew_first_aid"
  ],
  "dining": [
    "local_food",
    "western_food",
    "vegetarian",
    "vegan",
    "buffet",
    "snacks",
    "beer",
    "wine"
  ],
  "languages": [
    "en",
    "es"
  ],
  "operator": "op_snng",
  "region": "galapagos",
  "status": "active",
  "merged_into": null,
  "external_ids": {
    "liveaboard_com": 5901
  },
  "sources": [
    "https://magicport.ai/vessels/passenger/calipso-mmsi-735023481",
    "https://www.liveaboard.com/diving/galapagos/calipso"
  ],
  "notes": "",
  "name": "Calipso",
  "url": "/boats/lvb_7k2m9q/calipso"
}

Look up by IMO or MMSI

GET /api/v1/lookup/imo/{imo}.json
GET /api/v1/lookup/mmsi/{mmsi}.json

Returns the ID of the active boat with that number, or HTTP 404 if there is none.

Examples: /api/v1/lookup/imo/8978930.json, /api/v1/lookup/mmsi/735023481.json

Response
{
  "id": "lvb_7k2m9q"
}

List regions

GET /api/v1/regions.json

Every region: { id, name, countries }, with ISO country codes.

Example: /api/v1/regions.json

Response
[
  {
    "id": "galapagos",
    "name": "Galápagos",
    "countries": [
      "EC"
    ]
  }
]

Boats in a region

GET /api/v1/regions/{id}.json

Active boats in the region, in the same compact form as /boats.json. Only regions with at least one boat have a file.

Example: /api/v1/regions/galapagos.json

Response
[
  {
    "id": "lvb_7y50yc",
    "name": "Aqua",
    "url": "/boats/lvb_7y50yc/aqua",
    "imo": null,
    "mmsi": null,
    "flag": null,
    "region": "galapagos",
    "operator": "op_kmy8",
    "hull": null,
    "loa_m": 26,
    "guests": 16,
    "cabins": 9,
    "status": "active"
  },
  {
    "id": "lvb_7k2m9q",
    "name": "Calipso",
    "url": "/boats/lvb_7k2m9q/calipso",
    "imo": 8978930,
    "mmsi": 735023481,
    "flag": "EC",
    "region": "galapagos",
    "operator": "op_snng",
    "hull": "steel_motor",
    "loa_m": 36,
    "guests": 16,
    "cabins": 8,
    "status": "active"
  },
  … 7 more
]

List operators

GET /api/v1/operators.json

Every active operator, with the number of active boats it runs.

Example: /api/v1/operators.json

Response
[
  {
    "id": "op_366c",
    "name": "Aggressor Fleet & Dancer Fleet",
    "url": "/operators/op_366c/aggressor-fleet-dancer-fleet",
    "country": null,
    "status": "active",
    "boats": 1
  },
  {
    "id": "op_kmy8",
    "name": "Andean Travel Company",
    "url": "/operators/op_kmy8/andean-travel-company",
    "country": null,
    "status": "active",
    "boats": 1
  },
  … 6 more
]

Get an operator

GET /api/v1/operators/{id}.json

The full operator record.

Example: /api/v1/operators/op_snng.json

Response
{
  "id": "op_snng",
  "names": [
    {
      "name": "Calipso Galapagos",
      "from": null,
      "to": null
    }
  ],
  "country": null,
  "website": null,
  "status": "active",
  "merged_into": null,
  "external_ids": {
    "liveaboard_com": 1290
  },
  "sources": [],
  "notes": "",
  "name": "Calipso Galapagos",
  "url": "/operators/op_snng/calipso-galapagos"
}

IDs

Boats are lvb_ + 6 characters, operators op_ + 4, in lowercase Crockford base32 (no i, l, o or u). IDs are random, never change and are never reused, even if a boat is renamed, reflagged or sold.

Store the ID, not the name or IMO. IMO and MMSI are attributes: they can be missing, and an MMSI can change when a boat is reflagged.

API paths are exact and lowercase. Website URLs are forgiving: /boats/LVB_7K2M9Q and any slug redirect to the canonical page.

Merges

When two records turn out to be the same boat, one is kept and the other gets status: "merged" plus merged_into with the surviving ID. Merged records drop out of lists and lookups, but their /boats/{id}.json file stays forever, so stored IDs keep resolving. Follow merged_into to get the current record.

Boat fields

FieldTypeDescription
idstringPermanent ID: lvb_ + 6 Crockford base32 characters. Never changes or gets reused.
namestringCurrent name.
urlstringCanonical page on liveaboardindex.com. For merged boats, the page of the boat it was merged into.
namesarrayName history, oldest first: { name, from, to }. to: null marks the current name. Dates are a year, YYYY-MM or YYYY-MM-DD.
statusstringOne of active, retired, lost, merged.
merged_intostring | nullWhen status is merged, the ID of the record this duplicate was merged into.
regionstring | nullRegion ID, see /regions.json.
operatorstring | nullOperator ID (op_xxxx).
hullstring | null<material>_<propulsion>. Materials: steel, wood, aluminium, fiberglass, composite. Propulsion: motor, sail, motor_sail.
builtobject{ year, yard }, both nullable.
refit_yearnumber | nullYear of the last major refit.
guestsnumber | nullMaximum guests.
cabinsnumber | nullGuest cabins.
bathroomsnumber | nullNumber of bathrooms.
cabin_typesarrayCabin types: { name, count, max_guests, beds, size_m2, deck, window, bathroom, aircon, external_ids }. beds is { single, double, bunk, convertible }; size_m2 is { min, max }. Deck: lower, main, upper, sun, across. Window: none, porthole, standard, picture, panoramic. Bathroom: ensuite, shared. count is the number of cabins of that type, when known.
amenitiesstring[]On-board amenities: ensuite_bathrooms, aircon_cabins, seaview_cabins, family_cabins, non_smoking_cabins, tv_in_cabins, hot_showers, outside_showers, indoor_saloon, aircon_saloon, outdoor_dining, bar, bbq, sun_deck, observation_deck, leisure_deck, jacuzzi, library, entertainment, internet, charging_stations, camera_station, camera_rinse, laundry, housekeeping, kayaks, snorkeling_gear, naturalist_guide, non_diver_friendly, purpose_built_dive, private_charter.
dive_facilitiesstring[]Diving setup: dive_deck, shaded_dive_area, dive_tenders, rinse_hoses, nitrox, din_adaptors, sidemount, tech_diving, gear_rental.
safetystring[]Navigation and safety equipment: radar, gps, vhf_dsc_ssb, satellite_phone, depth_sounder, fishfinder, searchlight, epirb, flares, life_rafts, life_vests, fire_suppression, bilge_alarm, engine_room_cctv, oxygen, first_aid_kit, crew_first_aid.
diningstring[]Food and drink: local_food, western_food, vegetarian, vegan, buffet, set_menu, snacks, beer, wine.
languagesstring[]Languages the crew speaks, ISO 639-1 (e.g. en, es).
max_speed_knnumber | nullTop speed, knots.
cruising_speed_knnumber | nullCruising speed, knots.
enginesobject | null{ count, make, model, power_hp }, power_hp per engine. Makes: caterpillar, cummins, detroit_diesel, deutz, john_deere, man, mitsubishi, mtu, mwm, perkins, scania, volvo_penta, yanmar.
tendersnumber | nullNumber of tenders (dinghies / skiffs).
fuel_lnumber | nullFuel capacity, liters.
water_lnumber | nullFresh water capacity, liters.
watermaker_lpdnumber | nullWatermaker output, liters per day.
loa_mnumber | nullLength overall, meters.
beam_mnumber | nullBeam, meters.
gtnumber | nullGross tonnage.
imonumber | nullIMO number (7 digits, check digit validated). Unique across active boats.
mmsinumber | nullMMSI (9 digits). Unique across active boats.
call_signstring | nullRadio call sign.
flagstring | nullFlag state, ISO 3166-1 alpha-2 (e.g. EC).
external_idsobjectIDs in other systems: { liveaboard_com }.
sourcesstring[]URLs the data was checked against.
notesstringFree-form editorial notes; empty string if none.

Operator fields

FieldTypeDescription
idstringPermanent ID: op_ + 4 Crockford base32 characters.
namestringCurrent name.
urlstringCanonical page on liveaboardindex.com.
namesarrayName history, same shape as for boats.
statusstringOne of active, defunct, merged.
merged_intostring | nullWhen merged, the ID of the operator it was merged into.
countrystring | nullHome country, ISO 3166-1 alpha-2.
websitestring | nullOfficial website.
external_idsobjectIDs in other systems: { liveaboard_com }.
sourcesstring[]URLs the data was checked against.
notesstringFree-form editorial notes; empty string if none.

List endpoints return a subset of these fields. /operators.json adds boats, the number of active boats.

Versioning

Within v1, fields may be added but are never renamed, removed or changed in type, so ignore fields you don't know. A breaking change would ship as /api/v2 alongside v1.

Missing values are always null, never omitted.