Royal Glow internal docs · now fully interactive — Steps, API tables, file trees & live status
Royal Glow Docs
API Reference

Bookings

Customer endpoints to create, list, view, and cancel bookings.

Bookings

Customer-facing booking endpoints. Every endpoint here calls requireSession, so a valid Better Auth session cookie is required. Bookings are scoped to the signed-in customer — you can only read or cancel your own.

Base URL: https://theroyalglow.in · Auth: Better Auth session; minimum role customer on all endpoints below (any authenticated user is at least a customer). Money is an integer in paise; dates are YYYY-MM-DD; times are HH:mm (24-hour). Requests without a session return UNAUTHENTICATED (401).

POST /api/bookings

Creates a booking request for the signed-in customer. The booking is created with status pending and a generated booking number. Pricing and total duration are computed server-side from the selected services (GST-inclusive paise), and endTime is derived from startTime + total duration.

Minimum role: customer (requireSession)

POST /api/bookings
Content-Type: application/json

Request body

Validated by createBookingSchema (@rgss/types).

Prop

Type

{
  "branchId": "br_rayasandra01",
  "serviceType": "salon",
  "bookingDate": "2026-06-15",
  "startTime": "11:00",
  "serviceIds": ["svc_haircut001", "svc_beardtrim01"],
  "notes": "Prefer a window seat if available."
}

Response

Returns 201 Created. The payload contains the new booking's id, generated booking number, and status.

{
  "success": true,
  "data": {
    "id": "bk_8f2a1c9e4d",
    "bookingNumber": "BK-RS-2606-H-38291",
    "status": "pending"
  }
}

The booking number format is BK-{branchCode}-{YYMM}-{H|S}-{5 digits}H for salon, S for spa.

Errors

All pre-condition failures (branch state, service existence/activeness, type mismatch, no available staff) are raised as badRequest, so they surface as VALIDATION_ERROR with a 400 — not as booking-domain codes.


GET /api/bookings

Lists all bookings for the signed-in customer, newest first. Each booking includes its services (the booking_service snapshot rows, ordered by displayOrder).

Minimum role: customer (requireSession)

GET /api/bookings

Response

{
  "success": true,
  "data": {
    "bookings": [
      {
        "id": "bk_8f2a1c9e4d",
        "bookingNumber": "BK-RS-2606-H-38291",
        "branchId": "br_rayasandra01",
        "customerId": "usr_abc123",
        "status": "pending",
        "serviceType": "salon",
        "bookingDate": "2026-06-15",
        "startTime": "11:00:00",
        "endTime": "12:00:00",
        "totalAmountPaise": 130000,
        "totalDurationMinutes": 60,
        "notes": "Prefer a window seat if available.",
        "isWalkin": false,
        "isMembershipSession": false,
        "offerId": null,
        "spaMembershipId": null,
        "confirmedAt": null,
        "completedAt": null,
        "cancellationReason": null,
        "cancelledAt": null,
        "rejectionReason": null,
        "rejectedAt": null,
        "rescheduleCount": 0,
        "createdAt": "2026-06-01T06:15:00.000Z",
        "updatedAt": "2026-06-01T06:15:00.000Z",
        "services": [
          {
            "id": "bs_1",
            "bookingId": "bk_8f2a1c9e4d",
            "serviceId": "svc_haircut001",
            "staffId": "stf_default01",
            "serviceNameSnapshot": "Signature Haircut",
            "priceAtBookingPaise": 80000,
            "durationMinutes": 45,
            "displayOrder": 0
          }
        ]
      }
    ]
  }
}

Errors


GET /api/bookings/[id]

Returns a single booking (with its services) owned by the signed-in customer.

Minimum role: customer (requireSession)

GET /api/bookings/bk_8f2a1c9e4d

Path parameters

Prop

Type

If the booking does not exist or belongs to another customer, the handler returns 404 NOT_FOUND (not 403) so it never reveals which booking ids exist.

Response

{
  "success": true,
  "data": {
    "booking": {
      "id": "bk_8f2a1c9e4d",
      "bookingNumber": "BK-RS-2606-H-38291",
      "branchId": "br_rayasandra01",
      "customerId": "usr_abc123",
      "status": "confirmed",
      "serviceType": "salon",
      "bookingDate": "2026-06-15",
      "startTime": "11:00:00",
      "endTime": "12:00:00",
      "totalAmountPaise": 130000,
      "totalDurationMinutes": 60,
      "notes": null,
      "isWalkin": false,
      "isMembershipSession": false,
      "offerId": null,
      "spaMembershipId": null,
      "confirmedAt": "2026-06-01T07:00:00.000Z",
      "completedAt": null,
      "cancellationReason": null,
      "cancelledAt": null,
      "rejectionReason": null,
      "rejectedAt": null,
      "rescheduleCount": 0,
      "createdAt": "2026-06-01T06:15:00.000Z",
      "updatedAt": "2026-06-01T07:00:00.000Z",
      "services": [
        {
          "id": "bs_1",
          "bookingId": "bk_8f2a1c9e4d",
          "serviceId": "svc_haircut001",
          "staffId": "stf_default01",
          "serviceNameSnapshot": "Signature Haircut",
          "priceAtBookingPaise": 80000,
          "durationMinutes": 45,
          "displayOrder": 0
        }
      ]
    }
  }
}

Errors


POST /api/bookings/[id]/cancel

Cancels a booking owned by the signed-in customer. Only bookings in status pending or confirmed can be cancelled. Sets status to cancelled and records the reason and timestamp.

Minimum role: customer (requireSession)

POST /api/bookings/bk_8f2a1c9e4d/cancel
Content-Type: application/json

Path parameters

Prop

Type

Request body

The body is optional and validated by cancelBookingSchema. An empty or missing body is accepted.

Prop

Type

{
  "reason": "Plans changed, will rebook next week."
}

Response

{
  "success": true,
  "data": {
    "id": "bk_8f2a1c9e4d",
    "status": "cancelled",
    "cancelledAt": "2026-06-02T09:20:00.000Z"
  }
}

Errors

OpenReport an issue

Was this page helpful?

On this page