For the complete documentation index, see llms.txt. This page is also available as Markdown.

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

Step
Call
Purpose

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.

Authentication works exactly like the rest of the API — see Authentication. Your key only sees the properties assigned to your account. Always identify properties by okupai_property_id (UUID) — never by name, which can change.


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, and

  • the stay length satisfies the min_nights of 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.

For payment_method: "Stripe", a successful 201 response always has status: "checkout_created", checkout_session_id, and checkout_url. Treat a Stripe response missing either checkout field as an error — do not confirm the booking as payment-ready.

Minimal request (non-Stripe)

Field reference

Field
Required
Notes

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 (400 if you send one)

  • city_tax_platform is not accepted for website bookings

  • payment_method values like Platform, Airbnb, or Block are rejected with 400

  • Monetary 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.

When Stripe redirects the guest back, your success_url automatically receives the booking as a query parameter: https://your-site.com/success?booking_id=... — read it there to start polling the payment status. If no cancel_url is provided, cancellations also return to success_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

Status
Meaning
What your site should do

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

Retry with the same idempotency key. After a timeout or 503, resend the identical payload with the same Idempotency-Key. If the booking committed, the API replays the created booking and its Stripe checkout URL. If the outcome is still being reconciled, the API returns 503 with Retry-After; do not create a second request with a new key while that outcome is unknown.


🏆 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_id everywhere. Property names (friendly_name) can change; the UUID never does

  • 📆 Cache pricing sensibly. Refresh the calendar with the Pricing endpoint's changed_since parameter instead of re-downloading everything — see Pricing

  • Validate min_nights and 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


  • Authentication — API keys and scoping

  • Pricing — availability, rates, and incremental sync

  • Bookings — reading bookings back