Import Boat
Import a boat listing with images
Same in API v1.0 and v1.1
/import/boatImport a new boat listing in a single API call. Handles creating the boat, storing image URLs, and auto-matching to a marina location. The boat is created unpublished — see Publishing.
Boat already on Boataround? You do not need to call this yourself: our Chrome extension imports your own Boataround listing with your API key in one click. See Import your boat from Boataround.
Authentication
Requires API key in the X-API-Key header.
- Your API key: the boat is created under a company you belong to — one you own, when you own one. If you belong to none, the request fails with
400("Create your company in the dashboard first") and nothing is created.owner_id/owner_emailare ignored. To target a specific company, passcompany_id— you must be a member of it, or the request fails with403. - Platform key (internal): requires
owner_idorowner_emailin the request body to identify who the boat belongs to. Only the platform key creates a personal "…'s Fleet" company, for an owner who belongs to none.
Every field is checked before anything is written: a request that fails with 400 creates no boat, company, owner, make or location.
Request Body
Required Fields
| Field | Type | Description |
|---|---|---|
title | string | Boat name/title |
boat_type | string | One of: catamaran, sailboat, yacht, motorboat, gulet, rib, other. Optional when model (with manufacturer_id or manufacturer_name) names a model we already know the type of — the boat then takes that model's type; a type you send always wins |
capacity | integer | Maximum guests (must be at least 1) |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
description | string | Full description, as plain text. Line breaks are kept; HTML and markdown are shown as typed, not rendered | |
price_per_day | number | Daily rate, returned as price_from (the boat's price_per_day is computed later from its seasons, and stays null until it has one). | |
length_ft | number | Length overall (LOA) in feet. Values outside the plausible hull range (~6.5–350 ft) are stored as no length rather than as sent — only boats priced from a connected platform take their length from the model catalogue. | |
year | integer | Year built | |
cabins | integer | Number of cabins | |
berths | integer | Number of berths | |
toilets | integer | Number of toilets | |
model | string | Boat model name, stored as sent | |
manufacturer_id | string | An existing make's id, as GET /api/manufacturers lists it; used as sent, ahead of manufacturer_name. An id that names no make fails the request with 400 | |
manufacturer_name | string | The make. Matched on its slug (the name lowercased, non-alphanumerics turned into -), then on the exact name ignoring case, then on the make's known aliases — so send the name as GET /api/manufacturers lists it. A name that matches no existing make creates a new one, and boats under a stray make don't answer the site's make filter for the real one. | |
rental_type | string | bareboat | bareboat, skippered, or no_licence_needed |
security_deposit | number | Security deposit amount | |
skipper | integer|null | 0 = no skipper, 1 = always skippered, null = skipper is an optional add-on | |
mmsi | integer | The boat's MMSI, for AIS tracking | |
flespi_imei | string | IMEI of the boat's tracking modem | |
flespi_modem_model | string | Model of the boat's tracking modem | |
instant_book | boolean | false | Allow instant booking |
charter_day | integer | Charter start weekday (0=Sun … 6=Sat), stored as sent | |
check_in_periods | array | Check-in/out windows, stored as sent — the shape Get Boat returns (dateFrom, dateTo, checkInDays, checkOutDays, checkInTime, checkOutTime, minimalReservationDuration) | |
checkin_time | string | Check-in time (e.g. "17:00"); not sent = to be confirmed | |
checkout_time | string | Check-out time (e.g. "09:00"); not sent = to be confirmed | |
is_published | boolean | false | Runs the completeness check — see Publishing |
Publishing
An imported boat is created unpublished. A listing goes live only when it is complete —
a title, a location, a capacity, at least one image, and check-in days
(charter_day or check_in_periods). is_published: true runs that completeness check after
the images are stored: a complete import is published, an incomplete one stays unpublished.
The response's boat.is_published says which.
A missing location, capacity or check-in days can be sent later through Update Boat, which re-runs the same check on every save. Images are not a field of Update Boat: send them with the import, or add them in the dashboard.
Location Fields
The boat is placed on a marina in this order:
location_id. An existing location's id is used as sent. An id that names no location fails the request with400.- Coordinates. With
latitudeandlongitude, the nearest known location inside a box of roughly ±1 km around the point is used, so send the marina's own coordinates. - New marina. If nothing is that close, a new marina is created at the coordinates, named after
location_address. Without one it has no name and is shown by its type ("Marina") — a name is never made up from the city.
A name alone never finds a location: location_address, location_city and location_state only fill in a newly created marina. A boat sent with neither location_id nor coordinates gets no location.
| Field | Type | Description |
|---|---|---|
location_id | integer | An existing location's id, used as sent |
location_city | string | City; stored on a newly created marina only |
location_state | string | Country; stored as the country of a newly created marina only |
location_address | string | Marina name, used to name a newly created marina |
latitude | number | GPS latitude |
longitude | number | GPS longitude |
Deduplication Fields
Both are accepted. When import_source names a platform whose listing IDs we link boats to, import_source_id is that link and is checked for duplicates; for any other platform both are ignored.
| Field | Type | Description |
|---|---|---|
import_source | string | Platform name |
import_source_id | string | The boat's listing ID on that platform |
Owner Identification
| Field | Type | Description |
|---|---|---|
company_id | string | Assign to a specific company (overrides auto-detection). With your API key you must be a member of it (403 otherwise) |
owner_id | string | Platform key only — ignored with your own API key |
owner_email | string | Platform key only — ignored with your own API key |
owner_name | string | Platform key only — ignored with your own API key |
Images
Array of image URLs or image objects. The first image is set as primary unless specified otherwise.
| Field | Type | Default | Description |
|---|---|---|---|
images | array | Image URLs (strings) or objects with url and optional is_primary | |
download_images | boolean | Accepted for older integrations and ignored. Every image is copied to our storage by an hourly job after the import; until then it is shown from your URL, so keep the URL reachable |
Equipment
Send equipment as features: an array of canonical slugs or plain names ("wifi", "Air condition"), resolved through the same vocabulary the features search filter uses — see Feature Vocabulary. Terms that resolve to nothing are ignored and counted out of features_added. amenities is accepted as the old spelling of the same array. Equipment can also be edited in the dashboard after import.
Request
Response
The boat object carries the fields your dashboard's boat editor reads — specs, location, changeover,
booking settings, pricing source and the features slug array — plus slug, price_from and
price_per_day, and company, manufacturer and images. Only the most relevant fields are shown below. Store boat.id — the slug in view_url can change when the listing is renamed.
Response Fields
| Field | Type | Description |
|---|---|---|
success | boolean | Whether the import succeeded |
duplicate | boolean | true if an existing boat was returned (a boat of the same company already carries that listing ID) |
boat | object | The created boat with company, manufacturer and images; on a duplicate, the existing boat with company and images |
images_uploaded | integer | Number of image records created (absent on a duplicate) |
images_downloaded | integer | Always 0: no image is copied during the request. An image has been copied once its url in Get Boat is stored with us (path starting /boats/) (absent on a duplicate) |
features_added | integer | Canonical feature slugs resolved from the features array and stored (absent on a duplicate) |
view_url | string | Public URL of the listing — it serves once the boat is published |
Deduplication Behavior
When import_source names a platform whose listing IDs we link boats to and import_source_id is provided:
- Same company: Returns the existing boat with
duplicate: trueand nothing is changed — the response is{ success, duplicate: true, boat, view_url }only (no image or feature counters) - Only another company: Returns
409 Conflict
The check runs before the boat, its images or a new marina are created, so a duplicate adds none of them.
Errors
| Status | Message |
|---|---|
400 | title is required |
400 | boat_type is required |
400 | boat_type is required for this model |
400 | boat_type must be one of: catamaran, sailboat, yacht, motorboat, gulet, rib, other |
400 | capacity is required and must be >= 1 |
400 | rental_type must be one of: bareboat, skippered, no_licence_needed |
400 | <field> must be a number |
400 | manufacturer_id not found |
400 | location_id not found |
400 | Create your company in the dashboard first |
400 | Owner identification required: provide owner_id or owner_email |
401 | Invalid API key format |
401 | Invalid API key |
403 | You are not a member of the specified company |
409 | This boat has already been imported by another company |
500 | Failed to create company: … |
500 | Failed to create boat: … |
A request with no key at all is stopped by bot protection before it reaches this endpoint (an HTML 403 page).