Two options
Choose your integration
Direct Feed
app.yachtmaster.cloud
Pull data directly from the app server. Best for server-side rendering or scheduled syncs where you cache the data yourself.
- Real-time data, straight from the database
- Supports incremental sync via ?since=
- No setup required beyond your feed token
Edge Feed
ads.yachtmaster.cloud
Cached and served globally via Cloudflare Workers. Best for browser-side JavaScript, static sites, or anywhere CORS and low latency matter.
- CORS enabled — call directly from the browser
- Served from the nearest Cloudflare edge node
- Single ad lookup via /v1/ads/:token/:id
Get your feed token
Your feed token is a unique UUID that identifies your company's listing feed. It is found in Settings → Adflow inside the YachtMaster app.
The token is included in the URL — anyone with it can read your active listings, so treat it like a public API key. You can regenerate it at any time from the settings page.
The feed includes ads with status forsale, incoming, or sold.
Draft and archived ads are always excluded. Sold ads are kept so you can show a "sold" badge — filter them out client-side (or via ?status= on the edge feed) if you only want live listings.
Your feed URLs look like this
https://app.yachtmaster.cloud/feed/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxhttps://ads.yachtmaster.cloud/v1/ads/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxapp.yachtmaster.cloud
Pull listings directly from the app server. Data is always current — fetched live from the database on every request.
/feed/:tokenQuery parameters
| Parameter | Type | Description |
|---|---|---|
filter | string | Return only ads tagged with this page value. Matches against the web_pages array on each ad.
Example: ?filter=main |
since | ISO 8601 | Return only ads updated after this timestamp. Use for incremental syncs.
Example: ?since=2025-01-01T00:00:00Z |
JavaScript
// Fetch all active ads
const res = await fetch(
'https://app.yachtmaster.cloud/feed/YOUR_TOKEN'
);
const { ads } = await res.json();
// Fetch only ads tagged for your main website
const res = await fetch(
'https://app.yachtmaster.cloud/feed/YOUR_TOKEN?filter=main'
);
// Incremental — only ads changed since last fetch
const res = await fetch(
'https://app.yachtmaster.cloud/feed/YOUR_TOKEN?since=2025-01-01T00:00:00Z'
);Response — 200 OK
{
"feed_generated_at": "2025-01-15T08:00:00.000Z",
"ads": [
{
"id": 1234,
"status": "forsale",
"object_type_id": 1,
"object_type": "motorboat",
"updated_at": "2025-01-14T12:00:00.000Z",
"year": 2019,
"make_name": "Beneteau",
"model": "Oceanis 40.1",
"price": 95000,
"currency": "EUR",
"vat": false,
"vat_marginal": true,
"length": 11.98,
"width": 3.99,
"draft": 2.05,
"weight": 7800,
"cabins": 3,
"berths": 6,
"toilets": 2,
"engine_qty": 1,
"engine_make_name": "Yanmar",
"engine_model": "4JH45",
"engine_year": 2019,
"engine_type_name": { "en": "Inboard", "fi": "Sisäperämoottori", "sv": "Inombordare" },
"engine_fuel_name": { "en": "Diesel", "fi": "Diesel", "sv": "Diesel" },
"distance": 2340,
"material_name": { "en": "GRP", "fi": "Lasikuitu", "sv": "GRP" },
"country_code": "SE",
"country_name": { "en": "Sweden", "fi": "Ruotsi", "sv": "Sverige" },
"city_name": { "en": "Gothenburg", "fi": "Göteborg", "sv": "Göteborg" },
"description": { "en": "...", "fi": "...", "sv": "..." },
"subtitle": { "en": "...", "fi": "...", "sv": "..." },
"web_url": "https://example.com/boats/1234",
"web_pages": ["main"],
"images": [
{
"id": "abc123def456",
"name": "Main photo",
"width": 1920,
"height": 1080,
"type": "jpg",
"url": "https://cdn.yachtmaster.cloud/abc123def456",
"category": "exterior"
}
],
"equipment": [
{
"equipment_group_name": { "en": "Navigation", "fi": "Navigointi", "sv": "Navigation" },
"group_sort": 1,
"equipment_items": [
{
"name": { "en": "GPS", "fi": "GPS", "sv": "GPS" },
"description": "Garmin 742xs"
}
]
}
]
},
{
"id": 1235,
"status": "forsale",
"object_type_id": 4,
"object_type": "car",
"updated_at": "2025-01-14T12:00:00.000Z",
"year": 2021,
"make_name": "Volvo",
"model": "XC60",
"price": 42000,
"currency": "SEK",
"vat": true,
"vat_marginal": false,
"body_type": "suv",
"transmission": "automatic",
"fuel_type": "diesel",
"drive_type": "awd",
"power_kw": 173,
"engine_displacement": 1969,
"color": "grey",
"number_of_seats": 5,
"number_of_doors": 5,
"first_registration_date": "2021-03-01",
"distance": 48000,
"country_code": "SE",
"country_name": { "en": "Sweden", "fi": "Ruotsi", "sv": "Sverige" },
"city_name": { "en": "Gothenburg", "fi": "Göteborg", "sv": "Göteborg" },
"description": { "en": "...", "fi": "...", "sv": "..." },
"subtitle": { "en": "...", "fi": "...", "sv": "..." },
"web_url": "https://example.com/cars/1235",
"web_pages": ["main"],
"images": [],
"equipment": []
}
]
}ads.yachtmaster.cloud
Edge-cached listings served from the Cloudflare network. Syncs automatically when ads are published. CORS headers are included on all responses so you can call this from browser JavaScript without a proxy.
/v1/ads/:tokenQuery parameters
| Parameter | Type | Description |
|---|---|---|
filter | string | Return only ads tagged with this page value.
Example: ?filter=main |
since | ISO 8601 | Return only ads updated after this timestamp.
Example: ?since=2025-01-01T00:00:00Z |
status | string | Filter by ad status. Accepts a single value or comma-separated list.
Valid values: forsale, incoming, sold.
Example: ?status=forsale,incoming |
Response — 200 OK
{
"last_synced_at": "2025-01-15T08:00:00.000Z",
"ads": [ /* same ad objects as Direct Feed */ ]
}/v1/ads/:token/:idReturns a single ad by ID. Returns 404 if the ad doesn't exist
or doesn't belong to this token. The response is the same ad object as in the list endpoint.
JavaScript
// Fetch from the edge (browser-friendly, CORS enabled)
const res = await fetch(
'https://ads.yachtmaster.cloud/v1/ads/YOUR_TOKEN'
);
const { last_synced_at, ads } = await res.json();
// Filter by page
const res = await fetch(
'https://ads.yachtmaster.cloud/v1/ads/YOUR_TOKEN?filter=main'
);
// Filter by status — single value
const res = await fetch(
'https://ads.yachtmaster.cloud/v1/ads/YOUR_TOKEN?status=forsale'
);
// Filter by status — multiple values (comma-separated)
const res = await fetch(
'https://ads.yachtmaster.cloud/v1/ads/YOUR_TOKEN?status=forsale,incoming'
);
// Single ad
const res = await fetch(
'https://ads.yachtmaster.cloud/v1/ads/YOUR_TOKEN/1234'
);Reference
Ad object fields
Every ad in the ads[] array has the following fields.
Fields with no value are returned as null.
Object types
Each ad's object_type slug maps to a numeric object_type_id. Slugs are stable — prefer them over the numeric id.
| id | slug | Description |
|---|---|---|
| 1 | motorboat | Motorboat |
| 2 | sailboat | Sailboat |
| 3 | trailer | Trailer |
| 4 | car | Car |
| 5 | truck | Truck |
| 6 | campervan | Campervan |
| 7 | motorbike | Motorbike |
| 8 | work_machine | Work machine |
| 9 | snowmobile | Snowmobile |
| 10 | jetski | Jetski / watercraft |
| 11 | equipment | Equipment |
| 12 | general | General |
always Always present nullable May be null boats Boat types only — null for cars cars Cars only — null for boats| Field | Type | Present | Description |
|---|---|---|---|
id | number | always | Unique ad identifier |
status | string | always | One of: forsale, incoming, sold |
object_type_id | number | always | Numeric object type: 1 = motorboat, 2 = sailboat, 10 = jetski, 4 = car (see full enum above) |
object_type | string | always | Stable slug: motorboat, sailboat, trailer, car, truck, campervan, motorbike, work_machine, snowmobile, jetski, equipment, general. Branch on this, not the numeric id |
updated_at | ISO 8601 | always | Last modification timestamp |
price | number | nullable | Asking price (null = price on request) |
currency | string | nullable | ISO 4217 currency code (e.g. EUR, SEK) |
vat | boolean | nullable | Price includes VAT |
vat_marginal | boolean | nullable | Margin scheme VAT applies |
year | number | nullable | Build year |
make_name | string | nullable | Manufacturer name |
model | string | nullable | Model name |
distance | number | nullable | Engine hours (boats) or mileage in km (cars) |
description | object | nullable | Localised description: { en, fi, sv } |
subtitle | object | nullable | Localised short description: { en, fi, sv } |
country_code | string | nullable | ISO 3166-1 alpha-2 country code |
country_name | object | nullable | Localised country name: { en, fi, sv } |
city_name | object | nullable | Localised city name: { en, fi, sv } |
zip_code | string | nullable | Postal code |
web_url | string | nullable | URL to the listing on your own website |
web_pages | string[] | always | Page tags this ad is published to (may be empty) |
images | object[] | always | Array of image objects (may be empty, see below) |
equipment | object[] | always | Array of equipment groups (may be empty, see below) |
length | number | boats | Length overall in metres |
width | number | boats | Beam in metres |
draft | number | boats | Draft in metres |
weight | number | boats | Displacement in kg |
cabins | number | boats | Number of cabins |
berths | number | boats | Number of berths |
toilets | number | boats | Number of toilets |
material_name | object | boats | Localised hull material: { en, fi, sv } |
engine_qty | number | boats | Number of engines |
engine_make_name | string | boats | Engine manufacturer |
engine_model | string | boats | Engine model |
engine_year | number | boats | Engine build year |
engine_type_name | object | boats | Localised engine type: { en, fi, sv } |
engine_fuel_name | object | boats | Localised fuel type: { en, fi, sv } |
body_type | string | cars | Body style slug (e.g. suv, sedan, station_wagon) |
transmission | string | cars | manual, automatic or sequential |
fuel_type | string | cars | gasoline, diesel, electric, hybrid, ethanol or gas |
drive_type | string | cars | fwd, rwd or awd |
power_kw | number | cars | Engine power in kW |
engine_displacement | number | cars | Engine displacement in cm³ |
color | string | cars | Exterior colour slug (e.g. black, silver, blue) |
number_of_seats | number | cars | Number of seats |
number_of_doors | number | cars | Number of doors |
first_registration_date | ISO 8601 date | cars | Date of first registration |
id | string | Unique image identifier |
name | string | Image label |
width | number | Width in pixels |
height | number | Height in pixels |
type | string | Format: jpg, webp, png |
url | string | Full CDN URL to the image file |
category | string | null | AI-classified image type: cruising, exterior, interior, layout, technical, or null if unclassified |
equipment_group_name | object | Localised group label: { en, fi, sv, ... } |
group_sort | number | Display sort order |
equipment_items | object[] | Array of equipment item objects (see below) |
name | object | Localised equipment name: { en, fi, sv, de, fr, ... } |
description | string | null | Optional free-text note about this specific item on the boat |
Webhook notifications
Instead of polling, you can configure a webhook endpoint in Settings → Adflow → Web pages.
YachtMaster will send a POST to your endpoint whenever an ad is published or updated.
On receiving this, fetch the feed to get updated listings. An optional API key can be added to the webhook for request validation.
Multiple page feeds
Each ad can be tagged to one or more page filters (e.g. main, regional).
Use ?filter= to serve different feeds from the same token — one per website or section.
Errors
Errors return the appropriate HTTP status with a JSON body of the shape { "error": "message" }. Successful responses return 200.
| Status | When |
|---|---|
200 | Success. Feed or single ad returned. |
404 | Unknown or inactive feed token, or (single-ad endpoint) an ad id that does not exist for this token. |
502 | Edge feed only — the upstream YachtMaster app could not be reached during a sync. |
Caching & sync
Responses are cacheable for 60 seconds. The direct feed is token-gated and
returns Cache-Control: private, max-age=60 (client cache only); the edge feed
is CDN-cacheable and returns public, max-age=60. The feed is not paginated — all matching ads return in a single response.
For incremental syncing, pass ?since=<ISO 8601> to receive
only ads modified after that time, or use the webhook to trigger a refetch.
Versioning & compatibility
New fields are added additively and are not considered breaking — your integration should ignore unknown fields rather than fail on them.
Any breaking change (a removed or renamed field, or changed semantics) ships under a new version path.
The edge feed is versioned at /v1/.
Machine-readable spec
The full contract is published as an OpenAPI 3.1 document — import it into Postman, Insomnia, or a code generator.
Get started
Ready to display your listings?
Enable Adflow in your YachtMaster settings and your feed is live in minutes.
