للمطوّرين

واجهة نُوَيّة البرمجية

واجهة REST فوق بيانات منظمتك: قراءة الحجوزات والنزلاء وأنواع الغرف ومؤشرات الأداء، وإنشاء الحجوزات وإلغاؤها، مع إشعارات ويب هوك موقّعة. التوثيق المرجعي أدناه بالإنجليزية.

Authentication

Create an API key on Integrations in your Nuwaya back office (permission integrations.manage). The plaintext key — tch_live_… — is shown once; store it securely. Send it on every request:

curl https://nuwaya.app/api/v1/me \
  -H "Authorization: Bearer tch_live_..."

Keys can expire, be revoked, and be scoped to a single property — a property-scoped key only ever sees that property's data.

Scopes

Grant scopes when creating the key (comma-separated). The literal scope read grants every read scope, write every write scope, and * everything. A key with no scopes can only call /v1/me.

  • read:reservations
  • read:guests
  • read:room-types
  • read:kpis
  • read:products
  • read:menu
  • write:reservations
  • write:guests
  • write:orders

Endpoints

EndpointScopeDescription
GET /api/v1/meKey introspection: organization, prefix, granted scopes. Smoke-test a new key here.
GET /api/v1/reservationsread:reservationsList reservations. Filters: from / to (arrival window), status, limit ≤ 100, offset.
GET /api/v1/reservations/{id}read:reservationsOne reservation by uuid or confirmation number, with room stays and nightly prices.
GET /api/v1/guestsread:guestsGuest profiles (PII). Filters: search (name/email prefix), limit, offset.
GET /api/v1/room-typesread:room-typesRoom types with active room counts and default rates.
GET /api/v1/daily-kpisread:kpisCompleted night-audit KPIs: occupancy, ADR, RevPAR, revenue split. Filters: from / to, limit, offset.
POST /api/v1/reservationswrite:reservationsCreate a booking through the availability-locked engine (409 when sold out). rate_plan_id defaults to the property's first active plan.
POST /api/v1/reservations/{id}/cancelwrite:reservationsCancel by uuid or confirmation number. The property's cancellation policy runs — any fee is charged and reported.
POST /api/v1/guestswrite:guestsCreate a guest profile. An existing guest with the same email is returned (deduplicated: true) instead of duplicated.
curl "https://nuwaya.app/api/v1/reservations?from=2026-07-01&status=confirmed&limit=10" \
  -H "Authorization: Bearer tch_live_..."
curl -X POST https://nuwaya.app/api/v1/reservations \
  -H "Authorization: Bearer tch_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "property_id": "…", "room_type_id": "…",
    "arrival": "2026-08-01", "departure": "2026-08-04", "adults": 2,
    "guest": { "first_name": "Aisha", "last_name": "Khan", "email": "aisha@example.com" }
  }'

MCP server (AI agents)

AI agents connect over the Model Context Protocol at https://nuwaya.app/api/mcp (Streamable HTTP, stateless) using the same Authorization: Bearer tch_live_… key and scopes as the REST API. Tools mirror the API: list_properties, list_room_types, check_availability, list_reservations, create_reservation, cancel_reservation, create_guest, list_products, create_store_order (scope write:orders) and list_menu — bookings and cancellations run through the same availability-locked, server-priced engines as the booking page, and a key only sees the tools its scopes allow. Agentic checkout stays human-settled: create_store_order returns a hosted payment_url — the order confirms only when a person pays it.

Webhooks

Subscribe on the Integrations page: add an endpoint URL and pick events. Nuwaya POSTs each event as JSON with two headers — X-Nuwaya-Event (the event type) and X-Nuwaya-Signature (sha256=<hex>, an HMAC-SHA256 of the raw body using your endpoint's whsec_… secret, shown once at creation). Respond 2xx within 5 seconds. Deliveries triggered by API writes go out right after the response; everything else is swept by a scheduled job (retried up to 5 attempts), and a manual run is available on the Integrations page.

  • reservation.created
  • reservation.confirmed
  • reservation.checked_in
  • reservation.checked_out
  • reservation.cancelled
  • reservation.no_show
  • payment.captured
  • guest.created
  • order.paid
  • invoice.issued
  • invoice.paid
  • invoice.overdue
  • event.lead_created
  • event.confirmed
  • event.completed
  • event.cancelled
  • guest_request.created

Verify the signature before trusting a delivery:

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody: string, signatureHeader: string, secret: string): boolean {
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  return timingSafeEqual(Buffer.from(signatureHeader), Buffer.from(expected));
}

Build an app (marketplace)

Ship your integration to every Nuwaya property. Any workspace can register an app on its Integrations page: pick a slug, the API scopes you need, and (optionally) the webhook events you want pushed to your endpoint — then submit it for review. Once the platform team approves the listing, it appears in the App marketplace on every tenant's Integrations page. When a hotel installs your app it hands you an API key limited to your approved scopes and a whsec_… signing secret for your webhook feed; uninstalling revokes both instantly. Apps can be priced per install per month (BHD); the platform retains a 15% share, recorded per listing.

OAuth install flow (v2)

An approved app can enable OAuth from its developer card (you get a nwc_… client id and a nws_… secret, shown once). Instead of a tenant copy-pasting a key, send them to /oauth/authorize?client_id=…&redirect_uri=…&scope=…&state=… — a signed-in admin approves the consent screen and Nuwaya redirects back with a single-use code (10-minute expiry). Exchange it server-side at POST /api/oauth/token (form fields grant_type=authorization_code, code, redirect_uri, client_id, client_secret) to receive a tch_live_… access token scoped to the tenant's consent — it works on the whole REST API and MCP server, and uninstalling the app revokes it.

Conventions

  • All monetary amounts are integers in minor units — BHD uses 3 decimals, so 75000 = BHD 75.000.
  • Dates are YYYY-MM-DD; timestamps are ISO 8601 UTC.
  • Listings paginate with limit (max 100) and offset, echoed back under pagination.
  • Errors return { "error": { "code", "message" } } with 401 (bad key), 403 (missing scope), 404, or 400.
  • Writes return 201 (created), 200 (idempotent match), 409 (sold out) or 422 (rejected by a business rule). Treat unknown response fields as additive.
Developers · Nuwaya