Skip to content

Build a custom booking flow with the JavaScript SDK

Use the SDK when you are building a custom website or app and want to control the UI yourself.

Terminal window
npm install @odeva/booking-sdk
import { OdevaClient } from "@odeva/booking-sdk";
const odeva = new OdevaClient({
organizationSlug: "crystal-springs",
});

The SDK uses the production Odeva Booking API and checkout URL by default.

const accommodations = await odeva.searchAccommodations({
startDate: "2026-07-01",
endDate: "2026-07-08",
guests: 2,
});

Show the returned accommodations in your own UI. Each accommodation includes units, guest limits, pricing information, images, and status fields needed for a search result or detail page.

const availability = await odeva.checkAvailability({
unitId: "unit_123",
startDate: "2026-07-01",
endDate: "2026-07-08",
});
if (availability.available) {
// Continue to pricing or booking.
}
const price = await odeva.calculatePrice({
unitId: "unit_123",
startDate: "2026-07-01",
endDate: "2026-07-08",
numAdults: 2,
numChildren: 0,
});

The result includes subtotal, charges, discounts, VAT, total amount, down payment amount, and security deposit amount.

const reservation = await odeva.createReservation({
unitId: "unit_123",
startDate: "2026-07-01",
endDate: "2026-07-08",
numAdults: 2,
numChildren: 0,
mainGuest: {
firstName: "Alex",
lastName: "Morgan",
email: "alex@example.com",
},
returnUrl: "https://example.com/booking-confirmation",
});

The reservation response includes a checkout token. Use the hosted checkout flow to collect payment when payment is required.

Only use apiKey in trusted server-side code. Do not ship an API key in browser JavaScript.

const odeva = new OdevaClient({
apiKey: process.env.ODEVA_API_KEY,
organizationSlug: "crystal-springs",
});

See example: https://github.com/Odeva-Labs/odeva-examples/tree/main/examples/astro-backend-proxy

Check that organizationSlug matches the organisation that owns the accommodation, availability, pricing, and checkout settings:

const odeva = new OdevaClient({
organizationSlug: "crystal-springs",
});

If you pass a custom API URL, confirm it points to the production API unless Odeva gave you a different endpoint:

https://booking.odeva.app/graphql

Use the hosted checkout URL from the reservation response when payment is required. If you set a custom returnUrl, make sure it is a full public URL and not a local development address.

Move API-key calls to server-side code. Browser code should use public booking methods that do not require a secret.

Local testing works but production does not

Section titled “Local testing works but production does not”

Confirm production can reach:

https://booking.odeva.app/graphql
https://booking.odeva.app/checkout

Also check browser console errors for blocked requests, content security policy rules, or mixed-content warnings.