# API Architecture Consolidation Proposal **Date:** 2025-11-22 **Status:** DRAFT - Awaiting Review **Priority:** HIGH ## Executive Summary The platform currently has **two parallel API structures** for shop/customer-facing endpoints: 1. **Original:** `/api/v1/platform/stores/{store_id}/*` 2. **New:** `/api/v1/shop/*` This divergence creates confusion, maintenance overhead, and potential bugs. This document analyzes the situation and proposes a consolidation strategy. --- ## Current State Analysis ### 1. Original Architecture (`/api/v1/platform/stores/`) **Location:** `app/api/v1/platform/stores/` **Endpoints:** ``` GET /api/v1/platform/stores → List active stores GET /api/v1/platform/stores/{store_id}/products → Product catalog GET /api/v1/platform/stores/{store_id}/products/{product_id} → Product detail POST /api/v1/platform/stores/{store_id}/cart → Cart operations GET /api/v1/platform/stores/{store_id}/orders → Customer orders POST /api/v1/platform/stores/auth/login → Customer authentication POST /api/v1/platform/stores/auth/register → Customer registration ``` **Characteristics:** - ✅ **Store-scoped:** Requires explicit `store_id` in path - ✅ **RESTful:** Clear resource hierarchy - ✅ **Authentication:** Supports customer auth via `/auth/*` endpoints - ✅ **Existing:** Already implemented with services and models - ❌ **Verbose:** Requires store_id in every call **Current Usage:** - Product catalog: `products.py` - Shopping cart: `cart.py` - Orders: `orders.py` - Customer auth: `auth.py` - Store listing: `stores.py` --- ### 2. New Architecture (`/api/v1/shop/`) **Location:** `app/api/v1/shop/` **Endpoints:** ``` GET /api/v1/shop/content-pages/navigation → CMS navigation pages GET /api/v1/shop/content-pages/{slug} → CMS page content ``` **Characteristics:** - ✅ **Store-agnostic URLs:** Clean paths without store_id - ✅ **Middleware-driven:** Relies on `StoreContextMiddleware` to inject store - ✅ **Simpler URLs:** `/api/v1/shop/products` vs `/api/v1/platform/stores/123/products` - ❌ **Incomplete:** Only CMS endpoints implemented - ❌ **Divergent:** Not consistent with existing public API **Current Usage:** - CMS content pages only - Called from shop templates (e.g., `shop/products.html`, `shop/home.html`) --- ## The Problem ### Inconsistency ```javascript // ❌ INCONSISTENT - Two different patterns for same context // CMS pages use new pattern fetch('/api/v1/shop/content-pages/about') // Products use old pattern fetch('/api/v1/platform/stores/123/products') ``` ### Confusion Developers must remember: - "Is this endpoint under `/shop` or `/public/stores`?" - "Do I need to pass store_id or is it from middleware?" - "Which authentication endpoints do I use?" ### Maintenance Overhead - Two sets of documentation - Two architectural patterns - Duplicate functionality risk - Testing complexity ### Broken Features **Current Issue:** CMS pages not loading at `/stores/orion/about` **Root Cause:** - CMS API exists at `/api/v1/shop/content-pages/{slug}` - No corresponding HTML route handler in `store_pages.py` - JavaScript might be calling wrong endpoint --- ## Options Analysis ### Option 1: Move Everything to `/api/v1/shop/*` (Middleware-Driven) **Approach:** Consolidate all customer-facing endpoints under `/api/v1/shop/*` **Proposed Structure:** ``` /api/v1/shop/ ├── auth/ │ ├── POST /login → Customer login │ ├── POST /register → Customer registration │ └── POST /logout → Customer logout ├── products/ │ ├── GET / → Product catalog │ ├── GET /{product_id} → Product detail │ └── GET /featured → Featured products ├── cart/ │ ├── GET / → View cart │ ├── POST /items → Add to cart │ └── PUT /items/{item_id} → Update quantity ├── orders/ │ ├── GET / → Order history │ ├── GET /{order_id} → Order detail │ └── POST / → Create order ├── content-pages/ → [EXISTING] │ ├── GET /navigation → Navigation pages │ └── GET /{slug} → Page content └── stores/ └── GET / → List stores (marketplace) ``` **Implementation:** - Store extracted by `StoreContextMiddleware` from request - All endpoints use `request.state.store` instead of path parameter - URLs are cleaner: `/api/v1/shop/products` instead of `/api/v1/platform/stores/123/products` **Pros:** - ✅ Clean, consistent API structure - ✅ Simpler URLs for frontend - ✅ Store is contextual (from domain/subdomain/path) - ✅ Aligns with multi-tenant architecture - ✅ Easier to document and understand **Cons:** - ❌ **Breaking change** for existing clients - ❌ Requires moving ~8-10 endpoint files - ❌ Need to update all frontend code - ❌ Testing effort to verify all endpoints work **Migration Effort:** HIGH (2-3 days) --- ### Option 2: Keep `/api/v1/platform/stores/*` and Deprecate `/api/v1/shop/*` **Approach:** Move CMS endpoints to `/api/v1/platform/stores/{store_id}/content-pages/*` **Proposed Changes:** ``` # Move CMS endpoints FROM: /api/v1/shop/content-pages/navigation TO: /api/v1/platform/stores/{store_id}/content-pages/navigation FROM: /api/v1/shop/content-pages/{slug} TO: /api/v1/platform/stores/{store_id}/content-pages/{slug} ``` **Pros:** - ✅ Maintains existing architecture - ✅ No breaking changes to existing endpoints - ✅ RESTful store-scoped URLs - ✅ Minimal code changes **Cons:** - ❌ Verbose URLs with store_id everywhere - ❌ Doesn't leverage middleware architecture - ❌ Less elegant than Option 1 - ❌ Frontend must always know store_id **Migration Effort:** LOW (1 day) --- ### Option 3: Hybrid Approach with Alias Routes **Approach:** Support both patterns during transition period **Implementation:** ```python # Primary (new pattern) @router.get("/products") async def get_products_new(request: Request, db: Session = Depends(get_db)): store = request.state.store # ... # Alias (old pattern for backwards compatibility) @router.get("/stores/{store_id}/products") async def get_products_legacy(store_id: int, db: Session = Depends(get_db)): # Redirect or proxy to new pattern # ... ``` **Pros:** - ✅ No breaking changes - ✅ Gradual migration path - ✅ Both patterns work simultaneously **Cons:** - ❌ Maintains complexity - ❌ Doubles maintenance burden - ❌ Confusing for developers - ❌ Technical debt accumulates **Migration Effort:** MEDIUM (1-2 days + ongoing maintenance) --- ## Recommendation ### **OPTION 1: Consolidate to `/api/v1/shop/*` (Middleware-Driven)** **Rationale:** 1. **Architectural Alignment**: Platform uses middleware for store context injection. APIs should leverage this instead of requiring explicit store_id. 2. **User Experience**: Cleaner URLs are easier for frontend developers: ```javascript // ✅ GOOD fetch('/api/v1/shop/products') // ❌ BAD fetch('/api/v1/platform/stores/123/products') ``` 3. **Multi-Tenant Best Practice**: Store context should be implicit (from domain/path), not explicit in every API call. 4. **Consistency**: All shop endpoints follow same pattern - no mixing `/shop` and `/public/stores`. 5. **Future-Proof**: Easier to add new shop features without worrying about store_id paths. --- ## Migration Plan ### Phase 1: Create New Endpoints (Week 1) **Day 1-2: Move Products** ```bash # Copy and adapt app/api/v1/platform/stores/products.py → app/api/v1/shop/products.py # Changes: - Remove store_id path parameter - Use request.state.store instead - Update route paths ``` **Day 3: Move Cart** ```bash app/api/v1/platform/stores/cart.py → app/api/v1/shop/cart.py ``` **Day 4: Move Orders** ```bash app/api/v1/platform/stores/orders.py → app/api/v1/shop/orders.py ``` **Day 5: Move Auth** ```bash app/api/v1/platform/stores/auth.py → app/api/v1/shop/auth.py ``` ### Phase 2: Update Frontend (Week 1) **Templates:** - Update all `fetch()` calls in shop templates - Change from `/api/v1/platform/stores/${storeId}/...` to `/api/v1/shop/...` **JavaScript:** - Update any shop-related API client code - Remove hardcoded store_id references ### Phase 3: Testing (Week 2, Day 1-2) - ✅ Test all shop pages load correctly - ✅ Test product catalog - ✅ Test cart operations - ✅ Test order placement - ✅ Test customer authentication - ✅ Test CMS pages ### Phase 4: Deprecation Notice (Week 2, Day 3) - Add deprecation warnings to old endpoints - Update documentation - Add logging to track old endpoint usage ### Phase 5: Removal (Week 3+) - Monitor old endpoint usage - After no usage for 2 weeks, remove old endpoints - Clean up code --- ## Code Examples ### Before (Current - `/api/v1/platform/stores`) ```python # app/api/v1/platform/stores/products.py @router.get("/{store_id}/products") def get_public_product_catalog( store_id: int = Path(...), db: Session = Depends(get_db), ): store = db.query(Store).filter(Store.id == store_id).first() # ... ``` ```javascript // Frontend const storeId = 123; fetch(`/api/v1/platform/stores/${storeId}/products`) ``` ### After (Proposed - `/api/v1/shop`) ```python # app/api/v1/shop/products.py @router.get("/products") def get_product_catalog( request: Request, db: Session = Depends(get_db), ): store = request.state.store # Injected by middleware # ... ``` ```javascript // Frontend fetch('/api/v1/shop/products') // Store context automatic ``` --- ## Impact Assessment ### Breaking Changes - All frontend code calling `/api/v1/platform/stores/*` must update - Mobile apps (if any) must update - Third-party integrations (if any) must update ### Non-Breaking - Admin APIs: `/api/v1/admin/*` → No changes - Store APIs: `/api/v1/store/*` → No changes - Store listing: Keep `/api/v1/platform/stores` (list all stores for marketplace) ### Risk Mitigation 1. **Deprecation Period**: Keep old endpoints for 2-4 weeks 2. **Logging**: Track usage of old endpoints 3. **Documentation**: Clear migration guide for developers 4. **Testing**: Comprehensive E2E tests before deployment --- ## Alternative: Quick Fix for Current Issue If full migration is not approved immediately, we can do a **minimal fix** for the CMS issue: ### Quick Fix: Just Move CMS to Public API ```python # Move: app/api/v1/shop/content_pages.py # To: app/api/v1/platform/stores/content_pages.py # Update routes: @router.get("/{store_id}/content-pages/navigation") @router.get("/{store_id}/content-pages/{slug}") ``` **Effort:** 1-2 hours **Impact:** Fixes immediate CMS issue **Debt:** Maintains architectural divergence --- ## Decision Required **Question for Team:** Should we: 1. ✅ **Consolidate to `/api/v1/shop/*`** (Recommended) 2. ❌ **Keep `/api/v1/platform/stores/*`** and move CMS there 3. ❌ **Hybrid approach** with both patterns 4. ❌ **Quick fix only** - move CMS, address later **Timeline:** Please decide by [DATE] so we can plan sprint accordingly. --- ## Appendix: Current Endpoint Inventory ### `/api/v1/platform/stores/*` - ✅ `stores.py` - Store listing - ✅ `auth.py` - Customer authentication - ✅ `products.py` - Product catalog - ✅ `cart.py` - Shopping cart - ✅ `orders.py` - Order management - 🚧 `payments.py` - Stub - 🚧 `search.py` - Stub - 🚧 `shop.py` - Stub ### `/api/v1/shop/*` - ✅ `content_pages.py` - CMS pages ### To Be Created (if Option 1 chosen) - 📝 `shop/products.py` - 📝 `shop/cart.py` - 📝 `shop/orders.py` - 📝 `shop/auth.py` - 📝 `shop/stores.py` (marketplace listing) --- ## References - [Authentication Dependencies Guide](../development/auth-dependencies-guide.md) - [Multi-Tenant Architecture](./multi-tenant.md) - [Middleware Stack Documentation](./middleware.md) - [URL Routing Overview](./url-routing/overview.md)