docs: Obsidian-style vault under docs/

Add a navigable Obsidian vault as the project's first-class
technical documentation. Notes cross-reference with [[wikilinks]];
docs/index.md is the Map of Content.

New notes:
  index.md             MOC, entry point
  architecture.md      what the extension owns vs what lives outside
  data-model.md        entity-by-entity schema reference
  menu-tree.md         the arbitrary-depth tree concept
  order-flow.md        state machine + invoice listener + print
  nostr-layer.md       kinds 0/30402/5/1059, signing, t-tags
  api-reference.md     endpoint catalog by audience
  cms.md               Vue 3 + Quasar 2 UMD conventions, q-tree
  webapp-integration.md  multi-restaurant cart pattern + atomicity
  glossary.md          domain terms

Existing notes (kept as-is):
  adr-0001-menu-tree.md  the storage choice rationale
  design-conversation.md trimmed transcript

README.md adds a Documentation section pointing at docs/index.md
with the headline note list. Each note links to ~3-5 others; the
vault forms a connected graph.

A project-level memory rule (saved outside the repo) commits us to
keeping these docs in sync as the code evolves: any commit that
materially changes schema, API, order flow, Nostr surface, CMS
conventions, or webapp integration must update the relevant note(s)
in the same commit.
This commit is contained in:
Padreug 2026-05-02 09:34:07 +02:00
commit 42a8b08a5b
11 changed files with 1015 additions and 0 deletions

109
docs/api-reference.md Normal file
View file

@ -0,0 +1,109 @@
# API reference
All routes live under `/restaurant/api/v1`. Three audiences:
- **Public** — no auth, used by customer webapps to read menus.
- **Customer** — no auth, places orders and queries them.
- **Owner** — wallet admin key in `X-Api-Key`, ownership-checked by
matching `restaurant.wallet`.
For exhaustive per-endpoint detail open `views_api.py`; this note is
the catalog.
## Public reads
| Method | Path | Notes |
|---|---|---|
| `GET` | `/restaurants/{id}` | Restaurant profile |
| `GET` | `/restaurants/{id}/menu` | `{restaurant, tree, items}` — the canonical [[menu-tree|menu tree]] (hydrated children + items per node) plus a flat enriched items list with modifier groups + availability windows pre-joined |
| `GET` | `/menu_items/{id}` | Single item |
| `GET` | `/menu_nodes/{id}` | Single node row |
| `GET` | `/restaurants/{id}/menu_nodes` | Flat list of all nodes — useful for parent pickers |
| `GET` | `/menu_items/{id}/modifier_groups` | Groups for an item |
| `GET` | `/modifier_groups/{id}/modifiers` | Modifiers for a group |
| `GET` | `/menu_items/{id}/availability_windows` | Availability rules |
## Customer order placement
| Method | Path | Notes |
|---|---|---|
| `POST` | `/orders/quote` | Pre-flight balance check; body is a list of `CreateOrderItem`. Returns `{required_msat}`. See [[order-flow]] |
| `POST` | `/orders` | Place an order on one restaurant; returns `{order, invoice}` where `invoice` is the bolt11 + payment_hash |
| `GET` | `/orders/{id}` | Order + items |
For multi-restaurant carts the webapp posts `/orders` once per
restaurant; see [[webapp-integration]].
## Owner CRUD (`X-Api-Key: <admin>`)
### Restaurants
| Method | Path |
|---|---|
| `GET` | `/restaurants?all_wallets=true` |
| `POST` | `/restaurants` |
| `PUT` | `/restaurants/{id}` |
| `DELETE` | `/restaurants/{id}` |
### Menu nodes (the tree)
| Method | Path | Notes |
|---|---|---|
| `POST` | `/menu_nodes` | depth + path derived from parent; HTTP 400 if creates would exceed cap |
| `PUT` | `/menu_nodes/{id}` | rename / desc / sort / image. **Rename re-publishes every item in the subtree** so [[nostr-layer\|ancestor `t` tags]] update |
| `PUT` | `/menu_nodes/{id}/move` | body `{new_parent_id}`; HTTP 400 on cycle / depth violation |
| `DELETE` | `/menu_nodes/{id}?cascade=true\|false` | default blocks (HTTP 409) if children/items exist; cascade=true detaches items and deletes the subtree of nodes |
### Menu items
| Method | Path | Notes |
|---|---|---|
| `POST` | `/menu_items` | Re-publishes to Nostr |
| `PUT` | `/menu_items/{id}` | Re-publishes |
| `DELETE` | `/menu_items/{id}` | Sends NIP-09 deletion |
### Modifier groups + modifiers
`POST` / `DELETE` for `/modifier_groups` and `/modifiers`.
### Availability windows
`POST` / `DELETE` for `/availability_windows`.
### Orders (operator)
| Method | Path | Notes |
|---|---|---|
| `GET` | `/restaurants/{id}/orders?statuses=...&limit=...` | invoice key acceptable — used by the [[cms\|order monitor + KDS]] |
| `PUT` | `/orders/{id}/status/{new_status}` | Manual transitions (`accepted`, `ready`, `completed`, `canceled`, `refunded`); admin key required |
### Print jobs
| Method | Path | Notes |
|---|---|---|
| `GET` | `/restaurants/{id}/print_jobs?status=...` | invoice key |
| `PUT` | `/print_jobs/{id}/ack` | Called by `printer-pi` after a successful print; admin key |
### Settings (LNbits admin only)
| Method | Path |
|---|---|
| `GET` | `/settings` |
| `PUT` | `/settings` |
## Error shapes
Standard FastAPI `{"detail": "<msg>"}`. Status codes:
- `400` — validation, depth / cycle on menu node ops, balance precheck failures
- `403` — owner check failed
- `404` — entity missing
- `409` — node delete blocked by children / items (pass `?cascade=true`)
- `500` — server-side, with the exception captured in logs
## See also
- [[architecture]]
- [[order-flow]]
- [[menu-tree]]
- [[webapp-integration]]