{"service":"shopdesk","version":"1.0.0","generatedAt":"2026-04-08T07:29:26.560Z","dashboardOverview":{"title":"Dashboard overview","intro":"Cross-cutting KPIs (orders, revenue, customers, stock, commission, etc.), admin wallets, and distance from the configured store location (miles, km, meters).","wallet":"Wallet: GET /api/admin/wallet/me, GET /api/admin/wallet/me/transactions (ledger; use GET /api/admin/wallet/:userId/transactions for another staff id with wallet.read or Super Admin).","walletActivity":"Wallet activity: history of credits and debits (Super Admin adjustments). GET /api/admin/wallet/me/transactions (same as GET /api/admin/wallet/:userId/transactions with :userId = me or a numeric staff id).","adjust":"Adjust: POST /api/admin/wallet/adjust (Super Admin) — writes balance and a ledger row.","walletAdjustUi":"Adjust another admin wallet: Super Admin only — credit or debit another staff member’s USD wallet and write a ledger row. POST /api/admin/wallet/adjust with JSON userId, amountUSD, and optional note.","geo":"Geo: public GET /api/geo/store; distance GET /api/geo/distance?lat=&lng= or POST /api/geo/distance with JSON lat & lng (or latitude / longitude). Store origin: GET /api/admin/store-geo (platform.read), PUT /api/admin/store-geo (shop_profile_editor: Super Admin or Operations Admin).","geoDistanceExample":"Distance from store: 4084.239 mi · 6572.946 km (example). Preview uses rounded strings so decimals match the summary. GET /api/geo/distance returns the same distances as JSON numbers (not strings). Store and client latitude/longitude are JSON numbers in the API response; the admin live JSON preview formats them as rounded strings for display."},"auditTrail":{"title":"Audit trail","intro":"Who changed commission, created admins, approved vendors, updated orders, adjusted stock, edited catalog overlays, payment methods, and more.","api":"API: GET /api/admin/audit-log (audit.read) with optional limit, action, actionPrefix.","export":"Export: GET /api/admin/audit-log/export (audit.export), query format=json or ndjson.","actorEmail":"Actor email: each entry includes actorEmail when the server can resolve it (staff user row, JWT email on new logs, auth rows, optional data/audit-actor-email-overrides.json for legacy actorUserId values). metadata.actorEmail is not returned on the API (top-level only)."},"stockManagement":{"title":"Stock management","intro":"Real-time inventory for the catalogue. Only numeric stock counts are tracked; the em dash (—) means unlimited / not tracked (no checkout cap, no automatic deduction).","checkout":"Checkout: Paid storefront orders subtract line quantities from tracked SKUs (never below zero).","threshold":"Threshold: The number below is only for alerts and KPI cards on this screen — it does not change how customers buy.","permissions":"Permissions: View summary needs inventory.read; adjust buttons need inventory.adjust (see Roles & permissions).","apis":"List / KPIs: GET /api/admin/inventory/summary?threshold= (inventory.read). Adjust: PATCH /api/admin/inventory/products/:id/stock (inventory.adjust) with { \"delta\": number } (tracked stock only), { \"stock\": number }, or { \"stock\": \"—\" } for unlimited.","adminHtml":{"intro":"<p style=\"margin:0 0 .65rem;font-size:.92rem;line-height:1.55;color:#1a1d27\">Real-time inventory for the catalogue. Only <strong>numeric</strong> stock counts are tracked; the em dash (<code>—</code>) means <strong>unlimited / not tracked</strong> (no checkout cap, no automatic deduction).</p>","bullets":"<ul style=\"margin:0 0 .65rem 1.15rem;padding:0;font-size:.85rem;color:#3d4a5c;line-height:1.55\"><li><strong>Checkout:</strong> Paid storefront orders subtract line quantities from tracked SKUs (never below zero).</li><li><strong>Threshold:</strong> The number below is only for <em>alerts and KPI cards</em> on this screen — it does not change how customers buy.</li><li><strong>Permissions:</strong> View summary needs <code>inventory.read</code>; adjust buttons need <code>inventory.adjust</code> (see Roles &amp; permissions).</li></ul>","apis":"<details class=\"dash-stock-api-details\"><summary class=\"dash-stock-api-summary\">API reference</summary><div class=\"dash-stock-api-body\"><p class=\"dash-stock-api-p\"><strong>List / KPIs:</strong> <code>GET /api/admin/inventory/summary?threshold=</code> (<code>inventory.read</code>).</p><p class=\"dash-stock-api-p dash-stock-api-p--adjust\"><strong>Adjust:</strong> <code>PATCH /api/admin/inventory/products/:id/stock</code> (<code>inventory.adjust</code>) with <code>{ \"delta\": number }</code> (tracked stock only), <code>{ \"stock\": number }</code>, or <code>{ \"stock\": \"—\" }</code> for unlimited.</p></div></details>"}},"catalogAndPayments":{"title":"Catalog & payments","intro":"Manage the merged storefront category tree (built-in seed + your overlay) and checkout payment methods.","categoryOverlays":"Category overlays: catalog.read to view; catalog.write to add or remove overlay rows via the admin API.","paymentMethods":"Payment methods: payments.read to view; payments.write to edit or reset the payment-method catalogue (not the category tree).","publicCategories":"The merged category JSON is public: GET /api/categories — same payload as /api/public/categories and /shopdesk/categories."},"vendorManagement":{"title":"Vendor management","intro":"Register a vendor record (KYC starts as pending).","apis":"POST /api/admin/vendors (vendors.write) registers a vendor. Pending KYC: GET /api/vendor/pending-verification (vendors.read). Approve/reject/suspend: vendors.approve (see Compliance center and endpoint list)."},"assignRoleByUserId":{"title":"Assign role by user ID","intro":"Super Admin only — sets adminRole for an existing staff account (same users as Admin management).","api":"PUT /api/admin/assign-role with JSON userId and adminRole (slug from the role list). Bearer: Super Admin JWT."},"adminApiReference":{"title":"Admin API reference","intro":"Live table: Method, Path, RBAC, Summary — same rows as adminApiEndpoints on GET /api/catalog.","rbacJwt":"jwt — any signed-in user","rbacAnyAdmin":"any_admin — admin JWT with no extra permission check","rbacSuperAdmin":"super_admin — Super Admin only","rbacOther":"Any other value — permission key, enforced with the same rules as the gateway","fallback":"If adminApiEndpoints is missing or empty from GET /api/admin/roles, the matrix is loaded from public GET /api/catalog (same adminApiEndpoints array), then from /admin-api-rbac.json.","regenerateStaticFile":"node -e \"const a=require('./lib/apiCatalog');require('fs').writeFileSync('public/admin-api-rbac.json',JSON.stringify({adminApiEndpoints:a.getAdminRbacEndpoints(),rbacLegend:a.RBAC_LABELS},null,2))\""},"auth":{"bearer":"Authorization: Bearer <JWT from /api/auth/login>","bearer_admin":"JWT with role=admin","bearer_super_admin":"JWT with role=admin and adminRole=super_admin"},"rbacLegend":{"jwt":"JWT (any signed-in user)","any_admin":"Admin JWT (role=admin; no permission key)","super_admin":"Super Admin only (adminRole=super_admin)","shop_profile_editor":"shop_profile_editor · Super Admin or Operations Admin"},"adminApiEndpoints":[{"method":"POST","path":"/api/admin/access-request","summary":"Submit operator/platform access request for Super Admin review","rbac":"any_admin","rbacLabel":"Admin JWT (role=admin; no permission key)","tags":["admin","access"]},{"method":"POST","path":"/api/admin/access-request/:id/decision","summary":"Approve or reject a pending access request","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","access"]},{"method":"PUT","path":"/api/admin/assign-role","summary":"Assign adminRole by userId","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin"]},{"method":"GET","path":"/api/admin/audit-log","summary":"List audit entries + actorEmail enrichment + action catalog (see getCatalog().auditTrail, auditTrail.actorEmail)","rbac":"audit.read","rbacLabel":"audit.read","tags":["audit"]},{"method":"GET","path":"/api/admin/audit-log/export","summary":"Export audit entries with same actorEmail rules as list (format=json|ndjson; see getCatalog().auditTrail.actorEmail)","rbac":"audit.export","rbacLabel":"audit.export","tags":["audit"]},{"method":"DELETE","path":"/api/admin/catalog-categories","summary":"Delete overlay (?name=)","rbac":"catalog.write","rbacLabel":"catalog.write","tags":["catalog"]},{"method":"GET","path":"/api/admin/catalog-categories","summary":"Merged categories + overlay keys","rbac":"catalog.read","rbacLabel":"catalog.read","tags":["catalog"]},{"method":"POST","path":"/api/admin/catalog-categories","summary":"Upsert overlay category","rbac":"catalog.write","rbacLabel":"catalog.write","tags":["catalog"]},{"method":"GET","path":"/api/admin/commission","summary":"Commission settings","rbac":"commission.read","rbacLabel":"commission.read","tags":["commission"]},{"method":"POST","path":"/api/admin/commission","summary":"Update commission settings","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["commission"]},{"method":"GET","path":"/api/admin/commission/category-rules","summary":"Per-category rate overrides","rbac":"commission.read","rbacLabel":"commission.read","tags":["commission"]},{"method":"POST","path":"/api/admin/commission/category-rules","summary":"Upsert category rule","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["commission"]},{"method":"DELETE","path":"/api/admin/commission/category-rules/:category","summary":"Remove category rule","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["commission"]},{"method":"POST","path":"/api/admin/create","summary":"Alias: create staff","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin"]},{"method":"GET","path":"/api/admin/customer-checkout-payments","summary":"Sanitized payment method rows from storefront orders for an email (query email, optional limit)","rbac":"orders.read","rbacLabel":"orders.read","tags":["orders","admin"]},{"method":"GET","path":"/api/admin/dashboard","summary":"Legacy dashboard JSON (prefer platform-overview; see getCatalog().dashboardOverview)","rbac":"dashboard.read","rbacLabel":"dashboard.read","tags":["admin"]},{"method":"PATCH","path":"/api/admin/inventory/products/:id/stock","summary":"Delta (tracked only), absolute number, or stock \"—\" for unlimited","rbac":"inventory.adjust","rbacLabel":"inventory.adjust","tags":["inventory"]},{"method":"GET","path":"/api/admin/inventory/summary","summary":"Stock KPIs + low-stock list (see getCatalog().stockManagement)","rbac":"inventory.read","rbacLabel":"inventory.read","tags":["inventory"]},{"method":"GET","path":"/api/admin/list","summary":"Alias: list admins","rbac":"staff.read","rbacLabel":"staff.read","tags":["admin"]},{"method":"GET","path":"/api/admin/notification-settings","summary":"Admin notification toggles, announcements queue, flash sale","rbac":"platform.read","rbacLabel":"platform.read","tags":["admin","notifications"]},{"method":"PUT","path":"/api/admin/notification-settings","summary":"Update notification settings","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","notifications"]},{"method":"POST","path":"/api/admin/notification-settings/clear-announcements","summary":"Clear announcement rows and queued announcements only","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","notifications"]},{"method":"POST","path":"/api/admin/notification-settings/clear-log","summary":"Clear full admin notification log","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","notifications"]},{"method":"POST","path":"/api/admin/notification-settings/clear-pending-approvals","summary":"Clear only pending approval_request rows","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","notifications"]},{"method":"POST","path":"/api/admin/notifications/announce","summary":"Push custom in-app announcement to customers","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","notifications"]},{"method":"PATCH","path":"/api/admin/orders/:orderNumber/status","summary":"Update fulfilment status","rbac":"orders.write","rbacLabel":"orders.write","tags":["orders"]},{"method":"GET","path":"/api/admin/payment-methods","summary":"All payment method configs","rbac":"payments.read","rbacLabel":"payments.read","tags":["payments"]},{"method":"POST","path":"/api/admin/payment-methods","summary":"Create method","rbac":"payments.write","rbacLabel":"payments.write","tags":["payments"]},{"method":"DELETE","path":"/api/admin/payment-methods/:id","summary":"Delete method","rbac":"payments.write","rbacLabel":"payments.write","tags":["payments"]},{"method":"PUT","path":"/api/admin/payment-methods/:id","summary":"Replace method","rbac":"payments.write","rbacLabel":"payments.write","tags":["payments"]},{"method":"POST","path":"/api/admin/payment-methods/reset-catalog","summary":"Reset to built-in catalogue","rbac":"payments.write","rbacLabel":"payments.write","tags":["payments"]},{"method":"POST","path":"/api/admin/permissions/check","summary":"Whether current admin JWT allows a permission key (no separate permission; admin role required)","rbac":"any_admin","rbacLabel":"Admin JWT (role=admin; no permission key)","tags":["admin"]},{"method":"GET","path":"/api/admin/platform-overview","summary":"Cross-cutting KPIs: orders, revenue, customers, stock, commission, etc. (Dashboard overview intro applies.)","rbac":"platform.read","rbacLabel":"platform.read","tags":["admin"]},{"method":"DELETE","path":"/api/admin/revoke-role","summary":"Suspend admin by userId","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin"]},{"method":"GET","path":"/api/admin/roles","summary":"Role definitions, glossary, permission patterns, admin API matrix","rbac":"roles.read","rbacLabel":"roles.read","tags":["admin"]},{"method":"GET","path":"/api/admin/security/login-events","summary":"Recent login attempts","rbac":"security.read","rbacLabel":"security.read","tags":["security"]},{"method":"GET","path":"/api/admin/security/sessions","summary":"Active sessions (PG)","rbac":"security.read","rbacLabel":"security.read","tags":["security"]},{"method":"DELETE","path":"/api/admin/security/sessions/:id","summary":"Revoke session by jti/id","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["security"]},{"method":"POST","path":"/api/admin/shop/restamp-products","summary":"Apply current shop name/logo stamp to all products (Shop profile editor role).","rbac":"shop_profile_editor","rbacLabel":"shop_profile_editor · Super Admin or Operations Admin","tags":["admin","geo"]},{"method":"GET","path":"/api/admin/staff","summary":"List admin users","rbac":"staff.read","rbacLabel":"staff.read","tags":["admin"]},{"method":"POST","path":"/api/admin/staff","summary":"Create staff admin","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin"]},{"method":"DELETE","path":"/api/admin/staff/:id","summary":"Delete staff","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin"]},{"method":"PATCH","path":"/api/admin/staff/:id","summary":"Update staff (role, 2FA flag, status)","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin"]},{"method":"POST","path":"/api/admin/staff/:id/reset-password","summary":"Set staff password","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin"]},{"method":"GET","path":"/api/admin/store-geo","summary":"Store origin (label, lat, lng, updatedAt) for distance APIs; platform.read (Dashboard overview — Geo).","rbac":"platform.read","rbacLabel":"platform.read","tags":["admin","geo"]},{"method":"PUT","path":"/api/admin/store-geo","summary":"Set store latitude, longitude, label (Shop profile editor: Super Admin or Operations Admin).","rbac":"shop_profile_editor","rbacLabel":"shop_profile_editor · Super Admin or Operations Admin","tags":["admin","geo"]},{"method":"GET","path":"/api/admin/tax-settings","summary":"VAT/tax shop settings","rbac":"platform.read","rbacLabel":"platform.read","tags":["admin","tax"]},{"method":"PUT","path":"/api/admin/tax-settings","summary":"Update tax settings (home country, VAT number, inclusive flag)","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","tax"]},{"method":"GET","path":"/api/admin/vendors","summary":"All vendors","rbac":"vendors.read","rbacLabel":"vendors.read","tags":["vendors"]},{"method":"POST","path":"/api/admin/vendors","summary":"Register vendor (optional businessTin)","rbac":"vendors.write","rbacLabel":"vendors.write","tags":["vendors"]},{"method":"PATCH","path":"/api/admin/vendors/:id","summary":"Update vendor profile / TIN / taxVerified","rbac":"vendors.write","rbacLabel":"vendors.write","tags":["vendors"]},{"method":"POST","path":"/api/admin/vendors/:id/approve","summary":"Approve by path id","rbac":"vendors.approve","rbacLabel":"vendors.approve","tags":["vendors"]},{"method":"POST","path":"/api/admin/vendors/:id/reject","summary":"Reject by path id","rbac":"vendors.approve","rbacLabel":"vendors.approve","tags":["vendors"]},{"method":"POST","path":"/api/admin/vendors/:id/suspend","summary":"Suspend vendor","rbac":"vendors.approve","rbacLabel":"vendors.approve","tags":["vendors"]},{"method":"GET","path":"/api/admin/wallet/:userId","summary":"Admin wallet balance for userId (self, Super Admin, or wallet.read; Dashboard overview — Wallet).","rbac":"wallet.read","rbacLabel":"wallet.read","tags":["admin","wallet"]},{"method":"GET","path":"/api/admin/wallet/:userId/transactions","summary":"Wallet ledger for a staff admin userId; use a numeric :userId with wallet.read or Super Admin (Dashboard overview — Wallet activity).","rbac":"wallet.read","rbacLabel":"wallet.read","tags":["admin","wallet"]},{"method":"POST","path":"/api/admin/wallet/adjust","summary":"Super Admin — writes balance and a ledger row (body: userId, amountUSD, optional note; Dashboard overview — Adjust).","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["admin","wallet"]},{"method":"GET","path":"/api/admin/wallet/me","summary":"Current admin USD wallet balance (Dashboard overview — Wallet: pair with …/wallet/me/transactions for ledger).","rbac":"any_admin","rbacLabel":"Admin JWT (role=admin; no permission key)","tags":["admin","wallet"]},{"method":"GET","path":"/api/admin/wallet/me/transactions","summary":"Wallet ledger for the current admin (Dashboard overview — Wallet activity).","rbac":"any_admin","rbacLabel":"Admin JWT (role=admin; no permission key)","tags":["admin","wallet"]},{"method":"POST","path":"/api/auth/cancel","summary":"Cancel own customer account","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["auth"]},{"method":"POST","path":"/api/auth/logout","summary":"Revoke current session (PG)","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["auth"]},{"method":"GET","path":"/api/auth/me","summary":"Current user","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["auth"]},{"method":"POST","path":"/api/auth/notification-log/:id/reply","summary":"Shopper reply on an announcement thread (role=customer; id matches announcement / log row)","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["auth","notifications","storefront"]},{"method":"GET","path":"/api/auth/orders","summary":"Customer orders for JWT email (payment details redacted)","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["auth"]},{"method":"GET","path":"/api/auth/orders/:orderNumber","summary":"Single customer order if email matches","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["auth"]},{"method":"PATCH","path":"/api/auth/profile","summary":"Update profile (e.g. displayName)","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["auth"]},{"method":"POST","path":"/api/commission/set-rate","summary":"Update rate (legacy body)","rbac":"super_admin","rbacLabel":"Super Admin only (adminRole=super_admin)","tags":["commission"]},{"method":"GET","path":"/api/orders","summary":"All orders (admin)","rbac":"orders.read","rbacLabel":"orders.read","tags":["orders"]},{"method":"GET","path":"/api/orders/:orderNumber","summary":"Order detail","rbac":"orders.read","rbacLabel":"orders.read","tags":["orders"]},{"method":"GET","path":"/api/products","summary":"Product list (any authenticated user)","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["products"]},{"method":"POST","path":"/api/products","summary":"Create product","rbac":"products.write","rbacLabel":"products.write","tags":["products"]},{"method":"DELETE","path":"/api/products/:id","summary":"Delete product","rbac":"products.delete","rbacLabel":"products.delete","tags":["products"]},{"method":"GET","path":"/api/products/:id","summary":"Product by id","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["products"]},{"method":"PATCH","path":"/api/products/:id","summary":"Patch product","rbac":"products.write","rbacLabel":"products.write","tags":["products"]},{"method":"PUT","path":"/api/products/:id","summary":"Replace product","rbac":"products.write","rbacLabel":"products.write","tags":["products"]},{"method":"GET","path":"/api/products/stats","summary":"Aggregate product stats","rbac":"jwt","rbacLabel":"JWT (any signed-in user)","tags":["products"]},{"method":"POST","path":"/api/vendor/approve","summary":"Approve vendor (body vendorId)","rbac":"vendors.approve","rbacLabel":"vendors.approve","tags":["vendors"]},{"method":"GET","path":"/api/vendor/pending-verification","summary":"Pending KYC vendors","rbac":"vendors.read","rbacLabel":"vendors.read","tags":["vendors"]},{"method":"POST","path":"/api/vendor/reject","summary":"Reject vendor","rbac":"vendors.approve","rbacLabel":"vendors.approve","tags":["vendors"]}],"endpoints":[{"method":"GET","path":"/api/health","auth":"none","summary":"Service health and storefront path hints","tags":["meta"]},{"method":"GET","path":"/api/catalog","auth":"none","summary":"JSON list of API endpoints","tags":["meta"]},{"method":"GET","path":"/api/meta/audit-action-catalog","auth":"none","summary":"Documented audit action types (same as audit-log payload; public, no auth)","tags":["meta","audit"]},{"method":"GET","path":"/api/openapi.json","auth":"none","summary":"OpenAPI 3.0 sketch (paths + bearer security)","tags":["meta"]},{"method":"GET","path":"/api/commission/current-rate","auth":"none","summary":"Public default commission settings snapshot","tags":["storefront"]},{"method":"GET","path":"/api/geo/store","auth":"none","summary":"Public store label and coordinates for distance (Dashboard overview — Geo).","tags":["storefront","geo"]},{"method":"GET","path":"/api/geo/distance","auth":"none","summary":"Haversine distance from configured store; query lat & lng (Dashboard overview — Geo).","tags":["storefront","geo"]},{"method":"POST","path":"/api/geo/distance","auth":"none","summary":"Haversine distance from configured store; JSON lat & lng or latitude & longitude (Dashboard overview — Geo).","tags":["storefront","geo"]},{"method":"GET","path":"/api/public/products","auth":"none","summary":"Storefront product list","tags":["storefront"]},{"method":"GET","path":"/api/public/products/:id","auth":"none","summary":"Storefront product by id","tags":["storefront"]},{"method":"GET","path":"/api/store/products","auth":"none","summary":"Alias: product list","tags":["storefront"]},{"method":"GET","path":"/api/store/products/:id","auth":"none","summary":"Alias: product by id","tags":["storefront"]},{"method":"GET","path":"/shopdesk/products","auth":"none","summary":"Alias: product list","tags":["storefront"]},{"method":"GET","path":"/shopdesk/products/:id","auth":"none","summary":"Alias: product by id","tags":["storefront"]},{"method":"GET","path":"/api/categories","auth":"none","summary":"Category tree (merged built-in + overlay)","tags":["storefront"]},{"method":"GET","path":"/api/public/categories","auth":"none","summary":"Alias: categories","tags":["storefront"]},{"method":"GET","path":"/api/currencies","auth":"none","summary":"Supported currencies","tags":["storefront"]},{"method":"GET","path":"/api/countries","auth":"none","summary":"Countries for checkout","tags":["storefront"]},{"method":"GET","path":"/api/public/payment-methods","auth":"none","summary":"Enabled payment methods (optional ?country=XX)","tags":["storefront"]},{"method":"GET","path":"/api/public/country-payment-reference","auth":"none","summary":"Informational payment landscape + doc links for a country (?country=XX); not legal advice; see disclaimer in JSON","tags":["storefront"]},{"method":"POST","path":"/api/public/payment-mock/authorize","auth":"none","summary":"Demo-only fake authorization id (body: countryCode, paymentMethodId, optional orderNumber & amountUSD); no real PSP","tags":["storefront"]},{"method":"POST","path":"/api/public/orders","auth":"none","summary":"Place order (validated server-side)","tags":["storefront"]},{"method":"POST","path":"/api/store/orders","auth":"none","summary":"Alias: place order","tags":["storefront"]},{"method":"POST","path":"/shopdesk/orders","auth":"none","summary":"Alias: place order","tags":["storefront"]},{"method":"POST","path":"/api/auth/register","auth":"none","summary":"Register customer account","tags":["auth"]},{"method":"POST","path":"/api/auth/login","auth":"none","summary":"Login; returns Bearer JWT","tags":["auth"]},{"method":"POST","path":"/api/auth/reactivate","auth":"none","summary":"Reactivate cancelled account","tags":["auth"]},{"method":"POST","path":"/api/auth/logout","auth":"bearer","summary":"Revoke current session (PG)","tags":["auth"],"rbac":"jwt"},{"method":"POST","path":"/api/admin/access-request","auth":"bearer_admin","summary":"Submit operator/platform access request for Super Admin review","tags":["admin","access"],"rbac":"any_admin"},{"method":"POST","path":"/api/admin/access-request/:id/decision","auth":"bearer_super_admin","summary":"Approve or reject a pending access request","tags":["admin","access"],"rbac":"super_admin"},{"method":"POST","path":"/api/auth/cancel","auth":"bearer","summary":"Cancel own customer account","tags":["auth"],"rbac":"jwt"},{"method":"PATCH","path":"/api/auth/profile","auth":"bearer","summary":"Update profile (e.g. displayName)","tags":["auth"],"rbac":"jwt"},{"method":"GET","path":"/api/auth/me","auth":"bearer","summary":"Current user","tags":["auth"],"rbac":"jwt"},{"method":"GET","path":"/api/auth/orders","auth":"bearer","summary":"Customer orders for JWT email (payment details redacted)","tags":["auth"],"rbac":"jwt"},{"method":"GET","path":"/api/auth/orders/:orderNumber","auth":"bearer","summary":"Single customer order if email matches","tags":["auth"],"rbac":"jwt"},{"method":"GET","path":"/api/products","auth":"bearer","summary":"Product list (any authenticated user)","tags":["products"],"rbac":"jwt"},{"method":"GET","path":"/api/products/stats","auth":"bearer","summary":"Aggregate product stats","tags":["products"],"rbac":"jwt"},{"method":"GET","path":"/api/products/:id","auth":"bearer","summary":"Product by id","tags":["products"],"rbac":"jwt"},{"method":"POST","path":"/api/products","auth":"bearer_admin","summary":"Create product","tags":["products"],"rbac":"products.write"},{"method":"PUT","path":"/api/products/:id","auth":"bearer_admin","summary":"Replace product","tags":["products"],"rbac":"products.write"},{"method":"PATCH","path":"/api/products/:id","auth":"bearer_admin","summary":"Patch product","tags":["products"],"rbac":"products.write"},{"method":"DELETE","path":"/api/products/:id","auth":"bearer_admin","summary":"Delete product","tags":["products"],"rbac":"products.delete"},{"method":"GET","path":"/api/orders","auth":"bearer_admin","summary":"All orders (admin)","tags":["orders"],"rbac":"orders.read"},{"method":"GET","path":"/api/orders/:orderNumber","auth":"bearer_admin","summary":"Order detail","tags":["orders"],"rbac":"orders.read"},{"method":"GET","path":"/api/admin/customer-checkout-payments","auth":"bearer_admin","summary":"Sanitized payment method rows from storefront orders for an email (query email, optional limit)","tags":["orders","admin"],"rbac":"orders.read"},{"method":"PATCH","path":"/api/admin/orders/:orderNumber/status","auth":"bearer_admin","summary":"Update fulfilment status","tags":["orders"],"rbac":"orders.write"},{"method":"GET","path":"/api/admin/dashboard","auth":"bearer_admin","summary":"Legacy dashboard JSON (prefer platform-overview; see getCatalog().dashboardOverview)","tags":["admin"],"rbac":"dashboard.read"},{"method":"GET","path":"/api/admin/platform-overview","auth":"bearer_admin","summary":"Cross-cutting KPIs: orders, revenue, customers, stock, commission, etc. (Dashboard overview intro applies.)","tags":["admin"],"rbac":"platform.read"},{"method":"GET","path":"/api/admin/tax-settings","auth":"bearer_admin","summary":"VAT/tax shop settings","tags":["admin","tax"],"rbac":"platform.read"},{"method":"PUT","path":"/api/admin/tax-settings","auth":"bearer_super_admin","summary":"Update tax settings (home country, VAT number, inclusive flag)","tags":["admin","tax"],"rbac":"super_admin"},{"method":"GET","path":"/api/admin/notification-settings","auth":"bearer_admin","summary":"Admin notification toggles, announcements queue, flash sale","tags":["admin","notifications"],"rbac":"platform.read"},{"method":"PUT","path":"/api/admin/notification-settings","auth":"bearer_super_admin","summary":"Update notification settings","tags":["admin","notifications"],"rbac":"super_admin"},{"method":"POST","path":"/api/admin/notifications/announce","auth":"bearer_super_admin","summary":"Push custom in-app announcement to customers","tags":["admin","notifications"],"rbac":"super_admin"},{"method":"POST","path":"/api/admin/notification-settings/clear-log","auth":"bearer_super_admin","summary":"Clear full admin notification log","tags":["admin","notifications"],"rbac":"super_admin"},{"method":"POST","path":"/api/admin/notification-settings/clear-announcements","auth":"bearer_super_admin","summary":"Clear announcement rows and queued announcements only","tags":["admin","notifications"],"rbac":"super_admin"},{"method":"POST","path":"/api/admin/notification-settings/clear-pending-approvals","auth":"bearer_super_admin","summary":"Clear only pending approval_request rows","tags":["admin","notifications"],"rbac":"super_admin"},{"method":"GET","path":"/api/public/tax/config","auth":"none","summary":"Tax settings + country row (?country=)","tags":["storefront","tax"]},{"method":"POST","path":"/api/public/tax/preview","auth":"none","summary":"Preview order tax (subtotal, shipping, country, categories)","tags":["storefront","tax"]},{"method":"GET","path":"/api/public/notification-context","auth":"none","summary":"Public notification toggles + announcements (each includes replies[] for announcement threads)","tags":["storefront","notifications"]},{"method":"POST","path":"/api/auth/notification-log/:id/reply","auth":"bearer","summary":"Shopper reply on an announcement thread (role=customer; id matches announcement / log row)","tags":["auth","notifications","storefront"],"rbac":"jwt"},{"method":"GET","path":"/api/admin/wallet/me","auth":"bearer_admin","summary":"Current admin USD wallet balance (Dashboard overview — Wallet: pair with …/wallet/me/transactions for ledger).","tags":["admin","wallet"],"rbac":"any_admin"},{"method":"GET","path":"/api/admin/wallet/me/transactions","auth":"bearer_admin","summary":"Wallet ledger for the current admin (Dashboard overview — Wallet activity).","tags":["admin","wallet"],"rbac":"any_admin"},{"method":"GET","path":"/api/admin/wallet/:userId","auth":"bearer_admin","summary":"Admin wallet balance for userId (self, Super Admin, or wallet.read; Dashboard overview — Wallet).","tags":["admin","wallet"],"rbac":"wallet.read"},{"method":"POST","path":"/api/admin/wallet/adjust","auth":"bearer_super_admin","summary":"Super Admin — writes balance and a ledger row (body: userId, amountUSD, optional note; Dashboard overview — Adjust).","tags":["admin","wallet"],"rbac":"super_admin"},{"method":"GET","path":"/api/admin/wallet/:userId/transactions","auth":"bearer_admin","summary":"Wallet ledger for a staff admin userId; use a numeric :userId with wallet.read or Super Admin (Dashboard overview — Wallet activity).","tags":["admin","wallet"],"rbac":"wallet.read"},{"method":"GET","path":"/api/admin/store-geo","auth":"bearer_admin","summary":"Store origin (label, lat, lng, updatedAt) for distance APIs; platform.read (Dashboard overview — Geo).","tags":["admin","geo"],"rbac":"platform.read"},{"method":"PUT","path":"/api/admin/store-geo","auth":"bearer_admin","summary":"Set store latitude, longitude, label (Shop profile editor: Super Admin or Operations Admin).","tags":["admin","geo"],"rbac":"shop_profile_editor"},{"method":"POST","path":"/api/admin/shop/restamp-products","auth":"bearer_admin","summary":"Apply current shop name/logo stamp to all products (Shop profile editor role).","tags":["admin","geo"],"rbac":"shop_profile_editor"},{"method":"GET","path":"/api/admin/roles","auth":"bearer_admin","summary":"Role definitions, glossary, permission patterns, admin API matrix","tags":["admin"],"rbac":"roles.read"},{"method":"POST","path":"/api/admin/permissions/check","auth":"bearer_admin","summary":"Whether current admin JWT allows a permission key (no separate permission; admin role required)","tags":["admin"],"rbac":"any_admin"},{"method":"GET","path":"/api/admin/staff","auth":"bearer_admin","summary":"List admin users","tags":["admin"],"rbac":"staff.read"},{"method":"GET","path":"/api/admin/list","auth":"bearer_admin","summary":"Alias: list admins","tags":["admin"],"rbac":"staff.read"},{"method":"POST","path":"/api/admin/staff","auth":"bearer_super_admin","summary":"Create staff admin","tags":["admin"],"rbac":"super_admin"},{"method":"POST","path":"/api/admin/create","auth":"bearer_super_admin","summary":"Alias: create staff","tags":["admin"],"rbac":"super_admin"},{"method":"PATCH","path":"/api/admin/staff/:id","auth":"bearer_super_admin","summary":"Update staff (role, 2FA flag, status)","tags":["admin"],"rbac":"super_admin"},{"method":"DELETE","path":"/api/admin/staff/:id","auth":"bearer_super_admin","summary":"Delete staff","tags":["admin"],"rbac":"super_admin"},{"method":"POST","path":"/api/admin/staff/:id/reset-password","auth":"bearer_super_admin","summary":"Set staff password","tags":["admin"],"rbac":"super_admin"},{"method":"PUT","path":"/api/admin/assign-role","auth":"bearer_super_admin","summary":"Assign adminRole by userId","tags":["admin"],"rbac":"super_admin"},{"method":"DELETE","path":"/api/admin/revoke-role","auth":"bearer_super_admin","summary":"Suspend admin by userId","tags":["admin"],"rbac":"super_admin"},{"method":"GET","path":"/api/admin/commission","auth":"bearer_admin","summary":"Commission settings","tags":["commission"],"rbac":"commission.read"},{"method":"POST","path":"/api/admin/commission","auth":"bearer_super_admin","summary":"Update commission settings","tags":["commission"],"rbac":"super_admin"},{"method":"POST","path":"/api/commission/set-rate","auth":"bearer_super_admin","summary":"Update rate (legacy body)","tags":["commission"],"rbac":"super_admin"},{"method":"GET","path":"/api/admin/commission/category-rules","auth":"bearer_admin","summary":"Per-category rate overrides","tags":["commission"],"rbac":"commission.read"},{"method":"POST","path":"/api/admin/commission/category-rules","auth":"bearer_super_admin","summary":"Upsert category rule","tags":["commission"],"rbac":"super_admin"},{"method":"DELETE","path":"/api/admin/commission/category-rules/:category","auth":"bearer_super_admin","summary":"Remove category rule","tags":["commission"],"rbac":"super_admin"},{"method":"GET","path":"/api/admin/vendors","auth":"bearer_admin","summary":"All vendors","tags":["vendors"],"rbac":"vendors.read"},{"method":"GET","path":"/api/vendor/pending-verification","auth":"bearer_admin","summary":"Pending KYC vendors","tags":["vendors"],"rbac":"vendors.read"},{"method":"POST","path":"/api/admin/vendors","auth":"bearer_admin","summary":"Register vendor (optional businessTin)","tags":["vendors"],"rbac":"vendors.write"},{"method":"PATCH","path":"/api/admin/vendors/:id","auth":"bearer_admin","summary":"Update vendor profile / TIN / taxVerified","tags":["vendors"],"rbac":"vendors.write"},{"method":"POST","path":"/api/vendor/approve","auth":"bearer_admin","summary":"Approve vendor (body vendorId)","tags":["vendors"],"rbac":"vendors.approve"},{"method":"POST","path":"/api/vendor/reject","auth":"bearer_admin","summary":"Reject vendor","tags":["vendors"],"rbac":"vendors.approve"},{"method":"POST","path":"/api/admin/vendors/:id/approve","auth":"bearer_admin","summary":"Approve by path id","tags":["vendors"],"rbac":"vendors.approve"},{"method":"POST","path":"/api/admin/vendors/:id/reject","auth":"bearer_admin","summary":"Reject by path id","tags":["vendors"],"rbac":"vendors.approve"},{"method":"POST","path":"/api/admin/vendors/:id/suspend","auth":"bearer_admin","summary":"Suspend vendor","tags":["vendors"],"rbac":"vendors.approve"},{"method":"GET","path":"/api/admin/security/login-events","auth":"bearer_admin","summary":"Recent login attempts","tags":["security"],"rbac":"security.read"},{"method":"GET","path":"/api/admin/security/sessions","auth":"bearer_admin","summary":"Active sessions (PG)","tags":["security"],"rbac":"security.read"},{"method":"DELETE","path":"/api/admin/security/sessions/:id","auth":"bearer_super_admin","summary":"Revoke session by jti/id","tags":["security"],"rbac":"super_admin"},{"method":"GET","path":"/api/admin/audit-log","auth":"bearer_admin","summary":"List audit entries + actorEmail enrichment + action catalog (see getCatalog().auditTrail, auditTrail.actorEmail)","tags":["audit"],"rbac":"audit.read"},{"method":"GET","path":"/api/admin/audit-log/export","auth":"bearer_admin","summary":"Export audit entries with same actorEmail rules as list (format=json|ndjson; see getCatalog().auditTrail.actorEmail)","tags":["audit"],"rbac":"audit.export"},{"method":"GET","path":"/api/admin/catalog-categories","auth":"bearer_admin","summary":"Merged categories + overlay keys","tags":["catalog"],"rbac":"catalog.read"},{"method":"POST","path":"/api/admin/catalog-categories","auth":"bearer_admin","summary":"Upsert overlay category","tags":["catalog"],"rbac":"catalog.write"},{"method":"DELETE","path":"/api/admin/catalog-categories","auth":"bearer_admin","summary":"Delete overlay (?name=)","tags":["catalog"],"rbac":"catalog.write"},{"method":"GET","path":"/api/admin/payment-methods","auth":"bearer_admin","summary":"All payment method configs","tags":["payments"],"rbac":"payments.read"},{"method":"POST","path":"/api/admin/payment-methods","auth":"bearer_admin","summary":"Create method","tags":["payments"],"rbac":"payments.write"},{"method":"PUT","path":"/api/admin/payment-methods/:id","auth":"bearer_admin","summary":"Replace method","tags":["payments"],"rbac":"payments.write"},{"method":"DELETE","path":"/api/admin/payment-methods/:id","auth":"bearer_admin","summary":"Delete method","tags":["payments"],"rbac":"payments.write"},{"method":"POST","path":"/api/admin/payment-methods/reset-catalog","auth":"bearer_admin","summary":"Reset to built-in catalogue","tags":["payments"],"rbac":"payments.write"},{"method":"GET","path":"/api/admin/inventory/summary","auth":"bearer_admin","summary":"Stock KPIs + low-stock list (see getCatalog().stockManagement)","tags":["inventory"],"rbac":"inventory.read"},{"method":"PATCH","path":"/api/admin/inventory/products/:id/stock","auth":"bearer_admin","summary":"Delta (tracked only), absolute number, or stock \"—\" for unlimited","tags":["inventory"],"rbac":"inventory.adjust"}]}