M10 — Staff and customer management What's missing right now: You have roles and permissions but no way to manage users through the API. An owner cannot invite a staff member. A customer cannot self-register for a specific tenant's store. There are no endpoints to list, deactivate, or update users. What gets built: POST /staff/invite — owner sends invite email, staff sets password via token GET/PATCH/DELETE /staff/{id} — owner manages staff accounts POST /staff/{id}/permissions — override specific permissions per staff member POST /auth/customer/register — customer self-registers scoped to a tenant GET /customers — owner/staff lists customers with booking history counts GET /customers/{id} — customer profile with full booking history PATCH /customers/{id} — update customer details GET/PATCH /profile — any user manages their own profile and password change M11 — Delivery management What's missing right now: delivery_type and delivery_address exist on bookings but there is no delivery configuration, no fee calculation rules, no scheduling, and no status tracking. The BRD explicitly requires delivery scheduling, fee calculation, and route assignment. What gets built: GET/POST /settings/delivery-zones — owner defines zones with fee rules (flat, per-km, free above threshold) POST /bookings/{id}/delivery — schedule a delivery for a booking GET /deliveries — staff sees all pending deliveries PATCH /deliveries/{id}/status — update delivery status (scheduled → dispatched → delivered) POST /deliveries/{id}/assign — assign a staff member as delivery driver Fee calculation wired into booking creation when delivery_type=delivery M12 — Reporting and analytics What's missing right now: The BRD lists revenue reports, inventory utilisation, asset performance, and customer behaviour as requirements. Nothing exists for any of these. What gets built: GET /reports/revenue — total revenue, breakdown by period (daily/weekly/monthly), params: date_from, date_to GET /reports/bookings — booking counts by status, cancellation rate, average rental duration GET /reports/inventory — utilisation rate per product (booked days / available days), top and bottom performers GET /reports/assets — revenue per asset, maintenance cost per asset, downtime percentage GET /reports/customers — new vs returning, top customers by spend, average booking value GET /reports/overdue — current overdue bookings summary with fees outstanding All reports accept date_from and date_to query params, return pre-aggregated data — no raw rows M13 — SaaS billing and plan enforcement What's missing right now: plans and tenant_subscriptions tables exist but nothing enforces plan limits. An owner on the Basic plan (5 products max) can create 500 products with zero resistance. Stripe subscription lifecycle is not wired. What gets built: Plan limit enforcement middleware — checks max_products, max_assets, max_staff_users before creating records, returns 403 with clear message when limit reached GET /billing/plan — current plan details and usage (5/5 products used) GET /billing/plans — all available plans for upgrade POST /billing/subscribe — create or change Stripe subscription POST /billing/cancel — cancel subscription (sets to cancel at period end) GET /billing/invoices — billing history from Stripe Stripe webhook handlers for: customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed, invoice.paid Trial expiry: when trial_ends_at passes and no active subscription, tenant is locked to read-only M14 — Tenant store settings What's missing right now: Tenant settings is a freeform JSON column with only currency, timezone, and delivery_enabled. There is no structured API for managing store configuration. A frontend cannot build a settings page against the current API. What gets built: GET/PATCH /settings/store — business name, logo, contact info, address GET/PATCH /settings/rental-policies — deposit policy text, late return policy, damage policy GET/PATCH /settings/business-hours — opening hours per day of week POST /settings/holidays — block specific dates (no bookings accepted) GET/PATCH /settings/notifications — which notification types are enabled, custom email templates per type GET/PATCH /settings/payment — accepted payment methods, deposit percentage rules GET/PATCH /settings/booking — auto-confirm bookings, minimum advance notice, maximum advance booking window M15 — Search and filtering What's missing right now: GET /catalog/products accepts basic filters but there is no full-text search, no faceted filtering (filter by multiple categories, price range, availability on a date), and no sort options beyond created_at DESC. What gets built: GET /catalog/search — unified search across products and categories, full-text against name/description/sku Enhanced GET /catalog/products — add sort options (price_asc, price_desc, name_asc, availability), availability_date filter (only show products with at least one free asset on a given date), multiple category_ids filter GET /catalog/products/featured — shortcut for is_featured=true published products GET /catalog/categories/{id}/products — all published products in a category including subcategories Response includes facet counts: how many products in each category, price range min/max, available count M16 — API hardening and production readiness What's missing right now: No rate limiting beyond Laravel defaults, no consistent pagination envelope across all list endpoints (some return meta, some may not), no machine-readable error codes (just human messages), no API versioning enforcement, no request ID tracing. What gets built: Rate limiting per route group: auth endpoints (10/min), public endpoints (60/min), authenticated (120/min), staff actions (300/min) Consistent pagination envelope enforced across every list endpoint: {data, meta: {current_page, last_page, per_page, total, from, to}} Machine-readable error codes added to every error response: {"success": false, "message": "...", "code": "BOOKING_NOT_FOUND", "errors": {}} X-Request-ID header echoed back on every response for tracing X-RateLimit-Remaining and X-RateLimit-Reset headers on all responses Throttle exceeded returns 429 with Retry-After header API health endpoint expanded: GET /health/detailed — checks DB, Redis, queue worker all in one response CORS configuration for the frontend domains M17 — Discount and coupon system What's missing right now: discount_code and discount_amount exist on the bookings table but the discount system was never built. The booking creation ignores discount codes entirely. What gets built: coupons tenant table: code, type (percentage/fixed), value, min_order_amount, max_uses, uses_count, valid_from, valid_until, applicable_products (JSON array or null for all) GET/POST /coupons — owner manages coupons GET/PATCH/DELETE /coupons/{id} POST /coupons/validate — public endpoint, customer checks if a code is valid before checkout, returns discount amount for their cart Booking creation accepts coupon_code, validates and applies it, discount_amount populated correctly Coupon uses_count incremented atomically on booking creation, decremented on cancellation M18 — Reviews and ratings What's missing right now: The BRD mentions customer behaviour insights. Reviews are the primary source of qualitative customer data and are a standard feature of any rental platform. What gets built: reviews tenant table: booking_id, user_id, product_id, rating (1-5), title, body, is_published, owner_response, owner_responded_at POST /bookings/{id}/review — customer submits review (only after booking is CLOSED) GET /catalog/products/{id}/reviews — public listing of reviews for a product, with average rating PATCH /reviews/{id}/respond — owner posts a response to a review PATCH /reviews/{id}/publish — owner moderates (publish/unpublish) GET /reviews — owner/staff sees all reviews with moderation controls Average rating added to ProductResource M19 — Outbound webhooks and integrations What's missing right now: The BRD lists QuickBooks, Xero, DHL, UPS, Shippo as integrations. More importantly, tenants need to be able to connect their own systems to the platform via outbound webhooks. What gets built: webhook_endpoints tenant table: url, secret, events (JSON array of subscribed event types), is_active GET/POST /settings/webhooks — owner registers outbound webhook URLs GET/PATCH/DELETE /settings/webhooks/{id} POST /settings/webhooks/{id}/test — sends a test payload to verify the endpoint Outbound webhook dispatcher: fires on every booking event, signs payload with HMAC-SHA256 using the endpoint's secret, queued job with retry on failure webhook_delivery_logs table: tracks every outbound delivery attempt with response code and body Accounting integration stubs: POST /integrations/quickbooks/sync-invoice, POST /integrations/xero/sync-invoice — structured stubs that log what would be sent, ready for real OAuth in a future phase Shipping stubs: GET /integrations/shipping/rates — accepts pickup/delivery address, returns placeholder rates structure ready for DHL/UPS/Shippo SDKs M20 — AI features (phase 2, after real data) Do not build until you have at least 6 months of booking data across multiple tenants. The endpoints should be stubbed in M16 with 501 Not Implemented responses so the frontend can be built against the contract. GET /ai/demand-forecast/{productId} — predicted demand for next 30 days GET /ai/pricing-suggestion/{productId} — suggested price adjustments GET /catalog/products/{id}/recommendations — related products to suggest at checkout