Sellers, sites and channels
Sellers
Section titled “Sellers”A seller is a local guide or a tour operator: Vacation Packages Oman in
Muscat, Dubai Fly Tours in Dubai, Vacations of Africa in Tanzania. A seller
owns its trips, prices, calendar and bookings, and runs the trips. Every
trip the API returns carries its seller, so a page can always say who
runs it.
A site, which the API calls a storefront, is where trips are sold. Your
website key names one. GET /v1/public/storefront says which:
curl "http://tourpingo-production-api:4000/v1/public/storefront" \ -H "Tp-Publishable-Key: $TP_KEY"const res = await fetch("http://tourpingo-production-api:4000/v1/public/storefront", { headers: { "Tp-Publishable-Key": process.env.TP_KEY!, },})const answer = await res.json()Answer: 200 OK
{ "id": "7f3a1d2e-5b6c-4d8e-9f01-2a3b4c5d6e7f", "operator_id": "8a4b2e3f-6c7d-4e9f-a012-3b4c5d6e7f80", "kind": "direct", "name": "tourpingo demo", "default_locale": "en", "locales": [ "en", "ar" ], "display_currency": "USD", "currencies": [ "USD", "AED" ], "display_rounding": "up_to_whole", "blog_url": null, "allowed_origins": [], "terms_url": null, "privacy_url": null, "cookies_url": null, "support": { "email": null, "phone": null, "whatsapp": null, "hours": null, "reply_hours": null }, "legal_name": null, "promise": null, "integrations": { "gtm_container_id": null, "ga4_measurement_id": null, "google_ads": { "conversion_id": null, "purchase_label": null, "lead_label": null, "contact_label": null }, "meta_pixel_id": null, "tiktok_pixel_id": null, "microsoft_uet_id": null, "consent": "opt_in", "enhanced_conversions": true }}| Field | What it is |
|---|---|
kind |
direct: one seller’s own site. marketplace: tourpingo’s marketplace, selling every seller’s trips approved for it. |
default_locale, locales |
The languages the site is in. |
display_currency, currencies |
The currency prices are shown in, and the others a traveller can pick. |
display_rounding |
How converted prices are rounded for display: none, up_to_whole or up_to_99. |
allowed_origins |
The sites a browser may call the API from with this key, and the only pages the booking embed may be shown on. Empty: server to server only. |
terms_url, privacy_url, cookies_url |
The site’s terms for travellers, its privacy policy and its cookie statement: a path on the site, such as /terms, or an address. Link the first two where travellers book, and all three in your footer. Null when the seller has none. |
support |
How travellers reach the site’s people: its email, phone and whatsapp, the hours someone answers (days as ISO weekdays, opens, closes and time_zone) and reply_hours, how soon a message is usually answered. Each is null until the seller sets it: show only what is there, never a placeholder. |
legal_name |
The company the site is published by, for a copyright line; null when the seller hasn’t said. |
promise |
On the marketplace, what it promises travellers: report_hours, how long after a trip’s start a traveller has to report that nobody came, and payer, who pays a refund support agrees (seller or platform). Null on a seller’s own site. |
A seller can have more than one site, each with its own key, languages and currencies.
The same API, one seller or many
Section titled “The same API, one seller or many”On a direct site every trip is the seller’s own. On the marketplace,
lists hold many sellers’ trips, and GET /v1/public/sellers lists the
sellers:
curl "http://tourpingo-production-api:4000/v1/public/sellers?locale=en" \ -H "Tp-Publishable-Key: $TP_KEY"const res = await fetch("http://tourpingo-production-api:4000/v1/public/sellers?locale=en", { headers: { "Tp-Publishable-Key": process.env.TP_KEY!, },})const answer = await res.json()Answer: 200 OK
{ "data": [ { "slug": "vpo", "name": "Vacation Packages Oman", "country": { "slug": "om", "name": "Oman" }, "trip_count": 41, "kind": "operator", "base": "Seeb, Muscat, Oman", "blurb": "Day trips and packages across Oman", "rating": null, "short_name": null, "logo": null }, { "slug": "voa", "name": "Vacations of Africa", "country": { "slug": "tz", "name": "Tanzania" }, "trip_count": 18, "kind": "operator", "base": "Tanzania", "blurb": "Safaris, Zanzibar and Kilimanjaro", "rating": null, "short_name": null, "logo": null }, { "slug": "dft", "name": "Dubai Fly Tours", "country": { "slug": "ae", "name": "United Arab Emirates" }, "trip_count": 5, "kind": "operator", "base": "Dubai, UAE", "blurb": "Tours in Dubai, Abu Dhabi and Sharjah", "rating": null, "short_name": null, "logo": null } ]}Each seller says what it is in kind: guide for a guide who works on
their own, operator for a tour company or a seller that hasn’t said. A
trip’s seller has the same field, so a site can call them “local guide”
or “tour operator” on the trip’s page.
curl "http://tourpingo-production-api:4000/v1/public/products?limit=3&locale=en" \ -H "Tp-Publishable-Key: $TP_KEY"const res = await fetch("http://tourpingo-production-api:4000/v1/public/products?limit=3&locale=en", { headers: { "Tp-Publishable-Key": process.env.TP_KEY!, },})const answer = await res.json()Answer: 200 OK (shortened)
{ "data": [ { "template": "multi_day", "content_locale": "en", "sales_paused": false, "duration_days": 4, "duration_nights": 3, "id": "0d1e2f3a-4b5c-4d6e-8f70-81a2b3c4d5e6", "slug": "zanzibar-the-slave-route", "title": "Zanzibar: the slave route", "duration_minutes": null, "city": { "slug": "stone-town", "name": "Stone Town" }, "country": { "slug": "tz", "name": "Tanzania" }, "seller": { "slug": "voa", "name": "Vacations of Africa" }, "from_price": null }, { "template": "day_tour", "content_locale": "en", "sales_paused": false, "duration_days": null, "duration_nights": null, "id": "8b9c0d1e-2f3a-4b4c-9d5e-6f7a8b9c0d1e", "slug": "desert-safari-with-bbq-dinner", "title": "Desert safari with BBQ dinner", "duration_minutes": 360, "city": { "slug": "dubai", "name": "Dubai" }, "country": { "slug": "ae", "name": "United Arab Emirates" }, "seller": { "slug": "dft", "name": "Dubai Fly Tours" }, "from_price": { "amount": 7800, "currency": "USD", "group_size": 1 } }, { "template": "day_tour", "content_locale": "en", "sales_paused": false, "duration_days": null, "duration_nights": null, "id": "1e2f3a4b-5c6d-4e7f-9081-92b3c4d5e6f7", "slug": "wadi-shab-and-wadi-tiwi", "title": "Wadi Shab and Wadi Tiwi", "duration_minutes": 480, "city": { "slug": "muscat", "name": "Muscat" }, "country": { "slug": "om", "name": "Oman" }, "seller": { "slug": "vpo", "name": "Vacation Packages Oman" }, "from_price": { "amount": 9500, "currency": "USD", "group_size": 4 } } ], "next_cursor": "WyIyMDI2LTA5LTIwVDA5OjA1OjAwLjAwMFoiLCIxZTJmM2E0Yi01YzZkLTRlN2YtOTA4MS05MmIzYzRkNWU2ZjciXQ", "total": 64}Two sellers on the marketplace can use the same slug, so open a trip there
by its slug with its seller: GET /v1/public/products/{product} with
seller, e.g. ?seller=dft. A direct site ignores seller.
Channels
Section titled “Channels”Each booking remembers where it was made, its channel:
direct: on the seller’s own site. The seller collects the money, and tourpingo takes no commission.marketplace: on tourpingo’s marketplace.
The channel comes from the key, like everything else about the site.