FrontDesk API & webhooks

Plug your hotel PMS into your revenue management system, BI dashboards, accounting, channel tools or automations (n8n, Zapier, Make). One REST API per property, JSON in and out, signed webhooks on every reservation change. Using Claude, ChatGPT or Cursor? Connect them through our MCP server.

Authentication

Create a key in Settings → Integrations → API & webhooks (owner or manager). Keys are scoped to one property and shown once; we only store a hash. Send it as a bearer token on every request to https://frontdesk.lumnika.com/api/v1. For groups, create one key per property.

Errors are JSON { "error": "…" } with status 401 (bad key), 402 (trial expired), 404, 409 (room taken), 422 (validation, with issues) or 500. Money is always in cents of the property currency.

Endpoints

The full contract is an OpenAPI 3.1 document at /openapi.json: import it into Postman, Insomnia or a code generator.

GET/api/v1/reservations

List reservations, ordered by check-in. Stays overlapping [from, to) when dates are given.

from, to (YYYY-MM-DD) · status (tentative, confirmed, checked_in, checked_out, cancelled, no_show) · updated_since (ISO timestamp, for incremental sync) · limit (1-500, default 100) · offset

curl "https://frontdesk.lumnika.com/api/v1/reservations?from=2026-10-01&to=2026-10-31" \
  -H "Authorization: Bearer fd_live_…"

POST/api/v1/reservations

Create a reservation. Pass an existing guest_id or an inline guest. Returns 201, or 409 if the room is already booked for those dates.

unit_id, check_in, check_out (required) · status (confirmed | tentative) · adults · children · total_cents · notes · source (default "api") · guest_id or guest { first_name, last_name, email, phone }

curl -X POST "https://frontdesk.lumnika.com/api/v1/reservations" \
  -H "Authorization: Bearer fd_live_…" -H "Content-Type: application/json" \
  -d '{"unit_id":"…","check_in":"2026-10-10","check_out":"2026-10-12","adults":2,
       "total_cents":24000,"guest":{"first_name":"Ada","last_name":"Lovelace","email":"ada@example.com"}}'

GET/api/v1/availability

Which rooms are free for the whole range [from, to), plus a count per room type. Active reservations and room blocks count as occupied.

from, to (YYYY-MM-DD, required, max 366 days)

curl "https://frontdesk.lumnika.com/api/v1/availability?from=2026-10-10&to=2026-10-12" \
  -H "Authorization: Bearer fd_live_…"

GET/api/v1/guests

Guest directory: id, name, email, phone, nationality. Identity documents are never exposed.

email (exact, case-insensitive) · limit · offset

curl "https://frontdesk.lumnika.com/api/v1/guests?email=ada@example.com" \
  -H "Authorization: Bearer fd_live_…"

POST/api/v1/charges

Post a charge from your POS, restaurant, bar or spa onto the guest folio, by reservation id or by room number (the checked-in stay). Safe to retry: the same idempotency key never charges twice (201 new, 200 replay). Emits charge.created.

reservation_id or room · description · amount_cents · type (service|extra) · department · idempotency_key (or Idempotency-Key header)

curl -X POST "https://frontdesk.lumnika.com/api/v1/charges" \
  -H "Authorization: Bearer fd_live_…" -H "Idempotency-Key: pos-check-4812" \
  -H "content-type: application/json" \
  -d '{"room":"101","description":"Dinner, table 7","amount_cents":6400,"department":"restaurant"}'

GET/api/v1/charges

Service and extra lines posted on folios, newest first, to reconcile what your POS sent.

reservation_id · since (ISO timestamp) · limit · offset

curl "https://frontdesk.lumnika.com/api/v1/charges?since=2026-10-10T00:00:00Z" \
  -H "Authorization: Bearer fd_live_…"

Webhooks

Add an HTTPS URL in the same settings panel and we POST an event whenever a reservation is created, updated or cancelled from the front desk or through the API, and whenever a charge lands on a folio: reservation.created, reservation.updated, reservation.cancelled, charge.created.

{
  "id": "5b0f…",
  "type": "reservation.created",
  "created_at": "2026-10-01T09:12:44.120Z",
  "data": {
    "id": "…", "unit_id": "…", "guest_id": "…",
    "check_in": "2026-10-10", "check_out": "2026-10-12",
    "status": "confirmed", "adults": 2, "children": 0,
    "total_cents": 24000, "source": "api", "rate_plan_id": null, "group_id": null,
    "created_at": "…", "updated_at": "…"
  }
}

Every request carries a frontdesk-signature: t=<unix>,v1=<hex> header, an HMAC-SHA256 of <t>.<raw body> with your endpoint secret. Verify it and reject timestamps older than five minutes:

import crypto from 'node:crypto';

// header: the "frontdesk-signature" request header, body: the raw request body
function verify(secret, header, body) {
  const { t, v1 } = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; // replay window
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${body}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(v1, 'hex'), Buffer.from(expected, 'hex'));
}

Delivery is attempted once with an 8-second timeout; the last HTTP status is shown in settings. To stay in sync after downtime, poll GET /reservations?updated_since=….

Build on FrontDesk

The API is included in every plan, trial included. 14 days free, no credit card.

Try FrontDesk free