# Smoky Pepper Core > Source of truth for Smoky Pepper (Mexican fast-casual, 3 branches in Phuket, Thailand): ingredients, > recipes, portions, menu items, selling prices, nutrition and EU 14 allergens. POS, web ordering and > the Ko Zaw ops agent read it. Use this API as the source of truth instead of guessing. ## Start here - Interactive API docs (Swagger UI): https://core.smokypepperthailand.com/api/docs - OpenAPI spec (machine-readable): https://core.smokypepperthailand.com/api/openapi.json - ReDoc: https://core.smokypepperthailand.com/api/redoc - This guide: https://core.smokypepperthailand.com/llms.txt ## Rules for using the data - Money is Thai Baht (฿). Selling prices are whole baht (integers); calculated costs are decimals. - NULL means unknown, never zero. Check `issues` (missing data) and `warnings` (data to review) on totals. - Branches: TI (Chalong), KA (Kathu, pickup + delivery only), SY (Rawai); timezone Asia/Bangkok. Channels: `walk_in`, `grab`, `lineman`. Prices differ by branch and channel. - Customer-facing menu text exists in English (source) and Thai, Russian and Chinese: add `lang=th|ru|zh` to `GET /api/menu` (and `GET /api/meta` for allergen labels). Missing phrases fall back to English. Print kitchen tickets from the English menu; IDs are the same in every language. - The selling price of anything is what `POST /api/quote` returns for that branch and channel. Never compute prices yourself from costs: live prices come only from the published price list in effect. - Changing a named special never costs more than the special + what was added (extra portions, a swap's difference); removals earn nothing unless building it yourself is cheaper. `/api/quote` applies this. - Every size and set is its own menu item with its own price: read `default_price_thb` from `GET /api/menu` or quote it; never multiply or scale another item's price. Each item has a format whose base fee is charged once per item (e.g. 1 taco ฿20, a set of 2 or 3 tacos ฿25), so a set of 3 tacos costs less than three single tacos. Before a price list is published, pass the draft's id as `price_list_id` to `GET /api/menu` or `POST /api/quote` to see its prices. - For a variant (another protein, a meal-prep size, one add-on), use the option's `with_price_thb` in `GET /api/menu`: the item's final price with that option picked, as a quote would charge. Don't add an option's `price_thb` (the per-pick add-on value) to the item price yourself: a swap only pays the difference. For combinations, `POST /api/quote`. - Some items have serving hours (`available_from` / `available_until`, Bangkok time; until is exclusive). Outside them a quote is not `ready_for_checkout`, and `GET /api/menu` marks the item `available_now: false`. - `menu_code` is the menu number (B1, W6, BR-2, MP-3) shared by every size and configuration of one special; print it on tickets. Empty = not numbered. - Quote responses have a customer-facing `pricing` block and a staff-only `internal` block (food cost, commission, margin). Never show `internal` to customers. - Nutrition is per item as configured; `allergens` maps allergen -> `contains` | `may_contain`, and `allergens_complete` is false until every ingredient's allergens are reviewed. - Writes need the current `version` (optimistic locking; 409 = reload and retry) and are audited. - Authentication: send `Authorization: Bearer ` on every `/api` call. An owner creates keys in the admin UI (Users & API keys); read keys can't change data. ## Common tasks - What's on the menu at a branch, with prices: `GET /api/menu?branch=TI&channel=walk_in` (add `&price_list_id=N` for a draft price list; `GET /api/price-lists` lists them) - Price, nutrition and allergens of an order: `POST /api/quote` `{"branch_code": "TI", "channel_code": "walk_in", "lines": [{"menu_item_id": "...", "quantity": 1}]}` - Ingredient details (cost, nutrition per 100 g, allergens, suppliers): `GET /api/ingredients/{id}` - Recipe totals per 100 g / per piece and where it's used: `GET /api/recipes/{id}` - Portion sizes, food cost and suggested price under the current policy: `GET /api/portions` - How prices are calculated (curves, minimum multiple): `GET /api/pricing/policies` (newest first) - What changed and who changed it: `GET /api/audit?entity_id=...` ## Endpoints ### meta Vocabularies (units, nutrients, EU 14 allergens), the audit log, and this guide. - `GET /api/audit`: Audit Log. Recent changes, newest first. Each entry holds the full saved record. - `GET /api/health`: Health - `GET /api/llms.txt`: Llms Txt. Plain-text guide for LLM agents: what Core is, the rules for using its data, and every endpoint. - `GET /api/meta`: Meta. Fixed vocabularies: units, ingredient kinds, nutrients, the EU 14 allergens, and menu languages. ### catalog Ingredients (everything bought, with purchase options, nutrition and allergens), suppliers, branches and sales channels. - `DELETE /api/ingredients/{ingredient_id}`: Delete Ingredient - `DELETE /api/suppliers/{supplier_id}`: Delete Supplier - `GET /api/ingredients/{ingredient_id}`: Get Ingredient - `GET /api/ingredients`: List Ingredients - `GET /api/suppliers`: List Suppliers - `POST /api/ingredients/bulk-delete`: Bulk Delete Ingredients. Delete several unused ingredients. Ones still used by a recipe or menu item are skipped, not deleted. - `POST /api/ingredients`: Create Ingredient - `POST /api/suppliers`: Create Supplier - `PUT /api/ingredients/{ingredient_id}`: Update Ingredient - `PUT /api/suppliers/{supplier_id}`: Update Supplier ### recipes Batch recipes, nested to any depth. Totals are per measured yield: cost, nutrition and allergens roll up from ingredients. - `DELETE /api/recipes/{recipe_id}`: Delete Recipe - `GET /api/recipes/{recipe_id}`: Get Recipe - `GET /api/recipes`: List Recipes - `POST /api/recipes`: Create Recipe - `PUT /api/recipes/{recipe_id}`: Update Recipe ### menu Menu items, the resolved menu for a branch and channel, and `POST /api/quote`: the authoritative price, nutrition and allergens for a configured order. - `DELETE /api/menu-items/{item_id}`: Delete Menu Item - `GET /api/menu-items/{item_id}`: Get Menu Item - `GET /api/menu-items`: List Menu Items - `GET /api/menu`: Get Menu. The menu one branch sells through one channel, with resolved prices. - `GET /api/org`: Get Org - `POST /api/calculate`: Calculate. Totals for an amount of any ingredient or recipe. - `POST /api/menu-items/{item_id}/approve`: Approve Menu Item. Mark an item reviewed (approved for sale) without resending it. Undo by unticking - `POST /api/menu-items/{item_id}/duplicate`: Duplicate Menu Item. Copy an item (new IDs everywhere) as a starting point for a variation. - `POST /api/menu-items`: Create Menu Item - `POST /api/quote`: Post Quote. Authoritative price (plus nutrition, allergens, and staff-only cost/margin) for configured items. - `PUT /api/menu-items/{item_id}`: Update Menu Item - `PUT /api/org/branch-channels`: Set Branch Channels. Replace which channels each branch sells through. - `PUT /api/org/branches/{code}`: Update Branch - `PUT /api/org/channels/{code}`: Update Channel ### pricing Portions, formats, pricing policies (cost curve, size curve, minimum multiple), dated price lists, overrides and promotions. - `DELETE /api/formats/{format_id}`: Delete Format - `DELETE /api/portions/{portion_id}`: Delete Portion - `DELETE /api/price-lists/{list_id}`: Delete Price List - `DELETE /api/pricing/overrides/{override_id}`: Delete Override - `DELETE /api/pricing/promotions/{promotion_id}`: Delete Promotion - `GET /api/formats/{format_id}`: Get Format - `GET /api/formats`: List Formats - `GET /api/portions/{portion_id}`: Get Portion - `GET /api/portions`: List Portions - `GET /api/price-lists/active`: Get Active Price List - `GET /api/price-lists/{list_id}`: Get Price List - `GET /api/price-lists`: List Price Lists - `GET /api/pricing/check`: Pricing Check. Structural conflicts plus what generating a price list now would warn about. Errors first. - `GET /api/pricing/overrides`: List Overrides - `GET /api/pricing/policies`: List Policies - `GET /api/pricing/promotions`: List Promotions - `POST /api/formats`: Create Format - `POST /api/menu-items/{item_id}/adopt-build-pricing`: Adopt Build Pricing. Switch a legacy item to build pricing: an explicit administrator decision. - `POST /api/portions`: Create Portion - `POST /api/price-lists/{list_id}/publish`: Publish Price List. Lock the whole list and make it live from `effective_from` (Bangkok date). - `POST /api/price-lists/{list_id}/regenerate`: Regenerate Price List. Recalculate a draft from current costs, portions, formats and named items. - `POST /api/price-lists`: Create Price List. New draft, generated from a policy and today's costs. Review it, then publish. - `POST /api/pricing/overrides`: Create Override. A standing exact price. Takes effect in the next generated (and published) price list. - `POST /api/pricing/policies`: Create Policy. Policies are immutable: changing the curve, floor, rounding or uplifts creates a new version. - `POST /api/pricing/promotions`: Create Promotion. Takes effect immediately for matching days (Asia/Bangkok). - `PUT /api/formats/{format_id}`: Update Format - `PUT /api/portions/{portion_id}`: Update Portion - `PUT /api/price-lists/{list_id}`: Update Price List. Rename a list or edit its notes. Works on published lists too: prices stay locked. - `PUT /api/pricing/overrides/{override_id}`: Update Override - `PUT /api/pricing/promotions/{promotion_id}`: Update Promotion ### translations Thai, Russian and Chinese text for customer-facing menu phrases. Read translated menus with `GET /api/menu?...&lang=th`. - `GET /api/translations/{lang}`: Get Translations. Every phrase the menu needs in one language (missing ones with `text` NULL), plus unused leftovers. - `GET /api/translations`: List Languages. Progress per language: how many menu phrases are reviewed, draft, or missing. - `PUT /api/translations/{lang}`: Save Translations. Create, change or (with empty `text`) delete translations. Send `status: reviewed` once a person has checked one. ### auth Signing in to the admin UI, users, and API keys for machine clients. - `DELETE /api/api-keys/{key_id}`: Revoke Api Key. Revoke a key. Clients using it get 401 from then on. - `GET /api/api-keys`: List Api Keys - `GET /api/auth/me`: Me. The signed-in user or API key. 401 when sign-in is required. - `GET /api/users`: List Users - `POST /api/api-keys`: Create Api Key. Create a key for a machine client. The key is returned once and never again. - `POST /api/auth/login`: Login. Sign in with username and password. Sets an HttpOnly session cookie. - `POST /api/auth/logout`: Logout - `POST /api/users`: Create User - `PUT /api/auth/password`: Change Password - `PUT /api/users/{user_id}`: Update User