curl --request GET \
--url https://api.safarapi.com/api/partner/v1/adventures/{slug} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.safarapi.com/api/partner/v1/adventures/{slug}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.safarapi.com/api/partner/v1/adventures/{slug}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.safarapi.com/api/partner/v1/adventures/{slug}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.safarapi.com/api/partner/v1/adventures/{slug}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.safarapi.com/api/partner/v1/adventures/{slug}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.safarapi.com/api/partner/v1/adventures/{slug}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_bodyDetailed adventure record
Full record for one adventure: description, itinerary, inclusions, accommodations and bookable rate packs. The slug is stable and safe to use as an identifier in partner links.
curl --request GET \
--url https://api.safarapi.com/api/partner/v1/adventures/{slug} \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.safarapi.com/api/partner/v1/adventures/{slug}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.safarapi.com/api/partner/v1/adventures/{slug}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.safarapi.com/api/partner/v1/adventures/{slug}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.safarapi.com/api/partner/v1/adventures/{slug}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.safarapi.com/api/partner/v1/adventures/{slug}")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.safarapi.com/api/partner/v1/adventures/{slug}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_bodyAuthorizations
API key authentication. Issued by the Safariat admin or via the partner portal. The secret is shown only once at generation.
Production sk_live_* keys must additionally sign every write request
(POST/PUT/DELETE) with the X-Timestamp and X-Signature headers.
Sandbox sk_test_* keys are exempt from request signing: X-Signature and
X-Timestamp are not required for writes in the sandbox (so the developer-portal
"Try it" playground works end to end). The Idempotency-Key header remains
required on writes in both environments.
Headers
Language of the returned labels (titles, descriptions, categories).
fr, en, ar Path Parameters
Stable adventure slug (usable as an ID in partner links). The example is illustrative — obtain a real value from GET /adventures. The sandbox catalogue mirrors production with every slug suffixed -sandbox; production slugs have no suffix.
200^[a-z0-9-]+$Response
Adventure found
"marrakech-3-jours-desert-sandbox"
EXPERIENCE: short adventure (a few hours to 1 day), hourly slots.TRIP: multi-day tour with an itinerary.
EXPERIENCE, TRIP Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Compact placeholder (BlurHash) for instant rendering before the cover image loads.
Responsive variant URLs of the cover image.
Show child attributes
Show child attributes
Main destination labels.
Indicative revenue breakdown on price_from (indicative = true).
Show child attributes
Show child attributes
Owning agency. name may be null if the agency record was deleted between indexing and read.
Show child attributes
Show child attributes
Computed at search-time from booking ratios. Surfaces UI badges ("plus que 2 places", "complet"). Null if no signal available.
AVAILABLE, FEW_LEFT, SOLD_OUT Haversine distance between the search reference point (lat/lng query params)
and the adventure's primary location. Null if the search was not geo-anchored.
x >= 0Show child attributes
Show child attributes
Multi-day periods grouping consecutive itinerary days (e.g. days 1-3 = "Marrakech to dunes").
Provided alongside itinerary for richer day-by-day rendering on long trips. Empty for
EXPERIENCE adventures.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Where travellers meet the guide (EXPERIENCE only). More than one entry means the operator offers a choice, made at booking time. Coordinates are frequently absent: roughly two thirds of the catalogue declares a name alone, so render the name and the instructions without assuming a map is available.
Show child attributes
Show child attributes
Frequently asked questions, ordered by display index.
Show child attributes
Show child attributes
Host profile (EXPERIENCE adventures only).
Show child attributes
Show child attributes
Future bookable dates, ascending, for every adventure type: the union of the calendars that apply to the rate packs (a pack calendar overrides the adventure one), with past dates and dates past their booking cut-off already removed. Empty when nothing is bookable. For a short-duration adventure these are the bookable days.
Soonest bookable future departure (respects per-pack booking cutoff).
Set when the returned content has been translated from the source language for the
requested Accept-Language. null if the requested locale equals the adventure's
source language (content delivered as authored).
auto, manual Age boundaries used to price travellers: 0..infant_max_age is an infant, infant_max_age+1..child_max_age a child, above child_max_age an adult.
Show child attributes
Show child attributes