{
"id": "ad000002-0000-4000-8000-0000000000d2",
"slug": "marrakech-3-jours-desert-sandbox",
"type": "TRIP",
"title": "[DEMO] 3-day Sahara desert circuit from Marrakech",
"subtitle": null,
"duration": {
"days": 3,
"hours": 0,
"minutes": 0
},
"cover_image_url": "https://placehold.co/600x400?text=DEMO",
"destinations": [
"Marrakech"
],
"categories": [
"desert"
],
"price_from": {
"amount": "2400.00",
"currency": "MAD"
},
"rating": {
"average": 4.7,
"count": 23
},
"agency": {
"id": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"name": "Sahara Demo Trekking"
},
"description": "A 3-day circuit from Marrakech to the Sahara dunes, with overnight stays in the desert.",
"highlights": [
"Camel trek at sunset over the Erg Chebbi dunes",
"Night under the stars in a desert camp"
],
"includes": [
"Air-conditioned 4x4 transport",
"2 nights accommodation",
"Half board"
],
"excludes": [
"Personal expenses",
"Travel insurance"
],
"what_to_bring": [
"Warm layer for the desert night",
"Sunscreen"
],
"good_to_know": [
"Departure at 07:00 from central Marrakech"
],
"gallery": [
"https://placehold.co/600x400?text=DEMO"
],
"itinerary": [
{
"day_number": 1,
"title": "Marrakech to Dades Valley",
"description": "Drive over the Tizi n'Tichka pass with photo stops.",
"steps": [
{
"order": 1,
"title": "Departure from Marrakech",
"description": "Pickup at the central meeting point.",
"duration": "30 min"
}
]
},
{
"day_number": 2,
"title": "Dades Valley to Merzouga",
"description": "Camel trek into the dunes and night at the camp.",
"steps": [
{
"order": 1,
"title": "Camel trek",
"description": "Sunset ride over the Erg Chebbi dunes.",
"duration": "2h"
}
]
},
{
"day_number": 3,
"title": "Merzouga back to Marrakech",
"description": "Sunrise over the dunes then return drive.",
"steps": [
{
"order": 1,
"title": "Sunrise viewpoint",
"description": "Early morning over the dunes before breakfast.",
"duration": "1h"
}
]
}
],
"accommodations": [
{
"name": "Desert Luxury Camp",
"type": "Camp",
"stars": 4
},
{
"name": "Hotel Dades",
"type": "Hotel",
"stars": 3
}
],
"age_brackets": {
"infant_max_age": 2,
"child_max_age": 11
},
"rate_packs": [
{
"id": "4a700002-0000-4000-8000-0000000000f2",
"name": "Comfort",
"description": "Standard comfort package with half board.",
"base_price": {
"amount": "2400.00",
"currency": "MAD"
},
"child_price": {
"amount": "1440.00",
"currency": "MAD"
},
"infant_price": {
"amount": "0.00",
"currency": "MAD"
},
"children_allowed": true,
"infants_allowed": true,
"max_children": null,
"max_infants": 2,
"room_allocation": "PER_ROOM",
"capacity": 16,
"start_times": [],
"room_types": [
{
"name": "Double",
"capacity": 2,
"max_occupancy": 3,
"extra_bed_allowed": true,
"supplement": {
"amount": "0.00",
"currency": "MAD"
},
"child_supplement": {
"amount": "0.00",
"currency": "MAD"
}
},
{
"name": "Single",
"capacity": 1,
"max_occupancy": 1,
"extra_bed_allowed": false,
"supplement": {
"amount": "630.00",
"currency": "MAD"
},
"child_supplement": {
"amount": "630.00",
"currency": "MAD"
}
}
],
"cancellation_tiers": [
{
"days_before": 30,
"hours_before": 720,
"refund_percent": 100
},
{
"days_before": 14,
"hours_before": 336,
"refund_percent": 50
},
{
"days_before": 7,
"hours_before": 168,
"refund_percent": 0
}
]
}
],
"departure_cities": [
"Marrakech"
]
}
Catalog
Detailed 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.
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.
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.
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.
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.
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.
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.
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).
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
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"SafarAPI","description":"Developer documentation for the SafarAPI partner channel — quote, book and settle Moroccan adventures from your app.","colors":{"primary":"#f2460d","light":"#fb923c","dark":"#c2410c"},"logo":{"light":"https://mintcdn.com/safariat/uq0i7jK0LmN_yZ-e/logo/safarapi-light.svg?fit=max\u0026auto=format\u0026n=uq0i7jK0LmN_yZ-e\u0026q=85\u0026s=6e54d448368f1737309eebb08e5e571c","dark":"https://mintcdn.com/safariat/uq0i7jK0LmN_yZ-e/logo/safarapi-dark.svg?fit=max\u0026auto=format\u0026n=uq0i7jK0LmN_yZ-e\u0026q=85\u0026s=007f52ec9befa6071011db06b432b61d"},"favicon":"https://mintcdn.com/safariat/uq0i7jK0LmN_yZ-e/favicon.svg?fit=max\u0026auto=format\u0026n=uq0i7jK0LmN_yZ-e\u0026q=85\u0026s=a5d5d7ecbe37e9205bda58ca868f2853","api":{"playground":{"display":"interactive","proxy":true}},"navbar":{"links":[{"href":"/status","label":"Status"},{"href":"https://console.safarapi.com","label":"Console"}],"primary":{"type":"button","label":"Get sandbox access","href":"https://console.safarapi.com/signup"}},"footer":{"socials":{"website":"https://safarapi.com","linkedin":"https://www.linkedin.com/company/safarapi"}},"search":{"prompt":"Search the SafarAPI docs — quotes, bookings, webhooks, settlements"},"seo":{"metatags":{"og:title":"SafarAPI — Morocco travel API for banks \u0026 fintechs","og:description":"Quote, book and settle curated Moroccan travel from your banking app. Sandbox in minutes, production in 7 days.","og:type":"website"},"indexing":"navigable"},"fonts":{"heading":{"family":"Space Grotesk"},"body":{"family":"Inter"}},"styling":{"eyebrows":"section","codeblocks":{"theme":"github-dark-dimmed"},"latex":false},"errors":{"404":{"redirect":false,"title":"Page not found","description":"This page does not exist. Start from the [welcome guide](/introduction/welcome), the [quickstart](/introduction/quickstart), or the [API reference](/api-reference/openapi)."}},"contextual":{"options":["copy","view","chatgpt","claude"],"display":"header"},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"safariat","hasAudioNarration":false,"actualSubdomain":"safariat","customDomains":["developers.safarapi.com"],"gitSource":{"type":"github","owner":"adnanahouzi","repo":"maroc-voyages-r-v-s","deployBranch":"main","contentDirectory":"docs-portal","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6a9c766b0d95020accd6ba30","collectionId":"ffbff38d-bd54-4930-96e6-24689d9a11de","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6a9c766b0d95020accd6ba30"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6a9c766b0d95020accd6ba30","clientVersion":"0.0.4076","searchFilterCounts":[{"language":"default","tag":"API Reference","count":67},{"language":"default","tag":"Endpoints","count":58},{"language":"default","tag":"Guides","count":22},{"language":"default","tag":"API concepts","count":10},{"language":"default","tag":"Catalog","count":8},{"language":"default","tag":"Webhooks","count":7},{"language":"default","tag":"Bookings","count":6},{"language":"default","tag":"Dashboard","count":5},{"language":"default","tag":"Settlements","count":5},{"language":"default","tag":"Introduction","count":4}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":true},"customCss":[{"filePath":"style.css","content":":root{--safarapi-ink: #1a1a1a;--safarapi-rule: #ececec;--safarapi-accent: #f2460d}.dark{--safarapi-ink: #ededed;--safarapi-rule: #2a2a2a;--safarapi-accent: #fb923c}body{-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}main p,main li{line-height:1.68}main h2{margin-top:2.5rem;letter-spacing:-0.01em}main h3{margin-top:1.75rem}main a:not([class]){color:var(--safarapi-accent);text-decoration:none;border-bottom:1px solid transparent;transition:border-color 120ms ease}main a:not([class]):hover{border-bottom-color:currentColor}pre,code{border:1px solid var(--safarapi-rule);border-radius:6px}pre{box-shadow:none}table{border-collapse:collapse}table th,table td{border-color:var(--safarapi-rule)}a:focus-visible,button:focus-visible{outline:2px solid var(--safarapi-accent);outline-offset:2px}"}],"page":{"pagePath":"api-reference/catalog/detailed-adventure-record","slug":"/api-reference/catalog/detailed-adventure-record","pageMetadata":{"title":"Detailed adventure record","description":"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.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /adventures/{slug}","href":"/api-reference/catalog/detailed-adventure-record","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_components.p, {\n children: [\"Full record for one adventure: description, itinerary, inclusions, accommodations and bookable rate packs. The \", _jsx(_components.code, {\n children: \"slug\"\n }), \" is stable and safe to use as an identifier in partner links.\"]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"codeStyling":{"theme":"github-dark-dimmed"},"config":{},"pageMetadata":{"title":"Detailed adventure record","description":"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.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /adventures/{slug}","href":"/api-reference/catalog/detailed-adventure-record","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":["/_mintlify/custom/safariat/f751755c840beb5a/trust/tools/generate-cobranded-pdf.js"],"openApiReferenceData":{"operation":{"tags":["Catalog"],"operationId":"getAdventure","summary":"Detailed adventure record","description":"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.","parameters":["7bc25ce2-ad72-4b45-bb61-e7898b765786","d0aa1ca8-7951-479a-abde-ba46aeebf03d"],"responses":{"200":"ed0c7b73-4250-4ea1-a233-678c2f741bfa","401":"813e6c36-00d2-44a4-9f97-f205b82dc3e7","404":"36c3fbb5-02c4-4e62-8fe0-e93b406603b4","429":"79f02f26-0457-46c8-b845-990e9560e65e"},"method":"get","type":"path","servers":["bef6bbb6-8b53-47c4-b0bd-53ed06e38170"],"security":["509b5ed1-5a9c-40f6-a981-6928a3ac2aa3"],"path":"/adventures/{slug}","baseUrlOptions":["https://api.safarapi.com/api/partner/v1"],"title":"Detailed adventure record","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"7bc25ce2-ad72-4b45-bb61-e7898b765786":{"in":"header","name":"Accept-Language","required":false,"schema":{"type":"string","enum":["fr","en","ar"],"default":"fr","isRequired":false,"description":"Language of the returned labels (titles, descriptions, categories).","uniqueKey":"","typeLabel":"enum\u003cstring>"},"description":"Language of the returned labels (titles, descriptions, categories)."},"d0aa1ca8-7951-479a-abde-ba46aeebf03d":{"in":"path","name":"slug","required":true,"schema":{"type":"string","pattern":"^[a-z0-9-]+$","maxLength":200,"isRequired":true,"description":"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.","uniqueKey":"","typeLabel":"string"},"example":"marrakech-3-jours-desert-sandbox","description":"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."}},"responses":{"ed0c7b73-4250-4ea1-a233-678c2f741bfa":{"description":"Adventure found","content":{"application/json":{"schema":{"type":"object","required":["description","includes","excludes","rate_packs","id","slug","type","title","duration","cover_image_url","price_from","rating"],"properties":{"id":{"type":"string","format":"uuid","isRequired":true,"uniqueKey":"id","typeLabel":"string\u003cuuid>"},"slug":{"type":"string","example":"marrakech-3-jours-desert-sandbox","isRequired":true,"uniqueKey":"slug","typeLabel":"string"},"type":{"type":"string","enum":["EXPERIENCE","TRIP"],"description":"- `EXPERIENCE`: short adventure (a few hours to 1 day), hourly slots.\n- `TRIP`: multi-day tour with an itinerary.\n","isRequired":true,"uniqueKey":"type","typeLabel":"enum\u003cstring>"},"title":{"type":"string","isRequired":true,"uniqueKey":"title","typeLabel":"string"},"duration":{"type":"object","properties":{"days":{"type":"integer","minimum":0,"uniqueKey":"duration.days","typeLabel":"integer"},"hours":{"type":"integer","minimum":0,"uniqueKey":"duration.hours","typeLabel":"integer"},"minutes":{"type":"integer","minimum":0,"uniqueKey":"duration.minutes","typeLabel":"integer"}},"isRequired":true,"uniqueKey":"duration","typeLabel":"object"},"cover_image_url":{"type":"string","format":"uri","isRequired":true,"uniqueKey":"cover_image_url","typeLabel":"string\u003curi>"},"price_from":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"price_from.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"price_from.currency","typeLabel":"enum\u003cstring>"}},"isRequired":true,"uniqueKey":"price_from","typeLabel":"object"},"rating":{"type":"object","properties":{"average":{"type":"number","format":"float","minimum":0,"maximum":5,"uniqueKey":"rating.average","typeLabel":"number\u003cfloat>"},"count":{"type":"integer","minimum":0,"uniqueKey":"rating.count","typeLabel":"integer"}},"isRequired":true,"uniqueKey":"rating","typeLabel":"object"},"description":{"type":"string","isRequired":true,"uniqueKey":"description","typeLabel":"string"},"includes":{"type":"array","items":{"type":"string","uniqueKey":"includes.items.[INDEX]","typeLabel":"string"},"isRequired":true,"uniqueKey":"includes","typeLabel":"string[]"},"excludes":{"type":"array","items":{"type":"string","uniqueKey":"excludes.items.[INDEX]","typeLabel":"string"},"isRequired":true,"uniqueKey":"excludes","typeLabel":"string[]"},"rate_packs":{"type":"array","items":{"type":"object","required":["id","name","base_price","children_allowed","infants_allowed","max_children","max_infants","room_allocation","cancellation_tiers"],"properties":{"id":{"type":"string","format":"uuid","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].id","typeLabel":"string\u003cuuid>"},"name":{"type":"string","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].name","typeLabel":"string"},"base_price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].base_price.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].base_price.currency","typeLabel":"enum\u003cstring>"}},"description":"Public B2C reference price, per adult traveler (the `b2c_price`, price floor).\nFor the partner revenue split on this price, see `pricing`.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].base_price","typeLabel":"object"},"children_allowed":{"type":"boolean","description":"Whether `POST /quotes` accepts children on this pack. It is `true` only when the operator\nboth allows children and declared a `child_price`, so it predicts exactly what the quote\nwill do: when `false`, sending a child age in `rooms[].children[].age` returns `400`\nwith code `adventure.children.not.accepted`.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].children_allowed","typeLabel":"boolean"},"infants_allowed":{"type":"boolean","description":"Whether `POST /quotes` accepts infants on this pack, on the same basis as\n`children_allowed`: `true` only when the operator both allows infants and declared an\n`infant_price`. When `false`, sending an age at or below `age_brackets.infant_max_age`\nreturns `400` with code `adventure.infants.not.accepted`. Always present, so an\nabsent `infant_price` no longer has to be read as a refusal.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].infants_allowed","typeLabel":"boolean"},"max_children":{"oneOf":[{"type":"integer","minimum":0,"description":"Largest number of children accepted on one booking, counted across every room and not\nper room. `null` means no cap, and is the common case. `0` forbids children outright.\nExceeding it returns `400` with code `adventure.children.max.exceeded`.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].max_children.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":0,"description":"Largest number of children accepted on one booking, counted across every room and not\nper room. `null` means no cap, and is the common case. `0` forbids children outright.\nExceeding it returns `400` with code `adventure.children.max.exceeded`.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].max_children.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].max_children","typeLabel":"integer | null"},"max_infants":{"oneOf":[{"type":"integer","minimum":0,"description":"Largest number of infants accepted on one booking, counted across every room and not\nper room. `null` means no cap. Exceeding it returns `400` with code\n`adventure.infants.max.exceeded`.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].max_infants.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":0,"description":"Largest number of infants accepted on one booking, counted across every room and not\nper room. `null` means no cap. Exceeding it returns `400` with code\n`adventure.infants.max.exceeded`.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].max_infants.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].max_infants","typeLabel":"integer | null"},"room_allocation":{"type":"string","enum":["PER_ROOM","PER_PERSON"],"description":"Occupancy model declared by the operator, and how `/quotes` charges `room_types`:\n- `PER_ROOM`: one supplement per room booked (Morocco standard). `child_supplement`\n does not apply.\n- `PER_PERSON`: every occupant is charged the supplement of the room type they occupy,\n adults at `supplement` and children at `child_supplement` (Umrah, Hajj, charters).\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_allocation","typeLabel":"enum\u003cstring>"},"cancellation_tiers":{"type":"array","description":"Refund grid of this rate pack, ordered from the most permissive tier to the least.\nThe number of tiers is set by the operator and is not capped.\n","items":{"type":"object","description":"One refund tier of a cancellation grid, as published by the operator and frozen on the\nbooking at confirmation. The same shape is returned by the rate pack, by the cancellation\nquote and by the cancellation itself.\n","required":["days_before","hours_before","refund_percent"],"properties":{"days_before":{"type":"integer","minimum":0,"description":"`hours_before` truncated to whole days, kept for display. A tier shorter than 24 h\nreads `0` here: rely on `hours_before` for any computation.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].cancellation_tiers.items.[INDEX].days_before","typeLabel":"integer"},"hours_before":{"type":"integer","minimum":0,"description":"Cancellation up to H hours before departure → this tier applies.","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].cancellation_tiers.items.[INDEX].hours_before","typeLabel":"integer"},"refund_percent":{"type":"integer","minimum":0,"maximum":100,"isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].cancellation_tiers.items.[INDEX].refund_percent","typeLabel":"integer"}},"uniqueKey":"rate_packs.items.[INDEX].cancellation_tiers.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].cancellation_tiers","typeLabel":"object[]"},"description":{"oneOf":[{"type":"string","uniqueKey":"rate_packs.items.[INDEX].description.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"rate_packs.items.[INDEX].description.oneOf.1","typeLabel":"null"}],"uniqueKey":"rate_packs.items.[INDEX].description","typeLabel":"string | null"},"child_price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].child_price.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].child_price.currency","typeLabel":"enum\u003cstring>"}},"description":"Price charged for one child, **instead of** `base_price`, not on top of it. A quote for\n2 adults and 1 child on a pack at 2000 with a `child_price` of 1200 is priced\n`2 x 2000 + 1 x 1200`. A traveller counts as a child when their age falls between\n`age_brackets.infant_max_age + 1` and `age_brackets.child_max_age`.\nAbsent when the operator declared no child rate, in which case `children_allowed`\nis `false` and `POST /quotes` rejects any child.\nDo not confuse this with `room_types[].child_supplement`, which is an *additional*\nroom charge and applies only under `room_allocation: PER_PERSON`.\n","uniqueKey":"rate_packs.items.[INDEX].child_price","typeLabel":"object"},"infant_price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].infant_price.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].infant_price.currency","typeLabel":"enum\u003cstring>"}},"description":"Price charged for one infant, **instead of** `base_price`, on the same replacement basis\nas `child_price`. A traveller counts as an infant up to `age_brackets.infant_max_age`.\nAbsent when the operator declared no infant rate, in which case `infants_allowed`\nis `false` and `POST /quotes` rejects any infant.\n","uniqueKey":"rate_packs.items.[INDEX].infant_price","typeLabel":"object"},"pricing":{"type":"object","description":"Indicative revenue breakdown on `base_price` (`indicative = true`).","required":["b2c_price","customer_price","amount_due_to_safariat","awb_commission_share","sandbox_surcharge","partner_revenue","indicative"],"properties":{"b2c_price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.b2c_price.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.b2c_price.currency","typeLabel":"enum\u003cstring>"}},"description":"Public B2C reference price (price floor guaranteed to the customer).","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.b2c_price","typeLabel":"object"},"customer_price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.customer_price.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.customer_price.currency","typeLabel":"enum\u003cstring>"}},"description":"Total price paid by the customer = `b2c_price + sandbox_surcharge`. Equals `b2c_price` before booking.","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.customer_price","typeLabel":"object"},"amount_due_to_safariat":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.amount_due_to_safariat.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.amount_due_to_safariat.currency","typeLabel":"enum\u003cstring>"}},"description":"Net reversed to Safariat = operator share + 65% of the base commission (the daily wire amount).","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.amount_due_to_safariat","typeLabel":"object"},"awb_commission_share":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.awb_commission_share.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.awb_commission_share.currency","typeLabel":"enum\u003cstring>"}},"description":"AWB's 35% share of the base commission.","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.awb_commission_share","typeLabel":"object"},"sandbox_surcharge":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.sandbox_surcharge.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.sandbox_surcharge.currency","typeLabel":"enum\u003cstring>"}},"description":"AWB's own surcharge (100% AWB), derived as `customer_price − b2c_price`. `0` before booking.","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.sandbox_surcharge","typeLabel":"object"},"partner_revenue":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.partner_revenue.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.partner_revenue.currency","typeLabel":"enum\u003cstring>"}},"description":"Total kept by the partner on this booking = `awb_commission_share + sandbox_surcharge`.\nProvided so reporting never has to add the two components client-side.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.partner_revenue","typeLabel":"object"},"indicative":{"type":"boolean","description":"`true` for catalog/quote \"from\" prices (final amounts confirmed at booking);\n`false` on booking responses.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].pricing.indicative","typeLabel":"boolean"}},"uniqueKey":"rate_packs.items.[INDEX].pricing","typeLabel":"object"},"capacity":{"oneOf":[{"type":"integer","description":"Capacity declared on the rate pack: the largest slot capacity for a fixed-schedule pack,\nthe daily capacity for a flexible one. Absent when the operator declared no cap.\nEvery traveller counts against it, infants included.\n","uniqueKey":"rate_packs.items.[INDEX].capacity.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Capacity declared on the rate pack: the largest slot capacity for a fixed-schedule pack,\nthe daily capacity for a flexible one. Absent when the operator declared no cap.\nEvery traveller counts against it, infants included.\n","uniqueKey":"rate_packs.items.[INDEX].capacity.oneOf.1","typeLabel":"null"}],"uniqueKey":"rate_packs.items.[INDEX].capacity","typeLabel":"integer | null"},"start_times":{"type":"array","description":"Bookable start times (`HH:MM`) for a fixed-schedule pack, ascending. Empty for multi-day trips\nand for flexible packs. When this list is non-empty, `POST /quotes` requires `start_time`\nto be one of these values.\n","items":{"type":"string","example":"09:00","uniqueKey":"rate_packs.items.[INDEX].start_times.items.[INDEX]","typeLabel":"string"},"uniqueKey":"rate_packs.items.[INDEX].start_times","typeLabel":"string[]"},"room_types":{"type":"array","description":"Room types bookable on this pack. When this list is non-empty, every entry of `rooms`\nin `POST /quotes` must carry a `room_type` taken from `name`, and the matching\nsupplement is added to the quote. Empty when the operator declared no room type,\nin which case the quote is priced from the traveller mix alone.\n","items":{"type":"object","required":["name","capacity","max_occupancy","extra_bed_allowed","supplement"],"properties":{"name":{"type":"string","example":"Double","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].name","typeLabel":"string"},"capacity":{"type":"integer","minimum":1,"isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].capacity","typeLabel":"integer"},"max_occupancy":{"type":"integer","minimum":1,"description":"Largest number of travellers this room type takes, extra bed included.\n`POST /quotes` enforces it per room and returns `400` with code\n`adventure.room.occupancy.exceeded` above it. Infants do not count towards\nit, since they take no bed, but they do count towards the departure `capacity`.\n","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].max_occupancy","typeLabel":"integer"},"extra_bed_allowed":{"type":"boolean","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].extra_bed_allowed","typeLabel":"boolean"},"supplement":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].supplement.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].supplement.currency","typeLabel":"enum\u003cstring>"}},"description":"Supplement per room (PER_ROOM) or per adult traveller (PER_PERSON).","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].supplement","typeLabel":"object"},"child_supplement":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].child_supplement.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].child_supplement.currency","typeLabel":"enum\u003cstring>"}},"description":"Room supplement **added** for a child occupying this room type, charged only under\n`room_allocation: PER_PERSON`. It is a room charge, unrelated to `child_price`,\nwhich replaces the traveller's base price. Falls back to `supplement` when the\noperator left it unset.\n\nOnly a traveller classified as a child is charged it. An infant is charged no room\nsupplement at all, and an age above `age_brackets.child_max_age` is charged the\nadult `supplement`, consistently with how the same age is charged on the\n`travelers` line.\n","uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX].child_supplement","typeLabel":"object"}},"uniqueKey":"rate_packs.items.[INDEX].room_types.items.[INDEX]","typeLabel":"object"},"uniqueKey":"rate_packs.items.[INDEX].room_types","typeLabel":"object[]"}},"uniqueKey":"rate_packs.items.[INDEX]","typeLabel":"object"},"isRequired":true,"uniqueKey":"rate_packs","typeLabel":"object[]"},"subtitle":{"oneOf":[{"type":"string","uniqueKey":"subtitle.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"subtitle.oneOf.1","typeLabel":"null"}],"uniqueKey":"subtitle","typeLabel":"string | null"},"cover_image_blurhash":{"oneOf":[{"type":"string","description":"Compact placeholder (BlurHash) for instant rendering before the cover image loads.","uniqueKey":"cover_image_blurhash.oneOf.0","typeLabel":"string"},{"type":"null","description":"Compact placeholder (BlurHash) for instant rendering before the cover image loads.","uniqueKey":"cover_image_blurhash.oneOf.1","typeLabel":"null"}],"uniqueKey":"cover_image_blurhash","typeLabel":"string | null"},"cover_image_variants":{"oneOf":[{"type":"object","description":"Responsive variant URLs of the cover image.","properties":{"small":{"oneOf":[{"type":"string","format":"uri","uniqueKey":"cover_image_variants.oneOf.0.small.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","uniqueKey":"cover_image_variants.oneOf.0.small.oneOf.1","typeLabel":"null"}],"uniqueKey":"cover_image_variants.oneOf.0.small","typeLabel":"string\u003curi> | null"},"medium":{"oneOf":[{"type":"string","format":"uri","uniqueKey":"cover_image_variants.oneOf.0.medium.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","uniqueKey":"cover_image_variants.oneOf.0.medium.oneOf.1","typeLabel":"null"}],"uniqueKey":"cover_image_variants.oneOf.0.medium","typeLabel":"string\u003curi> | null"}},"uniqueKey":"cover_image_variants.oneOf.0","typeLabel":"object"},{"type":"null","description":"Responsive variant URLs of the cover image.","properties":{"small":{"oneOf":[{"type":"string","format":"uri"},{"type":"null","format":"uri"}]},"medium":{"oneOf":[{"type":"string","format":"uri"},{"type":"null","format":"uri"}]}},"uniqueKey":"cover_image_variants.oneOf.1","typeLabel":"null"}],"uniqueKey":"cover_image_variants","typeLabel":"object | null"},"destinations":{"type":"array","items":{"type":"string","uniqueKey":"destinations.items.[INDEX]","typeLabel":"string"},"description":"Main destination labels.","uniqueKey":"destinations","typeLabel":"string[]"},"categories":{"type":"array","items":{"type":"string","uniqueKey":"categories.items.[INDEX]","typeLabel":"string"},"uniqueKey":"categories","typeLabel":"string[]"},"pricing":{"type":"object","description":"Indicative revenue breakdown on `price_from` (`indicative = true`).","required":["b2c_price","customer_price","amount_due_to_safariat","awb_commission_share","sandbox_surcharge","partner_revenue","indicative"],"properties":{"b2c_price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"pricing.b2c_price.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"pricing.b2c_price.currency","typeLabel":"enum\u003cstring>"}},"description":"Public B2C reference price (price floor guaranteed to the customer).","isRequired":true,"uniqueKey":"pricing.b2c_price","typeLabel":"object"},"customer_price":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"pricing.customer_price.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"pricing.customer_price.currency","typeLabel":"enum\u003cstring>"}},"description":"Total price paid by the customer = `b2c_price + sandbox_surcharge`. Equals `b2c_price` before booking.","isRequired":true,"uniqueKey":"pricing.customer_price","typeLabel":"object"},"amount_due_to_safariat":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"pricing.amount_due_to_safariat.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"pricing.amount_due_to_safariat.currency","typeLabel":"enum\u003cstring>"}},"description":"Net reversed to Safariat = operator share + 65% of the base commission (the daily wire amount).","isRequired":true,"uniqueKey":"pricing.amount_due_to_safariat","typeLabel":"object"},"awb_commission_share":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"pricing.awb_commission_share.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"pricing.awb_commission_share.currency","typeLabel":"enum\u003cstring>"}},"description":"AWB's 35% share of the base commission.","isRequired":true,"uniqueKey":"pricing.awb_commission_share","typeLabel":"object"},"sandbox_surcharge":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"pricing.sandbox_surcharge.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"pricing.sandbox_surcharge.currency","typeLabel":"enum\u003cstring>"}},"description":"AWB's own surcharge (100% AWB), derived as `customer_price − b2c_price`. `0` before booking.","isRequired":true,"uniqueKey":"pricing.sandbox_surcharge","typeLabel":"object"},"partner_revenue":{"type":"object","required":["amount","currency"],"properties":{"amount":{"type":"string","pattern":"^-?\\d+\\.\\d{2}$","description":"Amount as a decimal string with 2 decimals to preserve precision.","example":"3200.00","isRequired":true,"uniqueKey":"pricing.partner_revenue.amount","typeLabel":"string"},"currency":{"type":"string","enum":["MAD"],"description":"Currency — MAD only in V1.","example":"MAD","isRequired":true,"uniqueKey":"pricing.partner_revenue.currency","typeLabel":"enum\u003cstring>"}},"description":"Total kept by the partner on this booking = `awb_commission_share + sandbox_surcharge`.\nProvided so reporting never has to add the two components client-side.\n","isRequired":true,"uniqueKey":"pricing.partner_revenue","typeLabel":"object"},"indicative":{"type":"boolean","description":"`true` for catalog/quote \"from\" prices (final amounts confirmed at booking);\n`false` on booking responses.\n","isRequired":true,"uniqueKey":"pricing.indicative","typeLabel":"boolean"}},"uniqueKey":"pricing","typeLabel":"object"},"agency":{"oneOf":[{"type":"object","description":"Owning agency. `name` may be null if the agency record was deleted between indexing and read.","properties":{"id":{"type":"string","format":"uuid","uniqueKey":"agency.oneOf.0.id","typeLabel":"string\u003cuuid>"},"name":{"oneOf":[{"type":"string","uniqueKey":"agency.oneOf.0.name.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"agency.oneOf.0.name.oneOf.1","typeLabel":"null"}],"uniqueKey":"agency.oneOf.0.name","typeLabel":"string | null"}},"uniqueKey":"agency.oneOf.0","typeLabel":"object"},{"type":"null","description":"Owning agency. `name` may be null if the agency record was deleted between indexing and read.","properties":{"id":{"type":"string","format":"uuid"},"name":{"oneOf":[{"type":"string"},{"type":"null"}]}},"uniqueKey":"agency.oneOf.1","typeLabel":"null"}],"uniqueKey":"agency","typeLabel":"object | null"},"availability_hint":{"oneOf":[{"type":"string","enum":["AVAILABLE","FEW_LEFT","SOLD_OUT"],"description":"Computed at search-time from booking ratios. Surfaces UI badges\n(\"plus que 2 places\", \"complet\"). Null if no signal available.\n","uniqueKey":"availability_hint.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","enum":["AVAILABLE","FEW_LEFT","SOLD_OUT"],"description":"Computed at search-time from booking ratios. Surfaces UI badges\n(\"plus que 2 places\", \"complet\"). Null if no signal available.\n","uniqueKey":"availability_hint.oneOf.1","typeLabel":"null"}],"uniqueKey":"availability_hint","typeLabel":"enum\u003cstring> | null"},"distance_km":{"oneOf":[{"type":"number","format":"double","minimum":0,"description":"Haversine distance between the search reference point (`lat`/`lng` query params)\nand the adventure's primary location. Null if the search was not geo-anchored.\n","uniqueKey":"distance_km.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","minimum":0,"description":"Haversine distance between the search reference point (`lat`/`lng` query params)\nand the adventure's primary location. Null if the search was not geo-anchored.\n","uniqueKey":"distance_km.oneOf.1","typeLabel":"null"}],"uniqueKey":"distance_km","typeLabel":"number\u003cdouble> | null"},"highlights":{"type":"array","items":{"type":"string","uniqueKey":"highlights.items.[INDEX]","typeLabel":"string"},"uniqueKey":"highlights","typeLabel":"string[]"},"what_to_bring":{"type":"array","items":{"type":"string","uniqueKey":"what_to_bring.items.[INDEX]","typeLabel":"string"},"uniqueKey":"what_to_bring","typeLabel":"string[]"},"good_to_know":{"type":"array","items":{"type":"string","uniqueKey":"good_to_know.items.[INDEX]","typeLabel":"string"},"uniqueKey":"good_to_know","typeLabel":"string[]"},"gallery":{"type":"array","items":{"type":"string","format":"uri","uniqueKey":"gallery.items.[INDEX]","typeLabel":"string\u003curi>"},"uniqueKey":"gallery","typeLabel":"string\u003curi>[]"},"itinerary":{"type":"array","items":{"type":"object","required":["day_number","title"],"properties":{"day_number":{"type":"integer","minimum":1,"isRequired":true,"uniqueKey":"itinerary.items.[INDEX].day_number","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"itinerary.items.[INDEX].title","typeLabel":"string"},"description":{"oneOf":[{"type":"string","uniqueKey":"itinerary.items.[INDEX].description.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"itinerary.items.[INDEX].description.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary.items.[INDEX].description","typeLabel":"string | null"},"steps":{"type":"array","items":{"type":"object","required":["order","title"],"properties":{"order":{"type":"integer","minimum":1,"isRequired":true,"uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].order","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].title","typeLabel":"string"},"description":{"oneOf":[{"type":"string","uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].description.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].description.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].description","typeLabel":"string | null"},"duration":{"oneOf":[{"type":"string","example":"2h","uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].duration.oneOf.0","typeLabel":"string"},{"type":"null","example":"2h","uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].duration.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX].duration","typeLabel":"string | null"}},"uniqueKey":"itinerary.items.[INDEX].steps.items.[INDEX]","typeLabel":"object"},"uniqueKey":"itinerary.items.[INDEX].steps","typeLabel":"object[]"}},"uniqueKey":"itinerary.items.[INDEX]","typeLabel":"object"},"uniqueKey":"itinerary","typeLabel":"object[]"},"itinerary_periods":{"type":"array","description":"Multi-day periods grouping consecutive itinerary days (e.g. days 1-3 = \"Marrakech to dunes\").\nProvided alongside `itinerary` for richer day-by-day rendering on long trips. Empty for\nEXPERIENCE adventures.\n","items":{"type":"object","required":["day_from","day_to","title"],"properties":{"day_from":{"type":"integer","minimum":1,"isRequired":true,"uniqueKey":"itinerary_periods.items.[INDEX].day_from","typeLabel":"integer"},"day_to":{"type":"integer","minimum":1,"isRequired":true,"uniqueKey":"itinerary_periods.items.[INDEX].day_to","typeLabel":"integer"},"title":{"type":"string","isRequired":true,"uniqueKey":"itinerary_periods.items.[INDEX].title","typeLabel":"string"},"id":{"oneOf":[{"type":"string","uniqueKey":"itinerary_periods.items.[INDEX].id.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"itinerary_periods.items.[INDEX].id.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary_periods.items.[INDEX].id","typeLabel":"string | null"},"description":{"oneOf":[{"type":"string","uniqueKey":"itinerary_periods.items.[INDEX].description.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"itinerary_periods.items.[INDEX].description.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary_periods.items.[INDEX].description","typeLabel":"string | null"},"location":{"oneOf":[{"type":"string","uniqueKey":"itinerary_periods.items.[INDEX].location.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"itinerary_periods.items.[INDEX].location.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary_periods.items.[INDEX].location","typeLabel":"string | null"},"image":{"oneOf":[{"type":"string","format":"uri","uniqueKey":"itinerary_periods.items.[INDEX].image.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","uniqueKey":"itinerary_periods.items.[INDEX].image.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary_periods.items.[INDEX].image","typeLabel":"string\u003curi> | null"},"activities":{"type":"array","items":{"type":"string","uniqueKey":"itinerary_periods.items.[INDEX].activities.items.[INDEX]","typeLabel":"string"},"uniqueKey":"itinerary_periods.items.[INDEX].activities","typeLabel":"string[]"},"meals":{"type":"array","description":"Meal codes (e.g. `BREAKFAST`, `LUNCH`, `DINNER`).","items":{"type":"string","uniqueKey":"itinerary_periods.items.[INDEX].meals.items.[INDEX]","typeLabel":"string"},"uniqueKey":"itinerary_periods.items.[INDEX].meals","typeLabel":"string[]"},"accommodation_id":{"oneOf":[{"type":"string","format":"uuid","uniqueKey":"itinerary_periods.items.[INDEX].accommodation_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","uniqueKey":"itinerary_periods.items.[INDEX].accommodation_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"itinerary_periods.items.[INDEX].accommodation_id","typeLabel":"string\u003cuuid> | null"}},"uniqueKey":"itinerary_periods.items.[INDEX]","typeLabel":"object"},"uniqueKey":"itinerary_periods","typeLabel":"object[]"},"accommodations":{"type":"array","items":{"type":"object","required":["name","type"],"properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"accommodations.items.[INDEX].name","typeLabel":"string"},"type":{"type":"string","example":"Riad","isRequired":true,"uniqueKey":"accommodations.items.[INDEX].type","typeLabel":"string"},"stars":{"oneOf":[{"type":"integer","minimum":0,"maximum":5,"uniqueKey":"accommodations.items.[INDEX].stars.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":0,"maximum":5,"uniqueKey":"accommodations.items.[INDEX].stars.oneOf.1","typeLabel":"null"}],"uniqueKey":"accommodations.items.[INDEX].stars","typeLabel":"integer | null"}},"uniqueKey":"accommodations.items.[INDEX]","typeLabel":"object"},"uniqueKey":"accommodations","typeLabel":"object[]"},"meeting_points":{"oneOf":[{"type":"array","description":"Where travellers meet the guide (EXPERIENCE only). More than one entry means the\noperator offers a choice, made at booking time. Coordinates are frequently absent:\nroughly two thirds of the catalogue declares a name alone, so render the name and\nthe instructions without assuming a map is available.\n","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Stortorget","isRequired":true,"uniqueKey":"meeting_points.oneOf.0.items.[INDEX].name","typeLabel":"string"},"latitude":{"oneOf":[{"type":"number","format":"double","uniqueKey":"meeting_points.oneOf.0.items.[INDEX].latitude.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","uniqueKey":"meeting_points.oneOf.0.items.[INDEX].latitude.oneOf.1","typeLabel":"null"}],"uniqueKey":"meeting_points.oneOf.0.items.[INDEX].latitude","typeLabel":"number\u003cdouble> | null"},"longitude":{"oneOf":[{"type":"number","format":"double","uniqueKey":"meeting_points.oneOf.0.items.[INDEX].longitude.oneOf.0","typeLabel":"number\u003cdouble>"},{"type":"null","format":"double","uniqueKey":"meeting_points.oneOf.0.items.[INDEX].longitude.oneOf.1","typeLabel":"null"}],"uniqueKey":"meeting_points.oneOf.0.items.[INDEX].longitude","typeLabel":"number\u003cdouble> | null"},"instructions":{"oneOf":[{"type":"string","description":"Free text written by the operator telling travellers how to find the guide\non site: landmark, floor, outfit, what to look for. Absent when the operator\nwrote none. Never translated, it is served as typed.\n","example":"In front of the Nobel Museum, look for the guide with the red flag.","uniqueKey":"meeting_points.oneOf.0.items.[INDEX].instructions.oneOf.0","typeLabel":"string"},{"type":"null","description":"Free text written by the operator telling travellers how to find the guide\non site: landmark, floor, outfit, what to look for. Absent when the operator\nwrote none. Never translated, it is served as typed.\n","example":"In front of the Nobel Museum, look for the guide with the red flag.","uniqueKey":"meeting_points.oneOf.0.items.[INDEX].instructions.oneOf.1","typeLabel":"null"}],"uniqueKey":"meeting_points.oneOf.0.items.[INDEX].instructions","typeLabel":"string | null"}},"uniqueKey":"meeting_points.oneOf.0.items.[INDEX]","typeLabel":"object"},"uniqueKey":"meeting_points.oneOf.0","typeLabel":"object[]"},{"type":"null","description":"Where travellers meet the guide (EXPERIENCE only). More than one entry means the\noperator offers a choice, made at booking time. Coordinates are frequently absent:\nroughly two thirds of the catalogue declares a name alone, so render the name and\nthe instructions without assuming a map is available.\n","items":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Stortorget"},"latitude":{"oneOf":[{"type":"number","format":"double"},{"type":"null","format":"double"}]},"longitude":{"oneOf":[{"type":"number","format":"double"},{"type":"null","format":"double"}]},"instructions":{"oneOf":[{"type":"string","description":"Free text written by the operator telling travellers how to find the guide\non site: landmark, floor, outfit, what to look for. Absent when the operator\nwrote none. Never translated, it is served as typed.\n","example":"In front of the Nobel Museum, look for the guide with the red flag."},{"type":"null","description":"Free text written by the operator telling travellers how to find the guide\non site: landmark, floor, outfit, what to look for. Absent when the operator\nwrote none. Never translated, it is served as typed.\n","example":"In front of the Nobel Museum, look for the guide with the red flag."}]}}},"uniqueKey":"meeting_points.oneOf.1","typeLabel":"null"}],"uniqueKey":"meeting_points","typeLabel":"object[] | null"},"faq":{"type":"array","description":"Frequently asked questions, ordered by display index.","items":{"type":"object","required":["question","answer"],"properties":{"question":{"type":"string","isRequired":true,"uniqueKey":"faq.items.[INDEX].question","typeLabel":"string"},"answer":{"type":"string","isRequired":true,"uniqueKey":"faq.items.[INDEX].answer","typeLabel":"string"}},"uniqueKey":"faq.items.[INDEX]","typeLabel":"object"},"uniqueKey":"faq","typeLabel":"object[]"},"host":{"oneOf":[{"type":"object","description":"Host profile (EXPERIENCE adventures only).","required":["name"],"properties":{"name":{"type":"string","isRequired":true,"uniqueKey":"host.oneOf.0.name","typeLabel":"string"},"image":{"oneOf":[{"type":"string","format":"uri","uniqueKey":"host.oneOf.0.image.oneOf.0","typeLabel":"string\u003curi>"},{"type":"null","format":"uri","uniqueKey":"host.oneOf.0.image.oneOf.1","typeLabel":"null"}],"uniqueKey":"host.oneOf.0.image","typeLabel":"string\u003curi> | null"},"experience":{"oneOf":[{"type":"string","uniqueKey":"host.oneOf.0.experience.oneOf.0","typeLabel":"string"},{"type":"null","uniqueKey":"host.oneOf.0.experience.oneOf.1","typeLabel":"null"}],"uniqueKey":"host.oneOf.0.experience","typeLabel":"string | null"},"languages":{"type":"array","items":{"type":"string","uniqueKey":"host.oneOf.0.languages.items.[INDEX]","typeLabel":"string"},"uniqueKey":"host.oneOf.0.languages","typeLabel":"string[]"}},"uniqueKey":"host.oneOf.0","typeLabel":"object"},{"type":"null","description":"Host profile (EXPERIENCE adventures only).","required":["name"],"properties":{"name":{"type":"string"},"image":{"oneOf":[{"type":"string","format":"uri"},{"type":"null","format":"uri"}]},"experience":{"oneOf":[{"type":"string"},{"type":"null"}]},"languages":{"type":"array","items":{"type":"string"}}},"uniqueKey":"host.oneOf.1","typeLabel":"null"}],"uniqueKey":"host","typeLabel":"object | null"},"departure_cities":{"type":"array","items":{"type":"string","uniqueKey":"departure_cities.items.[INDEX]","typeLabel":"string"},"uniqueKey":"departure_cities","typeLabel":"string[]"},"departure_dates":{"type":"array","description":"Future bookable dates, ascending, for every adventure type: the union of the calendars\nthat apply to the rate packs (a pack calendar overrides the adventure one), with past\ndates and dates past their booking cut-off already removed. Empty when nothing is\nbookable. For a short-duration adventure these are the bookable days.\n","items":{"type":"string","format":"date","uniqueKey":"departure_dates.items.[INDEX]","typeLabel":"string\u003cdate>"},"uniqueKey":"departure_dates","typeLabel":"string\u003cdate>[]"},"next_departure_date":{"oneOf":[{"type":"string","format":"date","description":"Soonest bookable future departure (respects per-pack booking cutoff).","uniqueKey":"next_departure_date.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"Soonest bookable future departure (respects per-pack booking cutoff).","uniqueKey":"next_departure_date.oneOf.1","typeLabel":"null"}],"uniqueKey":"next_departure_date","typeLabel":"string\u003cdate> | null"},"translation_source":{"oneOf":[{"type":"string","enum":["auto","manual"],"description":"Set when the returned content has been translated from the source language for the\nrequested `Accept-Language`. `null` if the requested locale equals the adventure's\nsource language (content delivered as authored).\n","uniqueKey":"translation_source.oneOf.0","typeLabel":"enum\u003cstring>"},{"type":"null","enum":["auto","manual"],"description":"Set when the returned content has been translated from the source language for the\nrequested `Accept-Language`. `null` if the requested locale equals the adventure's\nsource language (content delivered as authored).\n","uniqueKey":"translation_source.oneOf.1","typeLabel":"null"}],"uniqueKey":"translation_source","typeLabel":"enum\u003cstring> | null"},"age_brackets":{"type":"object","description":"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.","required":["infant_max_age","child_max_age"],"properties":{"infant_max_age":{"type":"integer","minimum":0,"isRequired":true,"uniqueKey":"age_brackets.infant_max_age","typeLabel":"integer"},"child_max_age":{"type":"integer","minimum":1,"isRequired":true,"uniqueKey":"age_brackets.child_max_age","typeLabel":"integer"}},"uniqueKey":"age_brackets","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"id":"ad000002-0000-4000-8000-0000000000d2","slug":"marrakech-3-jours-desert-sandbox","type":"TRIP","title":"[DEMO] 3-day Sahara desert circuit from Marrakech","subtitle":null,"duration":{"days":3,"hours":0,"minutes":0},"cover_image_url":"https://placehold.co/600x400?text=DEMO","destinations":["Marrakech"],"categories":["desert"],"price_from":{"amount":"2400.00","currency":"MAD"},"rating":{"average":4.7,"count":23},"agency":{"id":"1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f","name":"Sahara Demo Trekking"},"description":"A 3-day circuit from Marrakech to the Sahara dunes, with overnight stays in the desert.","highlights":["Camel trek at sunset over the Erg Chebbi dunes","Night under the stars in a desert camp"],"includes":["Air-conditioned 4x4 transport","2 nights accommodation","Half board"],"excludes":["Personal expenses","Travel insurance"],"what_to_bring":["Warm layer for the desert night","Sunscreen"],"good_to_know":["Departure at 07:00 from central Marrakech"],"gallery":["https://placehold.co/600x400?text=DEMO"],"itinerary":[{"day_number":1,"title":"Marrakech to Dades Valley","description":"Drive over the Tizi n'Tichka pass with photo stops.","steps":[{"order":1,"title":"Departure from Marrakech","description":"Pickup at the central meeting point.","duration":"30 min"}]},{"day_number":2,"title":"Dades Valley to Merzouga","description":"Camel trek into the dunes and night at the camp.","steps":[{"order":1,"title":"Camel trek","description":"Sunset ride over the Erg Chebbi dunes.","duration":"2h"}]},{"day_number":3,"title":"Merzouga back to Marrakech","description":"Sunrise over the dunes then return drive.","steps":[{"order":1,"title":"Sunrise viewpoint","description":"Early morning over the dunes before breakfast.","duration":"1h"}]}],"accommodations":[{"name":"Desert Luxury Camp","type":"Camp","stars":4},{"name":"Hotel Dades","type":"Hotel","stars":3}],"age_brackets":{"infant_max_age":2,"child_max_age":11},"rate_packs":[{"id":"4a700002-0000-4000-8000-0000000000f2","name":"Comfort","description":"Standard comfort package with half board.","base_price":{"amount":"2400.00","currency":"MAD"},"child_price":{"amount":"1440.00","currency":"MAD"},"infant_price":{"amount":"0.00","currency":"MAD"},"children_allowed":true,"infants_allowed":true,"max_children":null,"max_infants":2,"room_allocation":"PER_ROOM","capacity":16,"start_times":[],"room_types":[{"name":"Double","capacity":2,"max_occupancy":3,"extra_bed_allowed":true,"supplement":{"amount":"0.00","currency":"MAD"},"child_supplement":{"amount":"0.00","currency":"MAD"}},{"name":"Single","capacity":1,"max_occupancy":1,"extra_bed_allowed":false,"supplement":{"amount":"630.00","currency":"MAD"},"child_supplement":{"amount":"630.00","currency":"MAD"}}],"cancellation_tiers":[{"days_before":30,"hours_before":720,"refund_percent":100},{"days_before":14,"hours_before":336,"refund_percent":50},{"days_before":7,"hours_before":168,"refund_percent":0}]}],"departure_cities":["Marrakech"]},"examples":{"Example":{"title":"Example","value":{"id":"ad000002-0000-4000-8000-0000000000d2","slug":"marrakech-3-jours-desert-sandbox","type":"TRIP","title":"[DEMO] 3-day Sahara desert circuit from Marrakech","subtitle":null,"duration":{"days":3,"hours":0,"minutes":0},"cover_image_url":"https://placehold.co/600x400?text=DEMO","destinations":["Marrakech"],"categories":["desert"],"price_from":{"amount":"2400.00","currency":"MAD"},"rating":{"average":4.7,"count":23},"agency":{"id":"1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f","name":"Sahara Demo Trekking"},"description":"A 3-day circuit from Marrakech to the Sahara dunes, with overnight stays in the desert.","highlights":["Camel trek at sunset over the Erg Chebbi dunes","Night under the stars in a desert camp"],"includes":["Air-conditioned 4x4 transport","2 nights accommodation","Half board"],"excludes":["Personal expenses","Travel insurance"],"what_to_bring":["Warm layer for the desert night","Sunscreen"],"good_to_know":["Departure at 07:00 from central Marrakech"],"gallery":["https://placehold.co/600x400?text=DEMO"],"itinerary":[{"day_number":1,"title":"Marrakech to Dades Valley","description":"Drive over the Tizi n'Tichka pass with photo stops.","steps":[{"order":1,"title":"Departure from Marrakech","description":"Pickup at the central meeting point.","duration":"30 min"}]},{"day_number":2,"title":"Dades Valley to Merzouga","description":"Camel trek into the dunes and night at the camp.","steps":[{"order":1,"title":"Camel trek","description":"Sunset ride over the Erg Chebbi dunes.","duration":"2h"}]},{"day_number":3,"title":"Merzouga back to Marrakech","description":"Sunrise over the dunes then return drive.","steps":[{"order":1,"title":"Sunrise viewpoint","description":"Early morning over the dunes before breakfast.","duration":"1h"}]}],"accommodations":[{"name":"Desert Luxury Camp","type":"Camp","stars":4},{"name":"Hotel Dades","type":"Hotel","stars":3}],"age_brackets":{"infant_max_age":2,"child_max_age":11},"rate_packs":[{"id":"4a700002-0000-4000-8000-0000000000f2","name":"Comfort","description":"Standard comfort package with half board.","base_price":{"amount":"2400.00","currency":"MAD"},"child_price":{"amount":"1440.00","currency":"MAD"},"infant_price":{"amount":"0.00","currency":"MAD"},"children_allowed":true,"infants_allowed":true,"max_children":null,"max_infants":2,"room_allocation":"PER_ROOM","capacity":16,"start_times":[],"room_types":[{"name":"Double","capacity":2,"max_occupancy":3,"extra_bed_allowed":true,"supplement":{"amount":"0.00","currency":"MAD"},"child_supplement":{"amount":"0.00","currency":"MAD"}},{"name":"Single","capacity":1,"max_occupancy":1,"extra_bed_allowed":false,"supplement":{"amount":"630.00","currency":"MAD"},"child_supplement":{"amount":"630.00","currency":"MAD"}}],"cancellation_tiers":[{"days_before":30,"hours_before":720,"refund_percent":100},{"days_before":14,"hours_before":336,"refund_percent":50},{"days_before":7,"hours_before":168,"refund_percent":0}]}],"departure_cities":["Marrakech"]}}},"exampleType":"examples"}},"exampleType":"examples"},"813e6c36-00d2-44a4-9f97-f205b82dc3e7":{"description":"API key missing, invalid, expired, or incorrect HMAC signature.","content":{"application/json":{"schema":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","description":"Stable, documented i18n code. Form `domain.subdomain.detail`\n(e.g. `payment.amount.mismatch`, `auth.api_key.invalid`).\n","example":"validation.required.field","isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"English message (for bank logs). API errors are never localized on the Safariat side.","example":"Field 'rate_pack_id' is required.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","description":"Unique request ID on the Safariat side.","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","description":"Optional structured details (offending field, expected value, etc.).","additionalProperties":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"missing":{"title":"missing","value":{"code":"auth.api_key.missing","message":"Authorization header is required.","request_id":"01HXY2ZRPM3R8K9PSBTRQYNFHC"}},"invalid":{"title":"invalid","value":{"code":"auth.api_key.invalid","message":"The provided API key is invalid or has been revoked.","request_id":"01HXY2ZRPM3R8K9PSBTRQYNFHC"}},"signatureInvalid":{"title":"signatureInvalid","value":{"code":"auth.signature.invalid","message":"HMAC signature does not match.","request_id":"01HXY2ZRPM3R8K9PSBTRQYNFHC"}},"timestampSkew":{"title":"timestampSkew","value":{"code":"auth.timestamp.skew","message":"Timestamp is more than 5 minutes off server time.","request_id":"01HXY2ZRPM3R8K9PSBTRQYNFHC"}}},"exampleType":"examples"}},"exampleType":"examples"},"36c3fbb5-02c4-4e62-8fe0-e93b406603b4":{"description":"Resource does not exist or is inaccessible for this partner.","content":{"application/json":{"schema":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","description":"Stable, documented i18n code. Form `domain.subdomain.detail`\n(e.g. `payment.amount.mismatch`, `auth.api_key.invalid`).\n","example":"validation.required.field","isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"English message (for bank logs). API errors are never localized on the Safariat side.","example":"Field 'rate_pack_id' is required.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","description":"Unique request ID on the Safariat side.","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","description":"Optional structured details (offending field, expected value, etc.).","additionalProperties":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"code":"validation.required.field","message":"Field 'rate_pack_id' is required.","request_id":"\u003cstring>","details":{}}}},"exampleType":"generated"}},"exampleType":"generated"},"79f02f26-0457-46c8-b845-990e9560e65e":{"description":"Rate limit exceeded for the current key.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before the next attempt (RFC 7231)."},"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"Request limit per minute for the current key."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests remaining in the current window."},"X-RateLimit-Reset":{"schema":{"type":"integer","format":"int64"},"description":"Unix timestamp (s) at which the window resets."}},"content":{"application/json":{"schema":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","description":"Stable, documented i18n code. Form `domain.subdomain.detail`\n(e.g. `payment.amount.mismatch`, `auth.api_key.invalid`).\n","example":"validation.required.field","isRequired":true,"uniqueKey":"code","typeLabel":"string"},"message":{"type":"string","description":"English message (for bank logs). API errors are never localized on the Safariat side.","example":"Field 'rate_pack_id' is required.","isRequired":true,"uniqueKey":"message","typeLabel":"string"},"request_id":{"type":"string","description":"Unique request ID on the Safariat side.","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"},"details":{"type":"object","description":"Optional structured details (offending field, expected value, etc.).","additionalProperties":true,"uniqueKey":"details","typeLabel":"object"}},"uniqueKey":"","typeLabel":"object"},"example":{"code":"rate_limit.exceeded","message":"Rate limit exceeded for this API key.","request_id":"01HXY2ZRPM3R8K9PSBTRQYNFHC"},"examples":{"Example":{"title":"Example","value":{"code":"rate_limit.exceeded","message":"Rate limit exceeded for this API key.","request_id":"01HXY2ZRPM3R8K9PSBTRQYNFHC"}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{"509b5ed1-5a9c-40f6-a981-6928a3ac2aa3":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"sk_live_\u003cprefix>_\u003csecret> or sk_test_\u003cprefix>_\u003csecret>","x-default":"sk_test_DEMO0000_replace_with_your_sandbox_key","description":"API key authentication. Issued by the Safariat admin or via the partner portal.\nThe secret is shown only once at generation.\n\nProduction `sk_live_*` keys must additionally sign every write request\n(`POST`/`PUT`/`DELETE`) with the `X-Timestamp` and `X-Signature` headers.\nSandbox `sk_test_*` keys are exempt from request signing: `X-Signature` and\n`X-Timestamp` are not required for writes in the sandbox (so the developer-portal\n\"Try it\" playground works end to end). The `Idempotency-Key` header remains\nrequired on writes in both environments.\n","scopes":[]}}},"servers":{"bef6bbb6-8b53-47c4-b0bd-53ed06e38170":{"url":"https://api.safarapi.com/api/partner/v1","description":"Production and sandbox share this host. The environment is selected by the API key prefix: sk_live_ targets production, sk_test_ targets the sandbox."}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"sk_live_\u003cprefix>_\u003csecret> or sk_test_\u003cprefix>_\u003csecret>","x-default":"sk_test_DEMO0000_replace_with_your_sandbox_key","description":"API key authentication. Issued by the Safariat admin or via the partner portal.\nThe secret is shown only once at generation.\n\nProduction `sk_live_*` keys must additionally sign every write request\n(`POST`/`PUT`/`DELETE`) with the `X-Timestamp` and `X-Signature` headers.\nSandbox `sk_test_*` keys are exempt from request signing: `X-Signature` and\n`X-Timestamp` are not required for writes in the sandbox (so the developer-portal\n\"Try it\" playground works end to end). The `Idempotency-Key` header remains\nrequired on writes in both environments.\n","scopes":[]},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"API key authentication. Issued by the Safariat admin or via the partner portal.\nThe secret is shown only once at generation.\n\nProduction `sk_live_*` keys must additionally sign every write request\n(`POST`/`PUT`/`DELETE`) with the `X-Timestamp` and `X-Signature` headers.\nSandbox `sk_test_*` keys are exempt from request signing: `X-Signature` and\n`X-Timestamp` are not required for writes in the sandbox (so the developer-portal\n\"Try it\" playground works end to end). The `Idempotency-Key` header remains\nrequired on writes in both environments.\n","format":"bearer","default":"sk_test_DEMO0000_replace_with_your_sandbox_key","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"apiKey","name":"Authorization"}],"title":"apiKey"}]},"originalFileLocation":"api-reference/openapi.yaml"},"subdomain":"safariat","siteName":"SafarAPI","title":"SafarAPI — Morocco travel API for banks \u0026 fintechs","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-05T20:07:20.888Z","originalFileLocation":"api-reference/catalog/detailed-adventure-record.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"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.\">\u003cmeta data-mint-head name=\"application-name\" content=\"SafarAPI\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"SafarAPI — Morocco travel API for banks \u0026amp; fintechs\">\u003cmeta data-mint-head property=\"og:description\" content=\"Quote, book and settle curated Moroccan travel from your banking app. Sandbox in minutes, production in 7 days.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"SafarAPI\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://safariat.mintlify.site/_mintlify/api/og/v2?division=Catalog\u0026amp;title=Detailed+adventure+record\u0026amp;description=Full+record+for+one+adventure%3A+description%2C+itinerary%2C+inclusions%2C+accommodations+and+bookable+rate+packs.+The+%60slug%60+is+stable+and+safe+to+use+as+an+identifier\u0026amp;theme=3b8c95b43b12f994ae542965\u0026amp;signature=87f9cbe4cb2c03fa00104e4471f02521be3c3eacfadc2d323ed673851057dfa5\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"SafarAPI — Morocco travel API for banks \u0026amp; fintechs\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Quote, book and settle curated Moroccan travel from your banking app. Sandbox in minutes, production in 7 days.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://safariat.mintlify.site/_mintlify/api/og/v2?division=Catalog\u0026amp;title=Detailed+adventure+record\u0026amp;description=Full+record+for+one+adventure%3A+description%2C+itinerary%2C+inclusions%2C+accommodations+and+bookable+rate+packs.+The+%60slug%60+is+stable+and+safe+to+use+as+an+identifier\u0026amp;theme=3b8c95b43b12f994ae542965\u0026amp;signature=87f9cbe4cb2c03fa00104e4471f02521be3c3eacfadc2d323ed673851057dfa5\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/safariat/edKFf_9gmlxKUwaY/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"SafarAPI\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#f2460d\">\u003clink data-mint-head rel=\"canonical\" href=\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/catalog/detailed-adventure-record.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://developers.safarapi.com/#organization\",\"name\":\"SafarAPI\",\"url\":\"https://developers.safarapi.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/safariat/uq0i7jK0LmN_yZ-e/logo/safarapi-light.svg?fit=max\u0026auto=format\u0026n=uq0i7jK0LmN_yZ-e\u0026q=85\u0026s=6e54d448368f1737309eebb08e5e571c\"}},{\"@type\":\"WebSite\",\"@id\":\"https://developers.safarapi.com#website\",\"name\":\"SafarAPI\",\"url\":\"https://developers.safarapi.com\",\"publisher\":{\"@id\":\"https://developers.safarapi.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record#webpage\",\"url\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record\",\"name\":\"Detailed adventure record\",\"description\":\"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.\",\"dateModified\":\"2026-09-05T20:07:20.888Z\",\"isPartOf\":{\"@id\":\"https://developers.safarapi.com#website\"},\"breadcrumb\":{\"@id\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Endpoints\",\"item\":\"https://developers.safarapi.com/api-reference/meta/service-status\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Catalog\",\"item\":\"https://developers.safarapi.com/api-reference/catalog/list-adventure-categories\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Detailed adventure record\",\"item\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record#apireference\",\"headline\":\"Detailed adventure record\",\"name\":\"Detailed adventure record\",\"description\":\"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.\",\"url\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record\",\"mainEntityOfPage\":{\"@id\":\"https://developers.safarapi.com/api-reference/catalog/detailed-adventure-record#webpage\"},\"dateModified\":\"2026-09-05T20:07:20.888Z\",\"publisher\":{\"@id\":\"https://developers.safarapi.com/#organization\"},\"isPartOf\":{\"@id\":\"https://developers.safarapi.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"SafarAPI\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"SafarAPI","nav":{"global":null,"tabs":[{"tab":"Guides","pages":[{"title":"Guides","href":"/introduction/welcome"}]},{"tab":"API Reference","groups":[{"group":"Using the API","pages":[{"title":"Overview","href":"/api-reference/openapi"},{"title":"SDKs \u0026 tooling","href":"/api-reference/tooling"}]},{"group":"Endpoints","pages":[{"group":"Meta","pages":[{"title":"Service status","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /health","href":"/api-reference/meta/service-status"},{"title":"Read partner configuration","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /me/config","href":"/api-reference/meta/read-partner-configuration"},{"title":"Update the surcharge rate","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /me/config","href":"/api-reference/meta/update-the-surcharge-rate"},{"title":"Current key information","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /me","href":"/api-reference/meta/current-key-information"}]},{"group":"Catalog","pages":[{"title":"List adventure categories","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /categories","href":"/api-reference/catalog/list-adventure-categories"},{"title":"List destinations","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /destinations","href":"/api-reference/catalog/list-destinations"},{"title":"Autocomplete free-text places","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /places/autocomplete","href":"/api-reference/catalog/autocomplete-free-text-places"},{"title":"Resolve a place prediction to coordinates","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /places/details","href":"/api-reference/catalog/resolve-a-place-prediction-to-coordinates"},{"title":"Paginated adventure search","description":"Search the Safariat catalog. Returned prices are the **net prices** for the partner\n(Safariat public price − Safariat margin ± negotiated partner margin). The bank then\napplies its own commission on its front end to compute the customer price.\n\nPagination is cursor-based: pass the `cursor` received in `meta.next_cursor` to fetch\nthe next page. No `next_cursor` → end of the result set.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /adventures","href":"/api-reference/catalog/paginated-adventure-search"},{"title":"Detailed adventure record","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /adventures/{slug}","href":"/api-reference/catalog/detailed-adventure-record"},{"title":"Adventure availability over a period","description":"Returns the available slots with remaining capacity. Useful for rendering an\ninteractive calendar on the bank front end. Limited to 90 days per request.\n","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /adventures/{slug}/availability","href":"/api-reference/catalog/adventure-availability-over-a-period"},{"title":"Detailed agency record","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /agencies/{id}","href":"/api-reference/catalog/detailed-agency-record"}]},{"group":"Files","pages":[{"title":"Issue a presigned PUT URL to upload a review photo to R2","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /files/presigned-upload","href":"/api-reference/files/issue-a-presigned-put-url-to-upload-a-review-photo-to-r2"}]},{"group":"Reviews","pages":[{"title":"Paginated traveler reviews","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /reviews","href":"/api-reference/reviews/paginated-traveler-reviews"},{"title":"Post a traveler review on behalf of a completed booking","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /reviews","href":"/api-reference/reviews/post-a-traveler-review-on-behalf-of-a-completed-booking"},{"title":"Edit a previously posted review","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml put /reviews/{id}","href":"/api-reference/reviews/edit-a-previously-posted-review"}]},{"group":"Quotes","pages":[{"title":"List quotes","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /quotes","href":"/api-reference/quotes/list-quotes"},{"title":"Create a price-locked quote","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /quotes","href":"/api-reference/quotes/create-a-price-locked-quote"},{"title":"Retrieve a quote by id","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /quotes/{quote_id}","href":"/api-reference/quotes/retrieve-a-quote-by-id"}]},{"group":"Bookings","pages":[{"title":"Paginated list of the partner's bookings","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /bookings","href":"/api-reference/bookings/paginated-list-of-the-partners-bookings"},{"title":"Create a booking","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /bookings","href":"/api-reference/bookings/create-a-booking"},{"title":"Retrieve a booking","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /bookings/{booking_number}","href":"/api-reference/bookings/retrieve-a-booking"},{"title":"Cancel a booking","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /bookings/{booking_number}/cancel","href":"/api-reference/bookings/cancel-a-booking"},{"title":"Preview the cancellation refund","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /bookings/{booking_number}/cancellation-quote","href":"/api-reference/bookings/preview-the-cancellation-refund"},{"title":"Retrieve the PDF voucher","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /bookings/{booking_number}/voucher.pdf","href":"/api-reference/bookings/retrieve-the-pdf-voucher"}]},{"group":"Webhooks","pages":[{"title":"List webhook delivery attempts","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /webhooks/deliveries","href":"/api-reference/webhooks/list-webhook-delivery-attempts"},{"title":"Replay a webhook delivery","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /webhooks/deliveries/{id}/replay","href":"/api-reference/webhooks/replay-a-webhook-delivery"},{"title":"List configured webhook endpoints","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /webhooks","href":"/api-reference/webhooks/list-configured-webhook-endpoints"},{"title":"Register a webhook endpoint","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /webhooks","href":"/api-reference/webhooks/register-a-webhook-endpoint"},{"title":"Retrieve a webhook endpoint","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /webhooks/{id}","href":"/api-reference/webhooks/retrieve-a-webhook-endpoint"},{"title":"Delete a webhook endpoint","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /webhooks/{id}","href":"/api-reference/webhooks/delete-a-webhook-endpoint"},{"title":"Emit a test event","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /webhooks/{id}/test","href":"/api-reference/webhooks/emit-a-test-event"}]},{"group":"Sandbox","pages":[{"title":"Reset the sandbox dataset","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /sandbox/reset","href":"/api-reference/sandbox/reset-the-sandbox-dataset"}]},{"group":"Settlements","pages":[{"title":"Paginated list of monthly invoices","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /settlements","href":"/api-reference/settlements/paginated-list-of-monthly-invoices"},{"title":"Settlement detail (with lines)","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /settlements/{id}","href":"/api-reference/settlements/settlement-detail-with-lines"},{"title":"Invoice PDF (Safariat → partner)","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /settlements/{id}/invoice.pdf","href":"/api-reference/settlements/invoice-pdf-safariat-→-partner"},{"title":"Statement of Account CSV (Safariat → partner)","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /settlements/{id}/statement.csv","href":"/api-reference/settlements/statement-of-account-csv-safariat-→-partner"},{"title":"Daily transactions ledger CSV","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /settlements/daily","href":"/api-reference/settlements/daily-transactions-ledger-csv"}]},{"group":"Team","pages":[{"title":"List team members","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /team/members","href":"/api-reference/team/list-team-members"},{"title":"Invite a member","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /team/members","href":"/api-reference/team/invite-a-member"},{"title":"Change a member's role","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml patch /team/members/{user_id}/role","href":"/api-reference/team/change-a-members-role"},{"title":"Remove a member","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /team/members/{user_id}","href":"/api-reference/team/remove-a-member"}]},{"group":"API keys","pages":[{"title":"List API keys for the current partner","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /api-keys","href":"/api-reference/api-keys/list-api-keys-for-the-current-partner"},{"title":"Issue a new API key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml post /api-keys","href":"/api-reference/api-keys/issue-a-new-api-key"},{"title":"Revoke an API key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml delete /api-keys/{key_id}","href":"/api-reference/api-keys/revoke-an-api-key"}]},{"group":"Audit","pages":[{"title":"List HTTP audit trail for this partner","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /audit-logs","href":"/api-reference/audit/list-http-audit-trail-for-this-partner"}]},{"group":"Dashboard","pages":[{"title":"KPI overview for the Console home","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /dashboard","href":"/api-reference/dashboard/kpi-overview-for-the-console-home"},{"title":"Commercial performance over a period","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /metrics/commercial","href":"/api-reference/dashboard/commercial-performance-over-a-period"},{"title":"How many quotes turn into bookings","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /metrics/quote-funnel","href":"/api-reference/dashboard/how-many-quotes-turn-into-bookings"},{"title":"Travelers leaving soon","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /metrics/departures","href":"/api-reference/dashboard/travelers-leaving-soon"},{"title":"Same commercial figures, as a CSV file","deprecated":null,"version":null,"openapi":"/api-reference/openapi.yaml get /metrics/commercial.csv","href":"/api-reference/dashboard/same-commercial-figures-as-a-csv-file"}]},{"group":"API Reference","pages":[{"title":"Booking confirmed echo","version":null,"deprecated":null,"openapi":"/api-reference/openapi.yaml webhook bookingConfirmed","href":"/api-reference/booking-confirmed-echo"},{"title":"Booking cancelled","version":null,"deprecated":null,"openapi":"/api-reference/openapi.yaml webhook bookingCancelled","href":"/api-reference/booking-cancelled"},{"title":"Booking completed trip taken","version":null,"deprecated":null,"openapi":"/api-reference/openapi.yaml webhook bookingCompleted","href":"/api-reference/booking-completed-trip-taken"},{"title":"Monthly invoice available","version":null,"deprecated":null,"openapi":"/api-reference/openapi.yaml webhook settlementIssued","href":"/api-reference/monthly-invoice-available"},{"title":"Settlement marked paid","version":null,"deprecated":null,"openapi":"/api-reference/openapi.yaml webhook settlementPaid","href":"/api-reference/settlement-marked-paid"},{"title":"Adventure rate pack became unavailable","version":null,"deprecated":null,"openapi":"/api-reference/openapi.yaml webhook adventureUnavailable","href":"/api-reference/adventure-rate-pack-became-unavailable"},{"title":"Review hidden restored or deleted by a safariat admin","version":null,"deprecated":null,"openapi":"/api-reference/openapi.yaml webhook reviewModerated","href":"/api-reference/review-hidden-restored-or-deleted-by-a-safariat-admin"}]}]}]}]},"basePath":"","title":"SafarAPI — Morocco travel API for banks \u0026 fintechs","buildId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","deploymentId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-i2a3QZ8E.js","utils-ChLwp8m0.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-DRktVTDc.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-CA2pEs4T.js","snippetPresets-ClQ6XrKD.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-Ct_Lv36y.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-Cn2PYw9e.js","shallow-rkyymjXQ.js","getApiPlaygroundDisplay-BB9vkXtE.js","CodeSnippet-Bm5RU7m1.js","CodeSnippets-BgU9Deuz.js","Page-BUDYNlhG.js","getPastedJson-BD-6NNum.js","icon-8Z6tud2e.js","MethodPill-Tuzr4g3V.js","DuplicateIcon-0ceWFYhN.js","createIcon-FBXow_ST.js","DynamicMarkdown-CD8713Yy.js","SectionHeading-7zgzQbH-.js","axios-vUo_bRtp.js","Markdown-D7Ofw1oz.js","clsx-eKJ4rcii.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CwjSCXIK.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-9EK5IAXV.js"]}