Xentra Production · rest.myxentra.com

The Xentra Data API.

One integration point for everything Xentra knows about a booking — guest contact, check-in data, custom fields, billing address, payment status. Use the REST API to pull, subscribe to webhooks to be notified the moment something changes. Most partners use both.

The two layers

Pull — REST API

You ask, we answer. Create an Api-Key in Profil → Data API, send it in the request header, hit endpoints under /api/v1/. Read bookings, check-in data, properties, insurance. Write new bookings, cancel them, manage your webhook subscriptions.

Push — Outgoing webhooks

We tell you. Subscribe to events (checkin_completed, booking_cancelled, door_link_created, …) — Xentra POSTs to your URL the moment they happen. Signed with HMAC, retried on 5xx. Payload shape is identical to the REST response, so the same parsing code works for both.

Most integrations use both. Webhook = real-time. REST = backfill and recovery. The next two sections walk you through which endpoint to call and how to wire it all together.

Which endpoint do I use?
I have… Use this What you get back
A Xentra booking UUID (from a webhook or a prior list call) GET /api/v1/bookings/{id} One booking, full check-in tree inlined. No extra calls.
The guest-visible reservation number (Airbnb code, Smoobu ID, Booking.com confirmation…) GET /api/v1/bookings/?reservation_number=… A 1-row list with the same full body.
"Show me everything that changed since X" GET /api/v1/bookings/?updated_since=…&expand=verification All bookings updated since X, fully inlined, paginated. Won't repeat ones you've already fetched — as long as you store the latest updated_at and pass it next time.
Nothing yet — I want all check-ins to seed my system GET /api/v1/bookings/?check_in_status=approved&expand=verification&limit=25 Every completed check-in, full data per row. Paginate with offset until hasMore is false. (Limit is capped at 25 when expand=verification — each row triggers ~5 sub-queries server-side.)
I want to be notified the moment anything changes POST /api/v1/webhooks (or use the portal) Same body shape as the REST response — pushed to your URL when the event fires.
What "expand=verification" actually does. Add this flag to the list endpoint to inline the full check-in tree on every booking row (travelers, document numbers, resolved invoice address, services selected, custom fields, marketing consent). Without it, list rows are lightweight — fast for calendar views, missing the rich guest data. The single-booking endpoint (GET /bookings/{id}) always returns everything; no flag needed. Read the name as "include full check-in details" — it's a technical alias that stuck.
Recommended pattern: webhook + delta sync

Use both layers. Webhook gets you instant reaction. Delta sync is your safety net for anything the webhook didn't reach (your server was down, network blip, etc.). Together = bulletproof.

Recipes

Backfill all check-ins most common

Every booking with a completed check-in, full guest data inlined. Starting point for any new integration.

# Paginate with offset until hasMore=false. Limit caps at 25 with expand=verification.
curl 'https://rest.myxentra.com/api/v1/bookings/?check_in_status=approved&expand=verification&limit=25' \
  -H 'Api-Key: xtr_live_…'

Delta sync

Only bookings that changed since your last poll. Pair with the checkin_completed webhook for real-time.

# Use the highest updated_at from your last successful poll
curl 'https://rest.myxentra.com/api/v1/bookings/?updated_since=2026-05-01T00:00:00Z&expand=verification' \
  -H 'Api-Key: xtr_live_…'

Direct lookup by reservation number

You have the guest-visible code from an email forward or support ticket and want the matching Xentra booking.

curl 'https://rest.myxentra.com/api/v1/bookings/?reservation_number=HMRTXRFC9D' \
  -H 'Api-Key: xtr_live_…'

Single booking for an invoice

Everything an accounting integration needs in one call: guest contact, dates, totals, payment status, resolved invoice address, services.

curl 'https://rest.myxentra.com/api/v1/bookings/{bookingId}' \
  -H 'Api-Key: xtr_live_…'

Subscribe to a webhook

Self-onboarding via REST instead of the portal. The secret comes back exactly once — store it before the response goes away.

curl 'https://rest.myxentra.com/api/v1/webhooks' \
  -H 'Api-Key: xtr_live_…' \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://your.app/xentra-hook","events":["checkin_completed","booking_cancelled"]}'

Webhook → fetch the full booking

The accounting flow. React to checkin_completed, then fetch the booking by ID to get the freshest data (post-arrival edits, late guest additions, etc.).

# Your handler — after verifying the signature
const bookingId = body.booking_id;
const r = await fetch(`https://rest.myxentra.com/api/v1/bookings/${bookingId}`, {
  headers: { 'Api-Key': process.env.XENTRA_API_KEY }
});
const { booking, verification } = await r.json();

Create a booking

Channel-manager-style push of a new reservation into Xentra. Minimum is arrival, departure, guest name.

curl 'https://rest.myxentra.com/api/v1/bookings/create' \
  -H 'Api-Key: xtr_live_…' \
  -H 'Content-Type: application/json' \
  -d '{"check_in":"2026-06-01","check_out":"2026-06-05","guest_name":"Maria Schmidt","email":"m@example.com","accommodation":"<unit_uuid>","total":420,"currency":"EUR"}'

Cancel a booking

Marks it cancelled in Xentra, mirrors the cancel to your connected PMS and to Channex, and triggers the same Stripe refund flow as a UI cancel.

curl -X PUT 'https://rest.myxentra.com/api/v1/bookings/{bookingId}/cancel' \
  -H 'Api-Key: xtr_live_…'

Get door-links for a booking

Active entrance-access URLs for guest, cleaner, and maintenance — the same links Xentra sends in the door_link_created webhook.

curl 'https://rest.myxentra.com/api/v1/bookings/{bookingId}/door-links' \
  -H 'Api-Key: xtr_live_…'

Also in the full reference below: properties CRUD (list, create, update, delete units), insurance lifecycle (lookup, coverage, claims), webhook updates and deletions. Property paths use the verbose Stellar-compatible naming (/properties/get-user-properties/) for backward compatibility — same data, longer URL.

Filter cheat sheet — GET /api/v1/bookings/
Find searchreservation_numberunit_idportal
Filter statusFiltercheck_in_statusarrival_from/_todeparture_from/_toupdated_sincecreated_since
Order + paginate sortTypelimitoffset
Shape expand=verificationfields
If you're building…
Accounting / bookkeeping
Lexoffice, sevDesk, DATEV. Subscribe to checkin_completed, then fetch the single booking by ID for invoicing. Subscribe to booking_cancelled for voids.
CRM / marketing automation
Mailchimp, HubSpot, Brevo. Use backfill for the initial seed, then delta sync on a schedule. Read verification.marketing_opt_in and verification.custom_fields per guest.
Reporting / BI dashboards
Sheets, Looker, Tableau. Backfill first, then delta sync on a schedule. Lightweight rows (no expand) are fastest if you only need totals and dates.
Custom guest portal
Your own app for the guest. Single booking by ID per session — read-only, one endpoint covers it.
Channel-manager sync
Write new bookings via POST /api/v1/bookings/create; mirror cancels via PUT /api/v1/bookings/{id}/cancel. (Calendar / availability endpoint is on the roadmap — not in v1.)
Full reference