Quickstart
This walkthrough runs the entire booking lifecycle against the live API, the same path a custom booking engine or guest app follows. By the end you will have searched availability, priced a stay, registered a guest, held a room, confirmed a paid reservation, read the folio, and earned loyalty points.
What you need
An API key (see Authentication) with these scopes: availability:read, guests:write, reservations:write, folio:write, and loyalty:read. Set it once for the shell:
export VRDN_KEY="vrdn_live_xxxxxxxxxxxxxxxxxxxx"
export VRDN_BASE="https://veridien.app/api/v1"curl "$VRDN_BASE/me" -H "Authorization: Bearer $VRDN_KEY"{
"property_id": "p_8f2a1c",
"property_slug": "sunrise-bay",
"scopes": ["availability:read", "guests:write", "reservations:write", "folio:write", "loyalty:read"],
"request_id": "req_a1b2c3d4e5"
}Find which room types are bookable for the dates and party.
curl "$VRDN_BASE/availability?check_in=2026-08-01&check_out=2026-08-04&adults=2&children=0" \
-H "Authorization: Bearer $VRDN_KEY"{
"check_in": "2026-08-01",
"check_out": "2026-08-04",
"data": [
{
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"name": "Deluxe Ocean Villa",
"description": "A private villa over the lagoon.",
"max_occupancy": 3,
"available": 4,
"currency": "USD",
"amenities": ["Ocean view", "Private deck"],
"bed_configs": [{ "id": "bc_king", "label": "1 King" }],
"photos": ["https://cdn.veridien.app/p_8f2a1c/deluxe-1.jpg"]
}
]
}/rates returns each room type's visible rate plans with a per-night breakdown. Rate-plan visibility rules (local-only, promo-gated, loyalty-tier) are enforced server-side; pass guest_id or promo_code to unlock gated rates.
curl "$VRDN_BASE/rates?check_in=2026-08-01&check_out=2026-08-04&adults=2" \
-H "Authorization: Bearer $VRDN_KEY"{
"check_in": "2026-08-01",
"check_out": "2026-08-04",
"data": [
{
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"name": "Deluxe Ocean Villa",
"max_occupancy": 3,
"base_occupancy": 2,
"amenities": ["Ocean view", "Private deck"],
"bed_configs": [{ "id": "bc_king", "label": "1 King" }],
"photos": ["https://cdn.veridien.app/p_8f2a1c/deluxe-1.jpg"],
"rate_plans": [
{
"rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02",
"name": "Flexible",
"currency": "USD",
"total": "1260.00",
"room_subtotal": "1260.00",
"base_occupancy": 2,
"extra_guest_charge": "0.00",
"single_occupancy_discount": "0.00",
"extra_guest_total": "0.00",
"taxes_total": "0.00",
"tax_breakdown": [],
"nightly_rates": [
{ "date": "2026-08-01", "day_of_week": 6, "rate": "420.00", "source": "base_price" },
{ "date": "2026-08-02", "day_of_week": 0, "rate": "420.00", "source": "base_price" },
{ "date": "2026-08-03", "day_of_week": 1, "rate": "420.00", "source": "base_price" }
]
}
]
}
]
}Reservations belong to a guest. POST /guests finds an existing guest by email or creates one. It is idempotent on email, so it is safe to call on every checkout.
curl -X POST "$VRDN_BASE/guests" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]", "first_name": "Ada", "last_name": "Lovelace", "nationality": "GB" }'{ "guest_id": "3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34", "created": true }Create a soft hold. This reserves inventory for 15 minutes by creating a tentative reservation, prices the stay (room nights + taxes onto a folio), and returns a reservation_id to confirm.
Use an Idempotency-Key
Always send an Idempotency-Key on holds and confirmations so a network retry never creates a duplicate. See Conventions.
curl -X POST "$VRDN_BASE/holds" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1d2c9a-8b3e-4a17-9c2f-1e5b7d0a4c83" \
-d '{
"room_type_id": "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
"rate_plan_id": "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02",
"check_in": "2026-08-01",
"check_out": "2026-08-04",
"guest_id": "3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34",
"adults": 2
}'{
"reservation_id": "7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27",
"folio_id": "1a6c3e9f-4d2b-4e8a-b5c7-9f0e6d4a2c81",
"hold_expires_at": "2026-06-19T08:45:00.000Z",
"total": "1260.00",
"currency": "USD",
"status": "tentative"
}Take payment in your own flow, then confirm the hold with a payment_reference. Veridien marks the reservation confirmed, records the payment on the folio, and (for USD stays) awards loyalty points.
curl -X POST "$VRDN_BASE/holds/7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27/confirm" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9a2e7c10-4b3f-4d28-8c1f-2e6b8d0a5d94" \
-d '{ "payment_reference": "pay_abc123" }'{
"reservation_id": "7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27",
"status": "confirmed",
"check_in_date": "2026-08-01",
"check_out_date": "2026-08-04",
"currency": "USD",
"folio_balance": "0.00",
"already_confirmed": false
}Confirmation is idempotent: replaying the same payment_reference returns "already_confirmed": true without charging again.
Add anything to the guest's folio during the stay: a spa treatment, a restaurant order, a minibar item.
curl -X POST "$VRDN_BASE/reservations/7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27/folio/charges" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{ "description": "Spa treatment", "amount": "120.00", "category": "service" }'{ "line_item_id": "6d4f8b2a-9c1e-4f7d-b8a3-2e5c9f0a1d74", "folio_balance": "120.00", "balances": [{ "currency": "USD", "balance": "120.00" }] }curl "$VRDN_BASE/reservations/7d5dc2ea-1f4e-4bfa-9a52-6c3f08b41e27/folio" -H "Authorization: Bearer $VRDN_KEY"
curl "$VRDN_BASE/guests/3f8a2c1b-9d4e-4c6a-8b7f-5e2d1a9c0b34/loyalty" -H "Authorization: Bearer $VRDN_KEY"That is the full loop. From here, explore the resource references for every field and option:
const BASE = "https://veridien.app/api/v1";
const headers = {
Authorization: `Bearer ${process.env.VRDN_KEY}`,
"Content-Type": "application/json",
};
async function api(path: string, init?: RequestInit) {
const res = await fetch(`${BASE}${path}`, { ...init, headers: { ...headers, ...init?.headers } });
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
return body;
}
// 1. Register the guest
const { guest_id } = await api("/guests", {
method: "POST",
body: JSON.stringify({ email: "[email protected]", first_name: "Ada", last_name: "Lovelace" }),
});
// 2. Hold a room
const hold = await api("/holds", {
method: "POST",
headers: { "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({
room_type_id: "9b2f6c3e-8d1a-4f5b-a7c9-4e0d2b8f1a63",
rate_plan_id: "5c1e8f4a-2b7d-4a9c-8e6f-1d3b9a5c7e02",
check_in: "2026-08-01",
check_out: "2026-08-04",
guest_id,
adults: 2,
}),
});
// 3. Confirm after payment
const reservation = await api(`/holds/${hold.reservation_id}/confirm`, {
method: "POST",
headers: { "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({ payment_reference: "pay_abc123" }),
});
console.log(reservation.status); // "confirmed"