KiBand|API Documentationv1

KiBand REST API

Integrate your PMS, POS or kiosk with KiBand wristband management. Push reservations, check wallet balances, debit points, and pull transaction reports.

Base URL
https://api.kiband.app
Format
JSON (application/json)
Auth
Bearer token (API key)

Quickstart

1 — Generate an API key

Go to Dashboard → Settings → API Keys and click Generate new key. Copy the key immediately — it is shown only once.

2 — Authenticate every request

Pass the key in the Authorization header:

curl https://api.kiband.app/v1/me \
  -H "Authorization: Bearer kb_live_YOUR_KEY"

3 — Push a reservation

curl -X POST https://api.kiband.app/v1/stays \
  -H "Authorization: Bearer kb_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reservation_no": "RES-2026-001",
    "check_in_date": "2026-05-01",
    "check_out_date": "2026-05-05",
    "guests": [{ "full_name": "Mohammed El Fassi", "guest_type": "primary" }]
  }'

4 — Check a bracelet balance

curl https://api.kiband.app/v1/bracelets/04A3B2C1D2E3F4 \
  -H "Authorization: Bearer kb_live_YOUR_KEY"

🔑 Authentication

GET/v1/healthNo auth

Check API availability. No authentication required.

Response
{ "ok": true, "service": "KiBand API", "version": "1.0", "timestamp": "2026-04-24T10:00:00Z" }
GET/v1/me

Verify your API key and retrieve the associated hotel information.

Response
{
  "ok": true,
  "data": {
    "tenant_id": "uuid",
    "name": "The Lemonary Marrkech",
    "code": "the-lemonary-marrkech",
    "timezone": "Africa/Casablanca",
    "currency": "MAD",
    "subscription_status": "active"
  }
}

🏨 Stays

GET/v1/stays

List stays for your property. Supports filtering by status and date range.

Query Parameters
statusstringFilter by status: active | checked_out | cancelled
fromdateCheck-in date ≥ (YYYY-MM-DD)
todateCheck-out date ≤ (YYYY-MM-DD)
limitintegerMax results, 1–200 (default 50)
offsetintegerPagination offset (default 0)
Response
{
  "ok": true,
  "data": [
    {
      "id": "uuid",
      "reservation_no": "RES-2026-001",
      "check_in_date": "2026-05-01",
      "check_out_date": "2026-05-05",
      "status": "active",
      "rate_plan": { "code": "BB", "name": "Bed & Breakfast", "is_all_inclusive": false },
      "guests": [
        { "full_name": "Mohammed El Fassi", "guest_type": "primary" }
      ]
    }
  ],
  "meta": { "total": 42, "limit": 50, "offset": 0 }
}
POST/v1/stays

Create or upsert a stay. If reservation_no already exists it will be updated.

Request Body (JSON)
reservation_no*stringUnique reservation identifier from your PMS
check_in_date*dateYYYY-MM-DD
check_out_date*dateYYYY-MM-DD
folio_nostringFolio / billing reference
statusstringactive (default) | checked_out | cancelled
rate_plan_codestringRate plan code (must exist in KiBand)
guestsarrayGuest list (see guest object below)
Request
{
  "reservation_no": "RES-2026-001",
  "check_in_date": "2026-05-01",
  "check_out_date": "2026-05-05",
  "rate_plan_code": "BB",
  "guests": [
    { "full_name": "Mohammed El Fassi", "guest_type": "primary", "email": "m.elfassi@example.com" },
    { "full_name": "Fatima El Fassi", "guest_type": "sharer" }
  ]
}
Response
{ "ok": true, "data": { "id": "uuid", "reservation_no": "RES-2026-001", "created": true } }
GET/v1/stays/:reservation_no

Get full details for a stay including guests, bracelets and wallet summary.

Response
{
  "ok": true,
  "data": {
    "id": "uuid",
    "reservation_no": "RES-2026-001",
    "status": "active",
    "bracelets": [
      { "nfc_uid": "04A3B2C1", "status": "active", "guest_name": "Mohammed El Fassi" }
    ],
    "wallet": {
      "points_allocated": 500,
      "points_consumed": 120,
      "points_available": 380
    }
  }
}
PATCH/v1/stays/:reservation_no

Update stay dates or status.

Request Body (JSON)
check_in_datedateNew check-in date
check_out_datedateNew check-out date
statusstringactive | checked_out | cancelled
Request
{ "status": "checked_out" }
Response
{ "ok": true, "data": { "id": "uuid", "reservation_no": "RES-2026-001", "updated": true } }
DELETE/v1/stays/:reservation_no

Cancel a stay (sets status to cancelled). Does not delete data.

Response
{ "ok": true, "data": { "cancelled": true } }

💳 Bracelets & Wallet

GET/v1/bracelets/:nfc_uid

Get bracelet status, wallet balance, active coupons, and recent transactions. The NFC UID is the card identifier (uppercase hex).

Response
{
  "ok": true,
  "data": {
    "nfc_uid": "04A3B2C1D2E3F4",
    "status": "active",
    "guest": { "name": "Mohammed El Fassi", "type": "primary" },
    "stay": { "check_in_date": "2026-05-01", "check_out_date": "2026-05-05" },
    "wallet": {
      "service_date": "2026-05-02",
      "points_allocated": 200,
      "points_consumed": 45,
      "points_available": 155
    },
    "coupons": [
      { "code": "SPA50", "label": "50% Spa discount", "valid_to": "2026-05-05" }
    ],
    "recent_transactions": [
      { "kind": "debit_points", "points_delta": -30, "service_point": "Pool Bar", "timestamp": "2026-05-02T14:23:00Z" }
    ]
  }
}
POST/v1/bracelets/:nfc_uid/debit

Debit points from a bracelet. Useful for kiosk or POS integrations. Each item requires a client_uuid for idempotency.

Request Body (JSON)
service_point_code*stringCode of the service point (bar, restaurant…)
items*arrayArray of items to debit
items[].catalog_item_code*stringCatalog item code at this service point
items[].quantity*integerNumber of units
items[].client_uuid*uuidUnique idempotency key (UUID v4). Safe to retry.
notesstringOptional transaction note
Request
{
  "service_point_code": "POOL-BAR",
  "items": [
    { "catalog_item_code": "COCKTAIL", "quantity": 2, "client_uuid": "550e8400-e29b-41d4-a716-446655440000" },
    { "catalog_item_code": "WATER-1L", "quantity": 1, "client_uuid": "550e8400-e29b-41d4-a716-446655440001" }
  ]
}
Response
{
  "ok": true,
  "data": {
    "debited_count": 2,
    "skipped_duplicates": 0,
    "total_points_debited": 75,
    "balance": { "points_allocated": 200, "points_consumed": 120, "points_available": 80 }
  }
}

🍹 Service Points & Catalog

GET/v1/service-points

List all active service points. Add ?catalog=true to include item catalog.

Query Parameters
catalogbooleanInclude point catalog items per service point
Response
{
  "ok": true,
  "data": [
    {
      "id": "uuid",
      "code": "POOL-BAR",
      "name": "Pool Bar",
      "kind": "fb_pos",
      "open_time": "10:00:00",
      "close_time": "22:00:00",
      "catalog": [
        { "code": "COCKTAIL", "label": "Cocktail", "points_cost": 30 },
        { "code": "WATER-1L", "label": "Water 1L", "points_cost": 5 }
      ]
    }
  ]
}

📊 Transactions

GET/v1/transactions

List wallet transactions with optional date, bracelet, and type filters.

Query Parameters
fromdatetimeISO 8601 timestamp (server_ts ≥)
todatetimeISO 8601 timestamp (server_ts ≤)
bracelet_iduuidFilter by bracelet ID
kindstringcredit_daily | debit_points | refund_points | coupon_consume | adjustment
limitinteger1–200 (default 100)
offsetintegerPagination offset
Response
{
  "ok": true,
  "data": [
    {
      "id": "uuid",
      "kind": "debit_points",
      "points_delta": -30,
      "quantity": 2,
      "timestamp": "2026-05-02T14:23:00Z",
      "service_point": { "code": "POOL-BAR", "name": "Pool Bar" },
      "bracelet": { "nfc_uid": "04A3B2C1", "guest_name": "Mohammed El Fassi" }
    }
  ],
  "meta": { "total": 1250, "limit": 100, "offset": 0 }
}

⚠️ Errors

All errors return JSON with ok: false, an error code, and a human-readable message.

{ "ok": false, "error": "not_found", "message": "Stay not found" }
HTTP StatusError CodeDescription
400bad_requestMissing or invalid parameters
401unauthorizedMissing, invalid or expired API key
401api_key_expiredAPI key has passed its expiry date
404not_foundThe requested resource does not exist
409conflictResource already exists (e.g. duplicate reservation_no)
500internal_errorUnexpected server error — contact support