A busy week ahead of the bank pilot — new endpoints around bookings, a unified pricing engine, and a large round of security and reliability hardening.
New
- Cancellation quote endpoint.
GET /bookings/{n}/cancellation-quotereturns a refund preview before you actually cancel — fees, refundable amount and currency. Useful for showing customers what they’d get back. See Bookings. - Filter bookings by traveler.
GET /bookingsnow accepts acustomer_referencequery parameter so you can list every booking belonging to one of your customers in a single call. See Bookings. quote_idon bookings. Bookings now carry the originatingquote_id, making it easy to reconcile a quote with the booking it produced. Conflict responses onPOST /bookingsare now clean409s with a typed error code — see Errors.- Webhook lookup.
GET /webhooks/{id}lets you fetch a single webhook subscription by ID. See Webhooks.
Improvements
- Unified pricing engine. B2C (Safariat.com) and SafarAPI now share a single pricing engine, so a quote you get through the partner channel matches what end-users see on Safariat — no more silent drift between the two surfaces. See Quotes.
- Effective age brackets exposed. Quote responses now surface the actual age brackets applied to each traveler instead of returning
nullplaceholders. See Quotes. - Slot re-validation at booking time.
POST /bookingsnow re-checks slot availability at confirmation and returns a precise422if the slot is no longer bookable, instead of failing later in the flow. See Errors. - Stronger
customer_referencepseudonymization. Your customer references are now pseudonymized with keyed HMAC-SHA256 (per-partner key), so they can’t be correlated across partners even in the event of a data leak. See Bookings. - Pre-pilot security & reliability hardening. A multi-batch round of partner-channel hardening landed across rate limiting, idempotency, request signing, indexes and hot-path caches — translating to lower latency and more predictable behavior under load. The Idempotency contract has been tightened and documented.
- Partner Console hardening. RBAC, observability and performance improvements across the Console ahead of the bank pilot.
Fixes
- Removed the unused
extra_bedsfield from the quote contract — it never had any effect on pricing or availability. - The Partner Console now correctly shows your name and email instead of “Unknown user”.
- Fixed a tenant-isolation bug where the Team page could list users from other partners.
- Sandbox catalogue refresh is now correctly isolated per tenant, so test data from one partner can’t appear in another’s sandbox.
- Sandbox spec examples now match the real sandbox response shapes (the sandbox is a production clone, not a hand-crafted seed). See Sandbox.
This week marks the public launch of the SafarAPI partner channel and developer experience.
New
- SafarAPI partner channel is live.
api.safarapi.comnow serves the partner endpoints — quote, book and settle Moroccan adventures from your app. See the welcome guide and the 5‑minute quickstart. - Self‑service sandbox signup. Sign up at console.safarapi.com/signup, receive a magic link, and copy your
sk_test_*key from the activation page. Details in Sandbox. - Developer portal & landing site. developers.safarapi.com (this site) and safarapi.com are now public.
- Partner Console. console.safarapi.com gives you signup, key management, and an authenticated dashboard backed by our partner identity realm.
- Isolated sandbox catalogue. Sandbox data lives in a dedicated PostgreSQL schema, fully separated from production. The catalogue refreshes every Sunday at 03:00 UTC from the live Safariat inventory, while your sandbox bookings, quotes and idempotency keys are preserved across refreshes. See Sandbox.
- FLEXIBLE booking mode. Rate packs can now be sold without a fixed departure window — bookings are accepted on daily capacity rather than a schedule, which unlocks always‑on experiences (city tours, day trips, on‑demand activities) on the partner channel. See Bookings.
Improvements
- Automatic
Idempotency-Keyon Console writes. The Console now injects anIdempotency-Keyheader on every write request, so retries from the dashboard are always safe. The same header remains required on your own server‑to‑server calls — see the quickstart. - CORS allow‑list expanded. Calls from official SafarAPI surfaces (Console, developer portal, landing) are now accepted by the API without extra configuration.
- Health endpoints. The documented partner health check is
GET /api/partner/v1/health(public, returns{"status":"ok"}). Separately, the infrastructure liveness probe/actuator/healthis routed to a dedicated management port — internal only, not part of the API contract.
Fixes
- FLEXIBLE rate packs are now accepted by publication validation, so partners see them in the catalogue immediately after they go live.
- FLEXIBLE schedules correctly fall back to daily capacity when checking availability — bookings on always‑on experiences no longer fail with a schedule mismatch.
- Sandbox signup is now gracefully gated on identity‑provider readiness; failed signups return a clean error instead of a 5xx.