Connect your website
Take direct bookings on your own website — availability, booking creation, and guest payment in three API calls.
🌐 Connect your website
Build a booking flow on your own website powered by OkupAI. Your site shows live availability and prices, creates the booking, and (optionally) lets the guest pay by card — while OkupAI handles calendar sync, invoicing, guest messaging, and overbooking protection behind the scenes.
The whole integration is three calls with a single X-API-Key header. No Stripe SDK, no Stripe keys, and no webhooks are needed on your side.
🧭 Flow overview
1
GET /data/pricing
Show availability & prices, validate stay length
2
POST /data/bookings
Create the booking
3
Redirect to checkout_url
Guest pays via Stripe (card payments only)
4
GET /data/bookings/{booking_id}/payment-status
Confirm payment on your success page
For Bank Transfer, Cash, or Paypal bookings, steps 3 and 4 are not needed — the booking is final after step 2.
1️⃣ Get prices and availability
Use the Pricing endpoint to render your calendar:
curl -sS \
-H "X-API-Key: $OKUPAI_API_KEY" \
"https://api.okup.ai/data/pricing?from=2026-08-01&to=2026-08-05&okupai_property_id=0017a629-2f7f-4798-af77-98660c19d3a1"Only offer dates where:
every night of the stay has
available: true, andthe stay length satisfies the
min_nightsof the arrival date
The API enforces both rules on booking creation — closed nights are rejected with 409, a too-short stay with 400. Validating them upfront in your UI avoids failed bookings.
2️⃣ Create the booking
Returns 201 Created on success.
Minimal request (non-Stripe)
Field reference
platform
✅
Must be exactly Website
okupai_property_id
✅
Property UUID from the Pricing endpoint
reservation_start
✅
Check-in date, YYYY-MM-DD
reservation_end
✅
Checkout date, exclusive — must be after check-in; maximum stay 90 nights
guest_name
✅
Full guest name (whitespace is normalized)
adults
✅
Integer ≥ 1
nights_price
✅
Total for the nights, as a string decimal ("800.00"); "0.00" is allowed
payment_method
✅
One of Stripe, Bank Transfer, Cash, Paypal
children
optional
Default 0, maximum 10
email
optional
Basic format check
phone
optional
E.164 format, e.g. +431234567 (whitespace is stripped)
language
optional
ISO language code (2–3 letters), default en — controls guest messaging language
cleaning
optional
Cleaning fee, string decimal, default "0.00"
currency
optional
If provided, must be EUR
extension
optional
Default false — marks the booking as extending an existing stay
invoice
optional
Billing block (see below)
success_url
Stripe only
Your confirmation page, must be https:// (required for Stripe)
cancel_url
Stripe only
Your cancel page, must be https://; defaults to success_url
Important rules:
Do not send a
booking_id— OkupAI generates it and returns it in the response (400if you send one)city_tax_platformis not accepted for website bookingspayment_methodvalues likePlatform,Airbnb, orBlockare rejected with400Monetary values are parsed as decimals and rounded to 2 places — send them as strings
Safe retries with an idempotency key
Send a unique Idempotency-Key header with every new booking request (8–128 URL-safe characters). Keep the same key when retrying the same JSON payload after a timeout or 503; generate a new key for a genuinely new booking.
A replay returns the original booking and, for Stripe, the same checkout session and URL. Reusing a key with a different payload returns 409. The API echoes Idempotency-Key and X-Booking-Operation-Id in response headers; log those headers with the status code and response body when contacting support.
Invoice block (optional)
To have the guest invoice made out to a company:
All fields are optional nullable strings; email must be a valid address if provided.
Response — Bank Transfer / Cash / Paypal
Done — the booking is live in the host's calendar, availability syncs to all platforms, and the guest receives automatic messages.
Response — Stripe
Send payment_method: "Stripe" plus success_url (required, https://) and optionally cancel_url, and you get a ready-to-use checkout link:
Redirect the guest to checkout_url. The checkout charges nights_price + cleaning on the property's connected Stripe account.
Stripe bookings require the property to have Stripe configured in OkupAI — otherwise the API returns 400. Ask the property manager to complete their Stripe setup first.
If you ever receive payment_method: "Stripe" without checkout_url, do not silently continue as a non-card booking. Record the HTTP status, full response body, Idempotency-Key, and X-Booking-Operation-Id, then retry the same request with the same idempotency key. A conforming successful response includes the checkout URL.
3️⃣ Confirm the payment (Stripe only)
The redirect back to your success_url is only a UX signal — the authoritative confirmation comes from Stripe to OkupAI directly. On your success page, poll:
payment_status
Meaning
checkout_created
Checkout link exists, payment not completed yet
paid
Stripe confirmed the payment — show your confirmation
expired
Checkout session expired unpaid
none
No Stripe payment exists for this booking
Unknown or out-of-scope booking IDs return 404.
Recommended polling: every 2–3 seconds, for up to ~30 seconds. Show the confirmation only on paid.
⚡ Complete JavaScript example
❌ Error handling
400
Invalid payload — missing field, bad dates, stay too short for min_nights, unsupported payment method, invalid URL
Show the human-readable error message
401
Missing API key
Check your server configuration
403
Invalid key, or property outside your allowed scope / inactive
Check key & property assignment
404
Unknown booking on the payment-status endpoint
Verify the booking_id
409
Dates no longer available — overlap with an existing booking, host-closed nights, or duplicate submission
Refresh GET /data/pricing and ask the guest to pick new dates
500
Unexpected OkupAI-side error
Record the response and operation headers, then contact support if it persists
503
Temporary database or booking-state uncertainty
Retry the identical request with the same Idempotency-Key after Retry-After
🏆 Connecting optimally — best practices
🔑 Keep the API key server-side. Never ship it in browser JavaScript — proxy the calls through your backend
🆔 Use
okupai_property_ideverywhere. Property names (friendly_name) can change; the UUID never does📆 Cache pricing sensibly. Refresh the calendar with the Pricing endpoint's
changed_sinceparameter instead of re-downloading everything — see Pricing✅ Validate
min_nightsand availability in your UI before submitting, so guests never hit an error they could have avoided🔁 Always re-check pricing after a
409— availability changes in real time as bookings arrive from all platforms🌍 Send the guest's
language. OkupAI's automatic guest messages (confirmation, check-in instructions) are sent in that language🧾 Collect the invoice block for business guests at checkout — the invoice data flows straight into OkupAI's automatic invoicing
📩 Let OkupAI handle post-booking communication. Website guests automatically receive the same message automations as platform guests — no confirmation emails needed on your side
🧭 Related
Authentication — API keys and scoping
Pricing — availability, rates, and incremental sync
Bookings — reading bookings back