{"openapi":"3.0.3","info":{"title":"TwentyFiveMade Backend API","version":"0.1.0","description":"OpenAPI documentation for the TwentyFiveMade public storefront and admin APIs."},"servers":[{"url":"https://api.twentyfivemade.com","description":"Production"},{"url":"http://localhost:3000","description":"Local development"}],"tags":[{"name":"Public Products"},{"name":"Admin Auth"},{"name":"Admin Categories"},{"name":"Admin Products"},{"name":"Admin Orders"},{"name":"Admin Leather Types"},{"name":"Admin Storage"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"ErrorResponse":{"type":"object","properties":{"message":{"type":"string","example":"Internal server error"}},"required":["message"]},"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true}},"required":["success"]},"AdminUser":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"}},"required":["id","email"]},"LoginRequest":{"type":"object","properties":{"email":{"type":"string","format":"email","example":"admin@twentyfivemade.com"},"password":{"type":"string","format":"password","example":"your_admin_password"}},"required":["email","password"]},"LoginResponse":{"type":"object","properties":{"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"user":{"$ref":"#/components/schemas/AdminUser"}},"required":["token","user"]},"Category":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Belts"},"description":{"type":"string","nullable":true,"example":"Leather belts category"},"image_url":{"type":"string","nullable":true,"example":"https://cdn.example.com/category.jpg"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","name"]},"CategoryCreateRequest":{"type":"object","properties":{"name":{"type":"string","example":"Belts"},"description":{"type":"string","nullable":true,"example":"Leather belts category"}},"required":["name"]},"CategoryUpdateRequest":{"type":"object","properties":{"name":{"type":"string","example":"Belts Premium"},"description":{"type":"string","nullable":true,"example":"Updated category description"},"image_url":{"type":"string","nullable":true,"example":"https://cdn.example.com/category.jpg"}}},"Product":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Classic Wallet"},"description":{"type":"string","nullable":true,"example":"Handmade leather wallet"},"price":{"type":"number","format":"double","example":49.99},"category_id":{"type":"string","format":"uuid"},"image_url":{"type":"string","nullable":true,"example":"https://cdn.example.com/wallet-1.jpg"},"image_urls":{"type":"array","maxItems":3,"items":{"type":"string"},"example":["https://cdn.example.com/wallet-1.jpg","https://cdn.example.com/wallet-2.jpg"]},"default_image_url":{"type":"string","nullable":true,"example":"https://cdn.example.com/wallet-1.jpg"},"stock":{"type":"integer","example":25},"is_active":{"type":"boolean","example":true},"category":{"$ref":"#/components/schemas/Category"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","name","price","category_id"]},"ProductCreateRequest":{"type":"object","properties":{"name":{"type":"string","example":"Classic Wallet"},"description":{"type":"string","nullable":true,"example":"Handmade leather wallet"},"price":{"type":"number","format":"double","example":49.99},"stock":{"type":"integer","example":25},"category_id":{"type":"string","format":"uuid"},"image_url":{"type":"string","nullable":true,"deprecated":true},"image_urls":{"type":"array","maxItems":3,"items":{"type":"string"},"example":["https://cdn.example.com/wallet-1.jpg","https://cdn.example.com/wallet-2.jpg"]},"default_image_url":{"type":"string","nullable":true,"example":"https://cdn.example.com/wallet-1.jpg"}},"required":["name","price","category_id"]},"ProductUpdateRequest":{"type":"object","properties":{"name":{"type":"string","example":"Classic Wallet - Updated"},"description":{"type":"string","nullable":true},"price":{"type":"number","format":"double","example":54.99},"stock":{"type":"integer","example":20},"category_id":{"type":"string","format":"uuid"},"image_urls":{"type":"array","maxItems":3,"items":{"type":"string"}},"default_image_url":{"type":"string","nullable":true},"is_active":{"type":"boolean"}}},"ImageUploadResponse":{"type":"object","properties":{"path":{"type":"string","example":"products/9d87f5f8-1a2b-4c3d-8e9f-123456789abc.jpg"},"url":{"type":"string","example":"https://example.supabase.co/storage/v1/object/public/product-images/products/image.jpg"}},"required":["path","url"]},"StorageFile":{"type":"object","properties":{"name":{"type":"string","example":"image.jpg"},"id":{"type":"string"},"path":{"type":"string","example":"products/image.jpg"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"metadata":{"type":"object","additionalProperties":true}},"required":["name","path"]},"StorageFilesResponse":{"type":"object","properties":{"bucket":{"type":"string","example":"product-images"},"prefix":{"type":"string","example":"products"},"files":{"type":"array","items":{"$ref":"#/components/schemas/StorageFile"}}},"required":["bucket","prefix","files"]},"OrderItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"order_id":{"type":"string","format":"uuid"},"product_id":{"type":"string","format":"uuid"},"quantity":{"type":"integer","example":2},"unit_price":{"type":"number","format":"double","example":49.99},"created_at":{"type":"string","format":"date-time"}}},"Order":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"customer_name":{"type":"string","example":"Akhil Johnson"},"customer_email":{"type":"string","format":"email","example":"akhil@example.com"},"customer_phone":{"type":"string","nullable":true,"example":"+919999999999"},"total_amount":{"type":"number","format":"double","example":99.98},"order_status":{"type":"string","example":"pending"},"order_items":{"type":"array","items":{"$ref":"#/components/schemas/OrderItem"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"OrderUpdateRequest":{"type":"object","properties":{"order_status":{"type":"string","example":"shipped"}}},"LeatherType":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string","example":"Full Grain"},"company":{"type":"string","nullable":true,"example":"Acme Leather Co"},"tanning_type":{"type":"string","nullable":true,"example":"Vegetable Tanned"},"colour":{"type":"string","nullable":true,"example":"Brown"},"description":{"type":"string","nullable":true,"example":"Premium quality full grain leather"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","name"]},"LeatherTypeCreateRequest":{"type":"object","properties":{"name":{"type":"string","example":"Full Grain"},"company":{"type":"string","nullable":true,"example":"Acme Leather Co"},"tanning_type":{"type":"string","nullable":true,"example":"Vegetable Tanned"},"colour":{"type":"string","nullable":true,"example":"Brown"},"description":{"type":"string","nullable":true,"example":"Premium quality full grain leather"}},"required":["name"]},"LeatherTypeUpdateRequest":{"type":"object","properties":{"name":{"type":"string","example":"Full Grain"},"company":{"type":"string","nullable":true,"example":"Updated Leather Co"},"tanning_type":{"type":"string","nullable":true},"colour":{"type":"string","nullable":true,"example":"Tan"},"description":{"type":"string","nullable":true}}}},"parameters":{"CategoryId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Category id"},"ProductId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Product id"},"OrderId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Order id"},"LeatherTypeId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Leather type id"},"CategoryFilter":{"name":"category_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Filter products by category id"}},"responses":{"Unauthorized":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"message":"Unauthorized"}}}},"BadRequest":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalServerError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"message":"Internal server error"}}}}}},"paths":{"/api/products":{"get":{"tags":["Public Products"],"summary":"List public products","parameters":[{"$ref":"#/components/parameters/CategoryFilter"}],"responses":{"200":{"description":"Products","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}}}},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/login":{"post":{"tags":["Admin Auth"],"summary":"Admin login","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Login token and admin user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/categories":{"get":{"tags":["Admin Categories"],"summary":"List categories","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Categories","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Category"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"post":{"tags":["Admin Categories"],"summary":"Create category","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryCreateRequest"}}}},"responses":{"201":{"description":"Created category","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Category"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/categories/{id}":{"put":{"tags":["Admin Categories"],"summary":"Update category","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/CategoryId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryUpdateRequest"}}}},"responses":{"200":{"description":"Updated category","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Category"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"delete":{"tags":["Admin Categories"],"summary":"Delete category","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/CategoryId"}],"responses":{"200":{"description":"Category deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/products":{"get":{"tags":["Admin Products"],"summary":"List products","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/CategoryFilter"}],"responses":{"200":{"description":"Products","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"post":{"tags":["Admin Products"],"summary":"Create product","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCreateRequest"}}}},"responses":{"201":{"description":"Created product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/products/{id}":{"put":{"tags":["Admin Products"],"summary":"Update product","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ProductId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductUpdateRequest"}}}},"responses":{"200":{"description":"Updated product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Product"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"delete":{"tags":["Admin Products"],"summary":"Delete product","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ProductId"}],"responses":{"200":{"description":"Product deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/products/upload":{"post":{"tags":["Admin Products"],"summary":"Upload one product image","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"JPEG, PNG, or WebP image file"}},"required":["file"]}}}},"responses":{"201":{"description":"Uploaded image path and public URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageUploadResponse"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/storage/files":{"get":{"tags":["Admin Storage"],"summary":"List uploaded storage files","security":[{"bearerAuth":[]}],"parameters":[{"name":"prefix","in":"query","required":false,"schema":{"type":"string","example":"products"},"description":"Folder/prefix to list. Defaults to the bucket root."}],"responses":{"200":{"description":"Storage files","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorageFilesResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/orders":{"get":{"tags":["Admin Orders"],"summary":"List orders","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Orders with order items","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Order"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/orders/{id}":{"patch":{"tags":["Admin Orders"],"summary":"Update order","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/OrderId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUpdateRequest"}}}},"responses":{"200":{"description":"Updated order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/leather-types":{"get":{"tags":["Admin Leather Types"],"summary":"List leather types","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Leather types","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LeatherType"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"post":{"tags":["Admin Leather Types"],"summary":"Create leather type","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeatherTypeCreateRequest"}}}},"responses":{"201":{"description":"Created leather type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeatherType"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}},"/api/admin/leather-types/{id}":{"put":{"tags":["Admin Leather Types"],"summary":"Update leather type","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/LeatherTypeId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeatherTypeUpdateRequest"}}}},"responses":{"200":{"description":"Updated leather type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeatherType"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}},"delete":{"tags":["Admin Leather Types"],"summary":"Delete leather type","security":[{"bearerAuth":[]}],"parameters":[{"$ref":"#/components/parameters/LeatherTypeId"}],"responses":{"200":{"description":"Leather type deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalServerError"}}}}}}