API reference
API reference
Munim core-api — /v1 and /platform/v1, contract version w1. Generated from the zod contracts the server validates against; storefront routes first.
The raw document is at /developers/openapi.json (OpenAPI 3.1.0).
- Storefront 13
- Customer account 9
- Munim Cares network 5
- Orders, shifts and pickup 18
- Kitchen 5
- Catalogue and menu 14
- Inventory 17
- Purchasing 17
- Finance 13
- People 17
- Customers and growth 15
- Compliance and assets 16
- Munim Cares (business) 17
- Ask, threads and evidence 19
- Investigations 6
- Drafts and approvals 6
- Goals and tasks 6
- Imports 6
- Business setup and members 31
- Platform operator 19
269 operations
Storefront13
- get/v1/storefront/caresThe storefront key's own live donation listings (uncached; a bad key or a non-storefront channel is 404)
- get/v1/storefront/outletsOutlets the storefront key's tenant offers
- get/v1/storefront/outlets/{outlet_id}/menuPublic menu with availability, deals and the effective accepting state
- get/v1/storefront/outlets/{outlet_id}/stateEffective accepting-orders state (open / busy +N / paused / closed) with next opening
- get/v1/storefront/outlets/{outlet_id}/pickup-windowsPickup windows with spare capacity
- post/v1/storefront/orders:previewPrice a cart (Preview; writes nothing) with tax rates, component amounts and refusal parameters; channel comes from the key
- post/v1/storefront/ordersGuest or signed-in checkout in one transaction; pay at the counter. A refusal's 409 / 422 body carries `params`
- get/v1/storefront/orders/{id}The shopper's own order (customer token or guest access token); anything else is 404
- post/v1/storefront/orders/{id}:cancelstorefront.order.cancel.v1 — inside the outlet's cancel window
- post/v1/storefront/orders/{id}:reschedule-previewRe-price the order at a new pickup time; writes nothing
- post/v1/storefront/orders/{id}:reschedulestorefront.order.reschedule.v1 — inside the outlet's reschedule window; deals re-priced (deal_rejudged carries old/new totals in `params`)
- get/v1/streamServer-sent events for the given topics (kds / order / inbox / trace); text/event-stream, read with the SDK's openStream; resume with Last-Event-ID; heartbeat every 20 s, closed at 55 min
- get/v1/storefront/pageThe live storefront page (theme and home page sections), or null for the built-in look
Customer account9
- get/v1/accountThe signed-in customer's profile at this merchant (404 before first sign-in here)
- post/v1/account:linkcustomers.account.link.v1 — first sign-in creates this merchant's profile; X-Munim-Guest-Token claims that guest order
- post/v1/account/profilecustomers.profile.update.v1 — name and phone
- post/v1/account/consentcustomers.consent.set.v1 — marketing consent
- get/v1/account/ordersThe customer's orders at this merchant, newest first
- get/v1/account/orders/{id}One of the customer's own orders with its lines (404 for any other order)
- get/v1/account/loyaltyLoyalty: latest balance_after and every entry
- post/v1/account:exportcustomers.data.export.v1 — JSON of the customer's own rows at this merchant
- post/v1/account:erasecustomers.erasure.request.v1 — anonymise the profile; orders are kept
Munim Cares network5
- get/v1/cares-network/citiesCities with surplus-sharing businesses (Simulated recipients; Check your local food-donation rules)
- get/v1/cares-network/listingsLive donation listings in a city to Simulated recipients
- get/v1/cares-network/listings/{id}One live donation listing (404 when not live)
- get/v1/cares-network/impactMeals shared across Munim to Simulated recipients: the latest published network snapshot, each value beside its ref
- get/v1/cares-network/snapshots/{id}A published network snapshot with its rows and sha256 (404 when unpublished)
Orders, shifts and pickup18
- post/v1/orders:previewPrice a cart with core's pricing function; writes nothing; labelled Preview (R40 C1)
- get/v1/ordersOrders in the caller's outlet scope, newest first; a shift's orders are those it took a tender for
- post/v1/ordersorders.place.v1 — core re-prices; client totals are ignored; a preview total that no longer holds is refused (preview_total_changed)
- get/v1/orders/{id}One order with its lines and tenders; paid and remaining computed by core in the same read
- get/v1/orders/{id}/receiptThe bill per the country pack (tax invoice, or a Sec 9(5) record-only receipt)
- post/v1/orders/{id}:acceptAccept a placed order
- post/v1/orders/{id}:rejectReject a placed order with a reason code; consumed stock, redeemed points and the pickup slot are given back
- post/v1/orders/{id}:advanceMove an order one step (preparing, ready, completed, or cancelled with a reason — refused while payments stand unrefunded); completion derives loyalty earn and the sale's journal entry
- post/v1/orders/{id}:push-backMove the promised time later with a reason code; deals are re-judged at the new time; refused once a payment is recorded
- post/v1/orders/{id}/tendersRecord a cash / card / UPI payment (recorded only — Munim does not process payments)
- post/v1/orders/{id}/voidsVoid a line, or the whole order (which cancels it; voids never exceed the total), with a reason; before any payment
- post/v1/orders/{id}/refundsRecord a refund with a reason, within what was paid and the member's authority
- get/v1/pickup-windowsAn outlet's pickup slots for a local calendar day, in time order, with capacity and booked
- post/v1/pickup-windowsCreate pickup slots for a business date (outlet-local times, DST-safe); existing slots are kept
- get/v1/shiftsDrawer shifts in the caller's outlet scope, newest first (from / to = the outlet's business day of the opening, local time less its business-day cutoff)
- post/v1/shiftsOpen a drawer shift with its float
- post/v1/shifts/{id}:closeClose a shift with the counted cash; core computes expected cash and variance
- get/v1/shifts/{id}One drawer shift: opening float and, once closed, counted cash, expected cash and variance (row fields)
Kitchen5
- get/v1/kitchen/boardLive tickets for an outlet (optionally one station) with elapsed/due and amber/red colour; restaurants and cloud kitchens only
- post/v1/kitchen/tickets/{id}:advancekitchen.ticket.advance.v1 — queued → preparing → ready → done; a stale from_status or an illegal move is 409
- post/v1/kitchen/prep-timeskitchen.prep_time.set.v1 — a manager's own expected prep time (closes the previous one)
- post/v1/kitchen/prep-listskitchen.prep_list.create.v1 — a manager's own prep list (intel's proposals arrive as drafts and wait for approval)
- get/v1/kitchen/prep-listWhether the outlet's prep list for a business date is approved, waiting for approval, absent, or cannot be verified
Catalogue and menu14
- get/v1/catalogue/itemsItems with their variants; inactive ones only with include_inactive=true
- post/v1/catalogue/itemscatalogue.item.upsert.v1 — create or update an item with its variants and option groups (owner/manager, all outlets)
- get/v1/catalogue/recipesRecipe versions with their lines, optionally of one item
- post/v1/catalogue/recipescatalogue.recipe.version.create.v1 — the next recipe version; closes the open one; an overlapping validity or a unit that is not the ingredient's base unit is refused
- get/v1/catalogue/pricesPrice rows in every validity window, future-dated included
- post/v1/catalogue/pricescatalogue.price.set.v1 — a price for an outlet and channel; closes the open one; an overlapping validity is refused
- get/v1/catalogue/dealsDeals visible to the caller's outlet scope (an empty outlet list = every outlet)
- post/v1/catalogue/dealscatalogue.deal.upsert.v1 — create or update a deal with its weekly windows (outlet time zone)
- get/v1/catalogue/couponsCoupons visible to the caller's outlet scope (an empty outlet list = every outlet)
- post/v1/catalogue/couponscatalogue.coupon.set.v1 — create a coupon or change its caps, end date or status
- post/v1/catalogue/deals/{id}:endcatalogue.deal.end.v1 — end a deal (payload deal_id must equal the path id)
- post/v1/catalogue/availabilitycatalogue.availability.set.v1 — mark an item sold out or back on sale at one outlet
- get/v1/catalogue/menuItems for sale at an outlet and channel now: price rows, options, sold-out state and deal badges
- get/v1/catalogue/barcodes/{code}Shop scan: the item or variant with this barcode and its price at the outlet; unknown code → 404
Inventory17
- get/v1/inventory/ingredientsIngredients (tenant-wide); q matches the name; outlet is checked against the caller's scope
- post/v1/inventory/ingredientsinventory.ingredient.upsert.v1 — create or edit an ingredient / stock record
- get/v1/inventory/wasteAn outlet's waste log; business_date = the outlet's local day less its business-day cutoff
- post/v1/inventory/wasteinventory.waste.record.v1 — log waste; core derives the waste movement
- get/v1/inventory/countsStock counts with their lines (expected beside counted), newest first
- post/v1/inventory/countsinventory.count.submit.v1 — a blind count; core derives count_adjust movements
- get/v1/inventory/counts/{id}One stock count with its lines
- get/v1/inventory/transfersTransfers visible from either end (outlet = from or to), with their lines
- post/v1/inventory/transfersinventory.transfer.create.v1 — send stock to another outlet (draftable); both ends in scope
- post/v1/inventory/stock:receiveinventory.stock.receive.v1 — opening stock, optionally into new dated batches
- get/v1/inventory/reorder-levelsMin / par levels at an outlet
- post/v1/inventory/reorder-levelsinventory.reorder_level.set.v1 — min / par for one ingredient at one outlet (draftable)
- post/v1/inventory/batches:updateinventory.batch.update.v1 — correct a batch's expiry or MRP
- post/v1/inventory/transfers/{id}:receiveinventory.transfer.receive.v1 — the receiving outlet books the stock in
- post/v1/inventory/expired-sale-overridesinventory.expired_sale.override.v1 — a manager or owner lets one cart line sell from one expired batch, where the country pack allows it
- get/v1/inventory/movementsStock movement rows for an outlet, newest first; kind and ref (the source row id) filter (T-092a)
- get/v1/inventory/batchesBatches at an outlet with expiry and MRP, earliest expiry first
Purchasing17
- get/v1/suppliersSuppliers; simulated ones carry the label "Simulated supplier"
- post/v1/supplierspurchasing.supplier.upsert.v1 — create or update a supplier (kind is fixed)
- get/v1/suppliers/{id}One supplier with its price observations
- get/v1/purchase-ordersPurchase orders touching the caller's outlets (a pooled PO shows to each listed outlet's managers)
- post/v1/purchase-orderspurchasing.po.create.v1 — commit a purchase order (single or pooled)
- get/v1/purchase-orders/{id}One purchase order with its lines
- get/v1/goods-receivedGoods received in the caller's outlets
- post/v1/goods-receivedpurchasing.grn.receive.v1 — receive goods (creates batches, stock movements and postings)
- get/v1/goods-received/{id}One goods-received note with its lines
- get/v1/supplier-invoicesSupplier invoices (not for staff)
- post/v1/supplier-invoicespurchasing.invoice.record.v1 — record an invoice; a repeated supplier + number is refused with 409
- get/v1/supplier-invoices/{id}One supplier invoice with its lines and derived payable
- post/v1/supplier-invoices/{id}:approvepurchasing.invoice.approve.v1 — approve a recorded invoice (owner); derives the payable
- post/v1/supplier-invoices/{id}:disputepurchasing.invoice.dispute.v1 — record a dispute for the owner to send
- get/v1/supplier-returnsSupplier returns in the caller's outlets
- post/v1/supplier-returnspurchasing.supplier_return.create.v1 — return stock to a supplier
- post/v1/rfq-requestspurchasing.rfq.request.v1 — ask the simulated suppliers to quote one ingredient for the chosen outlets; any purchase order comes back as a draft to approve
Finance13
- get/v1/finance/settlementsChannel settlements (owner, advisor, judge); from / to overlap the settlement period
- get/v1/finance/settlement-linesSettlement lines with commission, ad fee, promo share and tax withheld (owner, advisor, judge)
- get/v1/finance/bank-linesImported bank lines by value date (owner, advisor, judge)
- get/v1/finance/disputesRecorded disputes with channels and suppliers (owner, advisor, judge)
- post/v1/finance/disputesfinance.dispute.draft.v1 — record a channel dispute for the owner to send (also draftable)
- get/v1/finance/disputes/{id}One dispute with its claimed lines
- get/v1/finance/period-closesClosed periods with their checklist (owner, advisor, judge)
- post/v1/finance/period-closesfinance.period.close.v1 — close a month (also draftable); later entries dated in it are refused
- get/v1/finance/channel-termsRecorded channel terms (commission, ad consent and cap, validity), newest window first (owner, advisor, judge)
- post/v1/finance/channel-termsfinance.channel_terms.set.v1 — record agreed commission, ad and promo terms for a channel (owner)
- post/v1/finance/expensesfinance.expense.record.v1 — record an expense (posts it)
- post/v1/finance/budgetsfinance.budget.set.v1 — set a month's budget for one spending category, for one outlet or the whole business (owner)
- get/v1/finance/exports/tallyJournal vouchers for a date range as a Tally-importable CSV (owner, advisor, judge)
People17
- get/v1/people/rostersRosters with their shifts; week = the roster's Monday. A staff-role member gets only their own shifts
- post/v1/people/rostersCreate a week's roster (a person's own command)
- get/v1/people/attendanceClock-ins and outs; from / to = the outlet's business day (local time less its business-day cutoff). A staff-role member gets only their own
- post/v1/people/attendanceClock a staff member in or out
- get/v1/people/advancesSalary advances given and recovered (not for staff-role members)
- post/v1/people/advancesRecord an advance given or recovered
- get/v1/people/payroll-draftsApproved payroll drafts with their lines; month = the 1st (not for staff-role members)
- post/v1/people/payroll-draftsRecord an approved payroll draft (IN only)
- post/v1/people/staff:upsertCreate or update a staff record
- post/v1/people/rosters:updateEdit or cancel a roster
- post/v1/people/payroll-drafts/{id}:statusMark an approved payroll paid outside Munim, or void it with a reason (reverses its journal entry; owner)
- post/v1/people/tip-poolsRecord a tip pool and its shares
- post/v1/people/trainingRecord a training completion
- post/v1/people/candidates:upsertCreate or move a hiring candidate
- get/v1/people/overtimeOvertime against the roster, per staff per ISO week
- get/v1/people/payroll-previewProposed payroll lines for a month (IN only)
- get/v1/people/staffStaff of an outlet with their pay terms (not for staff-role members)
Customers and growth15
- get/v1/customers/{id}One merchant-side customer record (owner/manager/staff/judge; staff see a masked phone and no email)
- get/v1/customersSearch merchant-side customer records (owner/manager/staff/judge; staff see masked contacts)
- post/v1/customers:upsertcustomers.customer.upsert.v1 — create or edit a customer record; consent can only be withdrawn
- get/v1/customers/{id}/loyaltyLoyalty balance (latest balance_after) and ledger entries
- get/v1/customers/{id}/coupon-usesCoupon use history of one customer
- post/v1/loyalty:adjustcustomers.loyalty.adjust.v1 — append an adjustment entry (never below zero)
- get/v1/campaignsQueued, cancelled and (demo) recorded-as-sent campaigns (created only by an approved draft; never sent by Munim)
- post/v1/campaigns:cancelcustomers.campaign.cancel.v1 — cancel a queued campaign
- post/v1/campaigns:record-sentcustomers.campaign.record_sent.v1 — on a demo business, record a queued campaign as sent (simulated: no message leaves Munim; owner)
- get/v1/reservationsReservations
- post/v1/reservations:upsertcustomers.reservation.upsert.v1
- get/v1/reviewsImported or hand-entered reviews
- post/v1/reviews:recordcustomers.review.record.v1 — enter a review (append-only)
- get/v1/bulk-ordersBulk / catering enquiries and orders
- post/v1/bulk-orders:upsertcustomers.bulk_order.upsert.v1
Compliance and assets16
- get/v1/compliance/licencesLicences (active by default), tenant-wide and in the caller's outlets
- post/v1/compliance/licencescompliance.licence.upsert.v1 — record or renew a licence
- get/v1/compliance/licences/expiringActive licences expiring within N days of as_of (outlet-local date)
- get/v1/compliance/assetsAssets in the caller's outlets
- post/v1/compliance/assetscompliance.asset.upsert.v1 — add or change an asset
- get/v1/compliance/checklistsChecklists
- post/v1/compliance/checklistscompliance.checklist.upsert.v1 — add or change a checklist
- get/v1/compliance/checklist-runsCompleted checklist runs, newest first
- post/v1/compliance/checklist-runscompliance.checklist.complete.v1 — complete a checklist for a business date
- get/v1/compliance/temp-logsTemperature readings with the asset's own range applied
- post/v1/compliance/temp-logscompliance.temp.record.v1 — record a temperature reading (evidence, not a certificate)
- get/v1/compliance/amcsAnnual maintenance contracts
- post/v1/compliance/amcscompliance.amc.record.v1 — record an AMC
- get/v1/compliance/maintenanceMaintenance rows
- post/v1/compliance/maintenancecompliance.maintenance.schedule.v1 — schedule maintenance (intel may draft it)
- post/v1/compliance/maintenance/recordcompliance.maintenance.record.v1 — record maintenance done
Munim Cares (business)17
- get/v1/cares/profileThe business's Munim Cares setup: availability, operator enablement, profile and outlet cities
- post/v1/cares/profilecares.profile.set.v1 — opt in or pause, name the business, set each outlet's city, location and pickup hours
- get/v1/cares/recipientsSimulated recipients in the outlet's city
- get/v1/cares/listingsSurplus listings and their hand-overs, newest first
- post/v1/cares/listingscares.listing.publish.v1 — publish a donation or an offer (owner or judge; intel may draft it, cooked lines only by the owner's own command)
- get/v1/cares/listings/{id}One listing with its lines and hand-overs
- post/v1/cares/listings/{id}:withdrawcares.listing.withdraw.v1 — withdraw a published listing (not after an offer is allocated)
- post/v1/cares/handoverscares.handover.record.v1 — record what was handed over; core derives the stock movements
- post/v1/cares/handovers/{id}:voidcares.handover.void.v1 — void a recorded hand-over with a reason; stock comes back (not after the buyer received)
- get/v1/cares/marketOther businesses' shared surplus offers in the caller's cities (needs B2B on)
- get/v1/cares/claimsThe buyer's own claims with their outcome
- post/v1/cares/claimscares.claim.create.v1 — claim every line of an offer at the offered quantity (all-or-nothing); the price is recorded, never processed
- post/v1/cares/claims/{id}:cancelcares.claim.cancel.v1 — cancel a claim before any verdict
- post/v1/cares/claims/{id}:closecares.claim.close.v1 — close a claim whose outcome is declined
- post/v1/cares/claims/{id}:receivecares.claim.receive.v1 — receive an accepted, handed-over claim into stock
- get/v1/cares/listings/{id}/claimsClaims on the caller's own offer
- post/v1/cares/listings/{id}:decidecares.claim.decide.v1 — accept or decline one claim on the caller's offer (one accepted claim per offer)
Ask, threads and evidence19
- post/v1/findings/{id}:dismissfindings.dismiss.v1 — dismiss an open finding with a reason code (payload finding_id must equal the path id)
- get/v1/conversationsConversations in the caller's outlet scope (handovers, supplier and imported chats); a conversation with no outlet is tenant-wide
- get/v1/conversations/{id}/messagesA conversation's messages, oldest first; bodies are untrusted text
- get/v1/wiki/pagesWiki pages, newest first
- get/v1/wiki/pages/{id}One wiki page with its current body (refs unresolved)
- get/v1/wiki/pages/{id}/versionsA page's versions with their bodies, newest first
- get/v1/findingsFindings in the caller's outlet scope; pack = the specialist (T-092a)
- get/v1/inboxFindings and drafts awaiting a person
- post/v1/snapshotsA member mints an allow-listed template snapshot (R40 C4); scope from the member token
- get/v1/snapshots/{id}Open the rows behind a ref
- get/v1/runs/{id}A run by id
- get/v1/runsRuns in the caller's scope, newest first; ?finding= gives the run that produced it
- get/v1/traces/{run}Trace events of a run, in seq order
- get/v1/lineageLineage of one book row via core.audit_log (row=<schema>.<table>:<uuid>); a row outside the caller's scope is 404
- get/v1/specialistsThe team: the eight specialists and the Manager, with what each owns
- get/v1/specialists/{id}A specialist's desk: findings, drafts, track record (snapshot refs), threads
- post/v1/askAsk the Manager, or a specialist by a leading @Name; appends a turn to a thread (new or given)
- get/v1/threadsThreads in the caller's outlet scope; ?specialist= those addressed to that desk
- get/v1/threads/{id}A thread with its turns, answers and rolling cited summary
Investigations6
- get/v1/investigationsInvestigations in the caller's outlet scope, most recently changed first; ?status= one status
- post/v1/investigationsOpen an investigation (Step or Plan mode, within the role's ceiling) for a playbook over the caller's outlet scope; the client's id is its idempotency key
- get/v1/investigations/{id}An investigation with its checklist, steps and narrations (404 outside the caller's outlet scope)
- post/v1/investigations/{id}:continueRun exactly the named next step: mint, judge in code, store, narrate
- post/v1/investigations/{id}:cancelCancel an open or waiting investigation (its creator); a repeat is a replay, a later :continue is 409
- post/v1/investigations/{id}:approve-planApprove a Plan-mode investigation (its creator, within the role's ceiling), as Plan or Auto, and run its steps inside this request until a stop
Drafts and approvals6
- get/v1/draftsDrafts in the caller's outlet scope (status: proposed (default) | executing | executed | failed | rejected | stale | decided)
- get/v1/drafts/{id}One draft with its decision and history
- post/v1/drafts/{id}:approvedrafts.approve.v1 — approve as proposed or edited (payload draft_id must equal the path id)
- post/v1/drafts/{id}:rejectdrafts.reject.v1 — reject with a reason (payload draft_id must equal the path id)
- get/v1/drafts/{id}/lineageA draft up (finding, run, snapshots) and down (decision, touched rows), including rejected, stale and failed ones
- get/v1/draftablesThe draftable command types, for forms and the SDK
Goals and tasks6
- get/v1/goalsGoals in the caller's outlets and the tenant-wide ones
- post/v1/goalsgoals.goal.create.v1 — set a goal (intel may draft it)
- post/v1/goals/updategoals.goal.update.v1 — close a goal as achieved, missed or cancelled
- get/v1/tasksTasks in the caller's outlets and the tenant-wide ones
- post/v1/tasksgoals.task.create.v1 — assign a task (intel may draft it)
- post/v1/tasks/updategoals.task.update.v1 — close or reassign a task
Imports6
- post/v1/imports/documentsUpload a file (sha256 unique per tenant: the same file again returns the existing document); a recognised format starts a run
- get/v1/imports/runsImport runs, newest first; kind and status filter, cursor = the last run's id (T-092a)
- post/v1/imports/runsStart a run for an uploaded document whose format is now known (after its mapping was approved)
- get/v1/imports/runs/{id}One import run (status, rows ready, rows quarantined, the file's total)
- get/v1/imports/runs/{id}/rowsStaged rows and quarantined rows (with reasons) of one run
- post/v1/imports/formats:proposePropose a column mapping (renames + units only) for a document's layout, as a draft to approve
Business setup and members31
- get/v1/ai/policyPer-role investigation-mode ceilings and the owner's monthly AI cap
- post/v1/ai/policy/ceilingai_policy.ceiling.set.v1 — set the highest investigation mode a role may pick (owner only)
- post/v1/ai/policy/capai_policy.cap.set.v1 — set the monthly AI spend cap, never above the operator's limit (owner only)
- get/v1/storefront-pagesThe storefront page's saved versions and the live one
- post/v1/storefront-pagesstorefront.page.save.v1 — save the next version of the storefront page (owner; all-outlet manager)
- get/v1/storefront-pages/{id}One saved version of the storefront page with its theme and sections
- post/v1/storefront-pages/{id}:publishstorefront.page.publish.v1 — put a saved version live; an older one restores it (owner)
- get/v1/outlets/{id}/calendarAn outlet's weekly hours and dated overrides (holidays), in the outlet's own zone; an outlet outside the caller's scope is 404
- get/v1/outletsOutlets in the caller's scope
- post/v1/outletstenancy.outlet.create.v1 — add an outlet (owner)
- post/v1/outlets/{id}:updatetenancy.outlet.update.v1 — outlet settings (owner; manager of that outlet)
- get/v1/brandsBrands
- post/v1/brandstenancy.brand.create.v1 — add a brand (owner)
- get/v1/channelsSales channels
- post/v1/channelstenancy.channel.create.v1 — add a sales channel (owner)
- get/v1/devicesPOS and KDS devices
- post/v1/devicestenancy.device.register.v1 — register a POS or KDS device (owner; manager of that outlet)
- post/v1/members:invitetenancy.member.invite.v1 — invite a member by email (owner)
- post/v1/tenant:updatetenancy.tenant.update.v1 — business settings; country is locked after onboarding (R30)
- post/v1/policytenancy.policy.set.v1 — the owner's labour and margin targets, as a new dated version (owner)
- get/v1/storefront-keysStorefront keys (no key material)
- post/v1/storefront-keysCreate a storefront key; the raw key is returned once (owner)
- post/v1/onboardingtenancy.onboard.v1 — a signed-in person with no tenant creates one: tenant, first outlet, owner membership, pack defaults. The owner's email is the verified IdP email; the same envelope twice makes one tenant
- get/v1/me/tenantsWhere this sign-in is an active member
- post/v1/members:bindtenancy.member.bind.v1 — the invitee's first sign-in binds the IdP subject to the invited member, once. Tenant from the invite link (X-Munim-Tenant); the email must match the invite AND be verified by the IdP, else 404
- get/v1/meThe caller's own member id, name, role and outlet scope in this tenant (read-only)
- get/v1/tenantThe business's settings row
- get/v1/membersMembers and their roles (owner only)
- post/v1/members/{id}:set-roletenancy.member.role.set.v1 — change another member's role and outlet scope (owner)
- post/v1/members/{id}:deactivatetenancy.member.deactivate.v1 — deactivate another member; their sign-in stops resolving, their records stay (owner)
- post/v1/storefront-keys/{id}:revokeRevoke a storefront key; it stops resolving at once (owner)
Platform operator19
- get/platform/v1/network-snapshotsMinted network snapshots with their publish state
- post/platform/v1/network-snapshotsMint the network impact snapshot (operator template platform.cares_network_impact); nothing is public until a config draft publishes it
- get/platform/v1/budgets/{tenant}/spendA tenant's monthly AI budget and spend rows for one UTC month (default the current), newest first; operator only
- get/platform/v1/tenantsTenants from platform.tenant_registry (no tenant business data)
- get/platform/v1/country-packsCountry pack versions
- get/platform/v1/country-packs/{code}/{version}One country pack version with its document
- get/platform/v1/plansPlans and limits
- get/platform/v1/feature-flagsFeature flags (intel.enabled is the AI kill switch)
- get/platform/v1/budgetsPer-tenant monthly AI budgets with spent from platform.llm_budget_spent
- get/platform/v1/model-rolesProvider + model per role (R36)
- get/platform/v1/operatorsOperators
- get/platform/v1/config-draftsConfig drafts (status: proposed (default) | applied | rejected | stale | all)
- post/platform/v1/config-draftsPropose a platform config change (nothing applies until approved)
- get/platform/v1/config-drafts/{id}One config draft (404 for an unknown id)
- post/platform/v1/config-drafts/{id}:approveApprove and apply a config draft (an operator's own command is its approval, R27)
- post/platform/v1/config-drafts/{id}:rejectReject a config draft with a reason
- post/platform/v1/snapshotsMint an operator snapshot of an operator-level template (R40 C4)
- post/platform/v1/tenants:provisiontenancy.provision.v1 — operator provisions a tenant (03-architecture §1.9)
- post/platform/v1/demo-sessionsdemo.session.start.v1 — operator starts an ephemeral judge session on a fresh demo tenant