# API Reference

Base URL: `/api`. All responses follow:

```json
// success
{ "success": true, "message": "...", "data": {} }
// list (paginated)
{ "success": true, "message": "...", "data": [], "pagination": { "page": 1, "limit": 20, "total": 100, "totalPages": 5 } }
// error
{ "success": false, "message": "...", "errors": [] }
```

Auth: `Authorization: Bearer <accessToken>` header, obtained from
`POST /api/auth/login`. Refresh token lives in an HTTP-only cookie and is
exchanged via `POST /api/auth/refresh` (the frontend's Axios interceptor
does this automatically on a `401`).

## Modules

| Base path | Notes |
|---|---|
| `/auth` | login, refresh, logout, me, change-password |
| `/companies`, `/outlets` | tenant admin |
| `/users`, `/roles`, `/permissions` | RBAC admin |
| `/dashboard` | live summary stats |
| `/menu` | `/menu/items`, `/menu/categories`, `/menu/combos`, `/menu/stations` |
| `/taxes`, `/discounts` (+ `/discounts/coupons`) | billing configuration |
| `/tables` (+ `/tables/floors`) | floor/table management |
| `/pos`, `/orders` | order creation (`POST /pos`), KOT (`POST /pos/:id/kot`), hold/resume/cancel, charge-to-room |
| `/payments` | split payments, refunds |
| `/kitchen` | KDS board, station list, KOT status transitions |
| `/inventory` | items, units, adjust, transactions, wastage, transfers |
| `/recipes` | recipe CRUD per menu item |
| `/purchases`, `/suppliers` | purchase orders, goods-receipt invoices |
| `/customers` | CRM |
| `/reservations` | restaurant table reservations |
| `/hotel` | room types, occupancy, hotel reservations, folio read/post |
| `/rooms` | room CRUD |
| `/guests` | hotel guest profiles |
| `/checkins`, `/checkouts` | hotel front-desk workflow |
| `/folios` | folio detail + posting a charge |
| `/housekeeping` | room housekeeping status |
| `/cash-registers` (+ `/cash-registers/day-end`) | cash session + day-end close |
| `/expenses`, `/employees` (+ `/employees/:id/attendance`) | ops |
| `/reports` | sales, items, payments, tax, hotel-occupancy |
| `/online-orders`, `/qr` (+ `/qr/public/:code`) | online/QR ordering surface |
| `/settings` (+ `/settings/printers`, `/settings/printer-routes`) | configuration |
| `/media` | authenticated upload/serve (Multer + Sharp) |
| `/notifications`, `/audit-logs` | system |

## Example: create a POS order

```http
POST /api/pos
Authorization: Bearer <token>
Content-Type: application/json

{
  "outlet_id": 1,
  "order_type": "dine_in",
  "table_id": 1,
  "items": [
    { "item_id": 1, "quantity": 2 },
    { "item_id": 9, "variation_id": 2, "quantity": 1 }
  ]
}
```

The server re-fetches every item/variation/addon/modifier/tax from the
database and computes `subtotal`, `discount_amount`, `tax_amount`,
`round_off` and `grand_total` itself (spec §132) — the client's `items`
array only ever supplies IDs and quantities, never prices.

## Example: charge a restaurant order to a hotel room

```http
POST /api/pos/:orderId/charge-to-room
{ "room_number": "103" }
```

Looks up the checked-in guest's open folio for that room, posts a
`restaurant` folio item, links it via `restaurant_room_charges`, and closes
the order with `charged_to_room: true` — see `docs/HOTEL-FLOW.md`.

Full request/response examples for the two critical end-to-end flows are in
`docs/POS-FLOW.md` and `docs/HOTEL-FLOW.md`.
