13 KiB
Backend API Requirements — Merchant Web Console
Audience: Backend team.
Purpose: These are the endpoints the merchant web app needs before it can go to staging with
zero mock data. Every UI spot listed below currently renders an explicit
Awaiting backend API [Rxx] placeholder (or a known-wrong stand-in like the
delivered × 355 revenue) until the matching endpoint ships.
Conventions (match the existing live API)
- Base / proxy: Fiesta REST at
https://fiesta.nearle.app/live/api/v1/web/<group>/<action>. The frontend calls it through the dev proxy as/fiesta/live/api/v1/web/.... - Auth: same as current read endpoints (no extra header required for GETs).
- Envelope: every response is
{ "code": 200, "status": true, "message": "OK", "details": <payload> }detailsis the documented payload (array or object). On failure return{ "code": 4xx, "status": false, "message": "<reason>" }. - Types: money = INR as a plain 2-dp number (e.g.
442800.00), no currency symbol/string. Dates =YYYY-MM-DD. Timestamps = ISO-8601 (2026-06-06T14:21:00). Ids = integers. - Tenant scope (current):
tenantid=1087,applocationid=1, primarylocationid=1097. - Paging: where listed, accept
pageno(1-based) andpagesize.
Index
| Id | Endpoint | Method | Powers (UI) | Priority |
|---|---|---|---|---|
| [R1] | /orders/getrevenuesummary |
GET | Revenue KPIs, OTIF, leaderboard, fulfilment health | P0 |
| [R2] | /orders/gettimeseries |
GET | Reports main chart, 7-day ledger | P0 |
| [R3] | /products/getproductanalytics |
GET | Product matrix sales + per-product detail | P0 |
| [R4] | /imports/getimportlogs (+ /imports/upload) |
GET/POST | Import audit stream + validator | P1 |
| [R5] | /products/getcatalogpresets |
GET | Inventory catalog presets (optional) | P2 |
| [R6] | /tenants/getsettings (+ /tenants/updatesettings) |
GET/PUT | Settings + Brand studio | P1 |
| [R7] | /insights/getforecast |
GET | Operations forecast tiles (optional) | P2 |
| [R8] | /products/stocktransfer |
POST | Operations stock-transfer modal | P1 |
| [R9] | /partners/getridertelemetry |
GET | Fleet rating, GPS, ETA | P1 |
| [R10] | /deliveries/getdispatchbuckets |
GET | StoreDetail intraday dispatch | P1 |
| [R11] | /customers/getcustomeranalytics |
GET | Customer CSAT/AOV/retention | P1 |
| [R12] | /alerts/getalerts |
GET | Operational alerts feed | P1 |
| [R13] | /reports/getschedules (+ POST) |
GET/POST | Scheduled reports (optional) | P2 |
Plus mutation routes already named in the endpoint sheet but not yet shape-documented — see the last section.
[R1] Revenue summary · GET /orders/getrevenuesummary
Real money totals. Today the app fakes revenue as delivered × 355 — replace that.
Request (query params)
| param | type | required | notes |
|---|---|---|---|
tenantid |
int | ✓ | |
locationid |
int | omit → all outlets (overall); set → store-wise | |
fromdate |
date | ✓ | |
todate |
date | ✓ |
Response details (single object)
{
"tenantid": 1087,
"locationid": null,
"grossrevenue": 1248302.00,
"netrevenue": 1180500.00,
"profit": 354216.00,
"marginpct": 28.4,
"ordercount": 4921,
"deliveredcount": 4102,
"cancelledcount": 142,
"otifpct": 98.2,
"avgordervalue": 1580.00,
"prev_grossrevenue": 1090000.00,
"prev_ordercount": 4370
}
prev_* = same metric for the immediately preceding equal-length window (lets the UI show
+14.2% deltas without a second call). otifpct powers the OTIF / fulfilment-health tiles.
Frontend hook to add: useFiestaRevenueSummary.
[R2] Orders / revenue time-series · GET /orders/gettimeseries
Powers the Reports main chart (Orders / Revenue / Cancelled / SKUs) and StoreDetail 7-day ledger.
Request
| param | type | required | notes |
|---|---|---|---|
tenantid |
int | ✓ | |
locationid |
int | omit → overall | |
granularity |
enum | ✓ | day | month | year |
fromdate |
date | ✓ | |
todate |
date | ✓ |
Response details (array, one bucket per period)
[
{ "label": "2026-06-01", "orders": 312, "revenue": 442800.00,
"delivered": 298, "cancelled": 9, "activeskus": 72 }
]
label = YYYY-MM-DD (day), YYYY-MM (month), or YYYY (year). Removes all hardcoded chart
arrays and the region-scaling multipliers (filter by locationid instead).
Frontend hook: useFiestaTimeSeries.
[R3] Product sales analytics · GET /products/getproductanalytics
True units-sold + revenue per product, plus the per-product/per-outlet detail the matrix expands.
Request
| param | type | required | notes |
|---|---|---|---|
tenantid |
int | ✓ | |
locationid |
int | omit → across all outlets | |
subcategoryid |
int | ||
fromdate / todate |
date | sales window (default month-to-date) | |
keyword |
string | ||
pageno / pagesize |
int |
Response details (array)
[
{ "productid": 88231, "productname": "Ponni Raw Rice 10kg",
"sku": "PONNI-RICE-10K", "categoryid": 2, "subcategoryname": "Rice",
"image": "https://…",
"unitssold": 12402, "revenue": 868140.00, "trend": "up",
"closingstock": 1402, "maxcapacity": 2000,
"binlocation": "BIN-C12", "lastauditdate": "2026-06-05", "verified": true,
"outlets": [ { "locationid": 1097, "locationname": "RS Puram", "stock": 840 } ] }
]
trend ∈ up|flat|down. outlets[] = real per-hub split (replaces hardcoded 60/40).
If the catalog doesn't track binlocation/lastauditdate, return null — the UI will hide them
rather than fake them. Frontend hook: useFiestaProductAnalytics.
[R4] Import / sync audit log · GET /imports/getimportlogs + POST /imports/upload
Replaces the mock "Live Sync Audit Stream" and the hardcoded "14 duplicate SKUs" validator.
GET request: tenantid (✓), pageno, pagesize.
GET details
[
{ "importid": 921, "batchref": "#IMP_0921_A", "type": "Inventory Sync",
"source": "ERP Export", "rows": 421, "result": "SUCCESS",
"message": "421 rows imported", "createdat": "2026-05-31T09:12:00" }
]
result ∈ SUCCESS|FAILED|PARTIAL.
POST /imports/upload (multipart, field file = CSV; plus tenantid) → returns the new log row
plus a validation block:
{ "importid": 922, "result": "PARTIAL",
"validation": { "passed": false, "duplicateskus": ["ST-SONA-25K"],
"badcolumns": [45, 82], "headerversion": "v2.8" } }
Frontend hooks: useFiestaImportLogs, useFiestaImportUpload (mutation).
[R5] Catalog presets (optional) · GET /products/getcatalogpresets
Inventory "Nilgiris Dairy / Coimbatore Heritage" quick-add packs.
Request: tenantid (✓). details:
[ { "presetid": 3, "name": "Nilgiris Dairy Fresh Pack",
"items": [ { "name": "Ooty Butter 500g", "sku": "DY-OOT-BTR",
"subcategoryname": "Dairy", "price": 340, "image": "https://…" } ] } ]
Alternative: skip this and reuse master catalog (
/products/getproducts) filtered by subcategory.
[R6] Merchant settings + branding · GET /tenants/getsettings + PUT /tenants/updatesettings
Replaces the localStorage DEFAULTS and the Brand Design Studio local state.
GET request: tenantid (✓). GET details:
{
"tenantid": 1087,
"contactemail": "ops@ragul.com", "contactphone": "+91…",
"minordervalue": 199, "deliverycharge": 29, "prepmins": 20,
"deliverywindowmins": 45, "cancelwindowsecs": 120, "autoassignrider": true,
"defaulttaxpercent": 5, "codenabled": true, "onlinepaymentenabled": true,
"defaultregion": "Coimbatore", "defaultnewuserrole": 4,
"ordernotifications": true, "lowstockalerts": true, "dailysummaryemail": false,
"syncinterval": 15, "sandboxmode": false,
"branding": { "themename": "Kaveri Org", "primarycolor": "#16a34a",
"secondarycolor": "#f59e0b", "baglabel": "Freshly Harvested",
"ecoverified": true, "stickerpattern": "radial" }
}
PUT body: same object (partial allowed) → returns the updated object.
Frontend hooks: useFiestaSettings, useFiestaUpdateSettings (mutation).
[R7] Forecast insight (optional) · GET /insights/getforecast
Operations "Forecast Efficiency 92% / ₹1.9L savings". Recommend dropping the tiles until a model
exists; if kept: request tenantid (✓), locationid (opt). details:
{ "forecastefficiencypct": 92, "estsavingsperweek": 190000.00, "horizondays": 7 }
[R8] Stock transfer · POST /products/stocktransfer
Operations transfer-stock modal. Body:
{ "tenantid": 1087, "productid": 88231,
"fromlocationid": 1097, "tolocationid": 1101, "quantity": 100 }
details: updated stock rows for both locations
[ { "locationid": 1097, "productid": 88231, "closingstock": 740 },
{ "locationid": 1101, "productid": 88231, "closingstock": 360 } ]
[R9] Rider telemetry · GET /partners/getridertelemetry
Replaces hardcoded rider rating, battery, lastPing and the fake GPS route / "9 MINS" / "1.2 km".
Request: applocationid (✓), tenantid (opt), userid (opt → single rider).
details (array)
[
{ "userid": 7781, "name": "Karthikeyan R", "status": "Delivering",
"rating": 4.7, "completedtoday": 12, "battery": 84,
"lastping": "2026-06-06T14:21:00", "zone": "RS Puram",
"lat": 11.0041, "lng": 76.9612,
"activedelivery": { "deliveryid": 99213, "etamins": 9, "distancekm": 1.2,
"destlat": 11.0102, "destlng": 76.9550 } }
]
status ∈ Delivering|Idle|Offline. activedelivery = null when the rider is idle.
Frontend hook: useFiestaRiderTelemetry.
[R10] Intraday dispatch buckets · GET /deliveries/getdispatchbuckets
Replaces StoreDetail intervalSlots (Morning Rush / Midday / Evening Peak computed from %).
Request: tenantid (✓), locationid (✓), date (✓, default today).
details (array, fixed buckets)
[ { "bucket": "06:00-10:00", "label": "Morning Rush",
"orders": 64, "revenue": 88400.00, "status": "PEAK" } ]
status ∈ PEAK|HIGH|NORMAL|LOW. Frontend hook: useFiestaDispatchBuckets.
[R11] Customer analytics · GET /customers/getcustomeranalytics
Replaces hardcoded CSAT 5.0 / retention 88.4% / AOV ₹1,580.
Request: tenantid (✓), locationid (opt), customerid (opt → single-customer rollup).
details (object)
{
"retentionpct": 88.4, "avgordervalue": 1580.00, "csat": 4.9,
"totalcustomers": 1240,
"percustomer": { "customerid": 55012, "orderscount": 18,
"totalspent": 28450.00, "csat": 5.0, "lastorderdate": "2026-06-04" }
}
percustomer present only when customerid is supplied.
Customer order history itself already exists:
GET /orders/getorders?customerid=— wire that, no new API. Frontend hook:useFiestaCustomerAnalytics.
[R12] Operational alerts · GET /alerts/getalerts
Replaces the mock operationalAlerts (stock-critical, latency, rebalance…).
Request: tenantid (✓), locationid (opt), status (open|all), pageno, pagesize.
details (array)
[ { "alertid": 5012, "tenantid": 1087, "locationid": 1097,
"type": "critical", "title": "Stock Critical: RS Puram",
"details": "Dairy inventory below 5%.",
"createdat": "2026-06-06T08:24:00", "acknowledged": false } ]
type ∈ critical|warning|info. Frontend hook: useFiestaAlerts.
[R13] Scheduled reports (optional) · GET /reports/getschedules + POST /reports/createschedule
Replaces 3 hardcoded calendar events. Drop if not on the roadmap.
GET details:
[ { "scheduleid": 11, "name": "Monthly Assortment Audit", "cron": "0 0 1 * *",
"nextrun": "2026-07-01T00:00:00", "format": "PDF", "recipients": ["ops@ragul.com"] } ]
POST body: { tenantid, name, cron, format, recipients[] } → returns the created schedule.
Mutation routes already named in the endpoint sheet (publish request/response, then we wire)
These are marked REVIEW_REQUIRED in Fiesta_All_Endpoints_With_Tables_And_Params.xlsx. We need
the exact request body + success response for each:
| Action | Suggested endpoint | Body (fields we'll send) |
|---|---|---|
| Create web order | POST /orders/create |
tenantid, locationid, customerid, items[{productid,qty,price}], paymenttype |
| Update order status | PUT /orders/updatestatus |
orderheaderid, status, financialflag |
| Assign rider / dispatch | POST /deliveries/assign |
orderheaderid, tenantid, locationid, partnerid, userid |
| Update pickup / delivered | PUT /deliveries/updatestatus |
deliveryid, status |
| Add multi-product stock | POST /products/addstock |
tenantid, locationid, items[{productid,qty,cost}] |
| Create / update / delete product | POST/PUT/DELETE /products/... |
product fields |
| Onboard tenant / store / location | POST /tenants/onboard, POST /tenants/createlocation |
tenant + location fields |
Frontend status (for reference)
- All read endpoints that already exist are wired (orders/deliveries/stock/customers/users/ locations/order-line-items/etc.).
- Each
[Rxx]above corresponds to a visibleAwaitingApiplaceholder in the UI, so QA can see exactly which screens are still blocked. - The moment an endpoint here ships with the documented shape, wiring it is one hook + swapping the placeholder — no redesign needed.