# Dutchie Analytics API - Usage Guide ## Base URL ``` http://localhost:3010/api ``` ## Authentication All endpoints require JWT authentication via Bearer token: ``` Authorization: Bearer YOUR_JWT_TOKEN ``` ## Products API ### Get Products with Filtering, Sorting & Field Selection **Endpoint:** `GET /products` #### Basic Usage ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&limit=10" ``` #### Field Selection (Reduce Payload Size) Only return specific fields to reduce bandwidth and improve performance: ```bash # Only get essential fields curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&fields=id,name,price,brand,in_stock" # Get fields needed for product cards curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&fields=id,name,price,brand,thc_percentage,image_url_full,in_stock" ``` #### Advanced Filtering **Filter by Category:** ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&category_id=5" ``` **Filter by Stock Status:** ```bash # Only in-stock products curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&in_stock=true" ``` **Search Products:** ```bash # Search in name, brand, and description curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?search=blue+dream" ``` **Filter by Brand:** ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&brand=Cresco" ``` **Filter by Price Range:** ```bash # Products between $20 and $50 curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&min_price=20&max_price=50" ``` **Filter by THC Percentage:** ```bash # High THC products (>20%) curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&min_thc=20" ``` **Filter by Strain Type:** ```bash # Get only indica strains curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&strain_type=indica" ``` #### Sorting **Sort by Price:** ```bash # Lowest price first curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&sort_by=price&sort_order=asc" # Highest price first curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&sort_by=price&sort_order=desc" ``` **Sort by THC:** ```bash # Highest THC first curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&sort_by=thc_percentage&sort_order=desc" ``` **Sort by Name:** ```bash # Alphabetical curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&sort_by=name&sort_order=asc" ``` **Available Sort Fields:** - `id` - `name` - `brand` - `price` - `thc_percentage` - `cbd_percentage` - `last_seen_at` - `created_at` #### Pagination ```bash # Get first page (50 items) curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&limit=50&offset=0" # Get second page curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?store_id=1&limit=50&offset=50" ``` #### Complex Query Example Get affordable indica products sorted by THC: ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products?\ store_id=1&\ strain_type=indica&\ max_price=40&\ min_thc=15&\ in_stock=true&\ sort_by=thc_percentage&\ sort_order=desc&\ limit=20&\ fields=id,name,brand,price,thc_percentage,strain_type,image_url_full" ``` #### Response Format ```json { "products": [ { "id": 123, "name": "Blue Dream 3.5g", "brand": "Cresco Labs", "price": 45.00, "thc_percentage": 24.5, "cbd_percentage": 0.5, "strain_type": "hybrid", "in_stock": true, "image_url_full": "http://localhost:9020/dutchie/products/123/full.jpg", "thumbnail_url": "http://localhost:9020/dutchie/products/123/thumb.jpg", "medium_url": "http://localhost:9020/dutchie/products/123/medium.jpg", "store_name": "Curaleaf - Phoenix", "category_name": "Flower" } ], "total": 145, "limit": 50, "offset": 0, "filters": { "store_id": "1", "category_id": null, "in_stock": "true", "search": null, "brand": null, "min_price": null, "max_price": null, "min_thc": null, "max_thc": null, "strain_type": null, "sort_by": "last_seen_at", "sort_order": "DESC" } } ``` ### Get Single Product **Endpoint:** `GET /products/:id` ```bash # Full product data curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products/123" # With field selection curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products/123?fields=id,name,price,description,image_url_full" ``` ### Get Available Brands (Meta Endpoint) **Endpoint:** `GET /products/meta/brands` Get list of all brands for filter dropdowns: ```bash # All brands curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products/meta/brands" # Brands for specific store curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products/meta/brands?store_id=1" ``` **Response:** ```json { "brands": [ "Cresco Labs", "Select", "Timeless", "Canamo", "Item 9" ] } ``` ### Get Price Range (Meta Endpoint) **Endpoint:** `GET /products/meta/price-range` Get min/max/avg prices for filter sliders: ```bash # All products curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products/meta/price-range" # For specific store curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/products/meta/price-range?store_id=1" ``` **Response:** ```json { "min_price": 15.00, "max_price": 120.00, "avg_price": 42.50 } ``` ## Stores API ### Get All Stores ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/stores" ``` ### Get Single Store ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/stores/1" ``` ### Get Store Brands ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/stores/1/brands" ``` ### Get Store Specials ```bash # Today's specials curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/stores/1/specials" # Specials for specific date curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/stores/1/specials?date=2025-01-15" ``` ### Trigger Store Scrape (Admin) ```bash curl -X POST -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"parallel": 3}' \ "http://localhost:3010/api/stores/1/scrape" ``` ## Categories API ### Get Categories (Flat List) ```bash # All categories curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/categories" # For specific store curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/categories?store_id=1" ``` ### Get Category Tree (Hierarchical) ```bash curl -H "Authorization: Bearer YOUR_TOKEN" \ "http://localhost:3010/api/categories/tree?store_id=1" ``` ## Real-World Usage Examples ### Build a Product Filter UI 1. **Get filter options:** ```javascript // Get brands for dropdown const brands = await fetch('/api/products/meta/brands?store_id=1'); // Get price range for slider const priceRange = await fetch('/api/products/meta/price-range?store_id=1'); // Get categories for checkboxes const categories = await fetch('/api/categories?store_id=1'); ``` 2. **Fetch filtered products:** ```javascript const params = new URLSearchParams({ store_id: '1', brand: selectedBrand, min_price: minPrice, max_price: maxPrice, category_id: selectedCategory, in_stock: 'true', sort_by: 'price', sort_order: 'asc', fields: 'id,name,price,brand,thc_percentage,image_url_full,in_stock' }); const products = await fetch(`/api/products?${params}`); ``` ### Build a WordPress Product Grid ```php // Efficient field selection for grid display $fields = 'id,name,price,brand,thc_percentage,image_url_full,in_stock'; $response = wp_remote_get( "http://localhost:3010/api/products?store_id=1&in_stock=true&limit=12&fields=$fields", ['headers' => ['Authorization' => 'Bearer ' . $token]] ); $data = json_decode(wp_remote_retrieve_body($response)); foreach ($data->products as $product) { // Only contains requested fields = smaller payload echo render_product_card($product); } ``` ### Build Price Comparison Tool ```javascript // Get cheapest products across all stores const cheapProducts = await fetch( '/api/products?in_stock=true&sort_by=price&sort_order=asc&limit=50&fields=id,name,price,store_name' ); // Get highest THC products const strongProducts = await fetch( '/api/products?in_stock=true&min_thc=25&sort_by=thc_percentage&sort_order=desc&limit=50' ); ``` ## Performance Tips 1. **Use Field Selection:** Only request fields you need to reduce bandwidth 2. **Pagination:** Use reasonable `limit` values (50-100) 3. **Caching:** Cache brand lists, price ranges, and category data 4. **Combine Filters:** Use multiple filters to reduce result set size 5. **Index Optimization:** The API uses indexed fields for filtering ## Rate Limits - Standard users: 100 requests/minute - Admin users: 500 requests/minute - Exceeded limits return `429 Too Many Requests` ## Error Responses ```json { "error": "Failed to fetch products" } ``` HTTP Status Codes: - `200` - Success - `400` - Bad Request - `401` - Unauthorized - `404` - Not Found - `429` - Too Many Requests - `500` - Server Error