342 lines
6.0 KiB
Markdown
342 lines
6.0 KiB
Markdown
# API Documentation #
|
|
|
|
Simple endpoint reference for the Marketplace Backoffice.
|
|
|
|
## Projects
|
|
|
|
### Get All Projects
|
|
```
|
|
GET /api/projects
|
|
|
|
Response:
|
|
[
|
|
{
|
|
"id": "dexar",
|
|
"name": "dexar",
|
|
"displayName": "Dexar Marketplace",
|
|
"active": true,
|
|
"logoUrl": "https://..."
|
|
}
|
|
]
|
|
```
|
|
|
|
## Categories
|
|
|
|
### Get Categories for Project
|
|
```
|
|
GET /api/projects/:projectId/categories
|
|
|
|
Response:
|
|
[
|
|
{
|
|
"id": "cat1",
|
|
"name": "Electronics",
|
|
"visible": true,
|
|
"priority": 1,
|
|
"img": "https://...",
|
|
"projectId": "dexar",
|
|
"subcategories": [...]
|
|
}
|
|
]
|
|
```
|
|
|
|
### Get Single Category
|
|
```
|
|
GET /api/categories/:categoryId
|
|
|
|
Response:
|
|
{
|
|
"id": "cat1",
|
|
"name": "Electronics",
|
|
"visible": true,
|
|
"priority": 1,
|
|
"img": "https://...",
|
|
"projectId": "dexar",
|
|
"subcategories": [...]
|
|
}
|
|
```
|
|
|
|
### Create Category
|
|
```
|
|
POST /api/projects/:projectId/categories
|
|
|
|
Body:
|
|
{
|
|
"name": "New Category",
|
|
"visible": true,
|
|
"priority": 10,
|
|
"img": "https://..."
|
|
}
|
|
|
|
Response: (created category object)
|
|
```
|
|
|
|
### Update Category
|
|
```
|
|
PATCH /api/categories/:categoryId
|
|
|
|
Body: (any field to update)
|
|
{
|
|
"name": "Updated Name",
|
|
"visible": false,
|
|
"priority": 5
|
|
}
|
|
|
|
Response: (updated category object)
|
|
```
|
|
|
|
### Delete Category
|
|
```
|
|
DELETE /api/categories/:categoryId
|
|
|
|
Response: 204 No Content
|
|
```
|
|
|
|
## Subcategories
|
|
|
|
### Get Subcategories
|
|
```
|
|
GET /api/categories/:categoryId/subcategories
|
|
|
|
Response:
|
|
[
|
|
{
|
|
"id": "sub1",
|
|
"name": "Smartphones",
|
|
"visible": true,
|
|
"priority": 1,
|
|
"img": "https://...",
|
|
"categoryId": "cat1",
|
|
"itemCount": 15,
|
|
"hasItems": true,
|
|
"subcategories": []
|
|
}
|
|
]
|
|
|
|
Note:
|
|
- Subcategories can have nested subcategories (recursive)
|
|
- If hasItems is true, cannot create child subcategories
|
|
```
|
|
|
|
### Get Single Subcategory
|
|
```
|
|
GET /api/subcategories/:subcategoryId
|
|
|
|
Response: (subcategory object with nested subcategories if any)
|
|
```
|
|
|
|
### Create Subcategory
|
|
```
|
|
POST /api/categories/:categoryId/subcategories
|
|
|
|
Note: categoryId can be either a category ID or a parent subcategory ID for nested structure
|
|
|
|
Body:
|
|
{
|
|
"id": "custom-id", // Optional, auto-generated if not provided
|
|
"name": "New Subcategory",
|
|
"visible": true,
|
|
"priority": 10
|
|
}
|
|
|
|
Response: (created subcategory object)
|
|
|
|
Error: Returns 400 if parent subcategory already has items
|
|
```
|
|
|
|
### Update Subcategory
|
|
```
|
|
PATCH /api/subcategories/:subcategoryId
|
|
|
|
Body: (any field)
|
|
{
|
|
"id": "new-id", // ID is now editable (used for routing)
|
|
"name": "Updated Name",
|
|
"visible": false
|
|
}
|
|
|
|
Response: (updated subcategory object)
|
|
```
|
|
|
|
### Delete Subcategory
|
|
```
|
|
DELETE /api/subcategories/:subcategoryId
|
|
|
|
Response: 204 No Content
|
|
```
|
|
|
|
## Items
|
|
|
|
### Get Items (Paginated)
|
|
```
|
|
GET /api/subcategories/:subcategoryId/items?page=1&limit=20&search=phone&visible=true
|
|
|
|
Query Params:
|
|
- page: number (default: 1)
|
|
- limit: number (default: 20)
|
|
- search: string (optional - filters by name)
|
|
- visible: boolean (optional - filters by visibility)
|
|
- tags: string (optional - comma separated tags)
|
|
|
|
Response:
|
|
{
|
|
"items": [
|
|
{
|
|
"id": "item1",
|
|
"name": "iPhone 15 Pro",
|
|
"visible": true,
|
|
"priority": 1,
|
|
"quantity": 50,
|
|
"price": 1299,
|
|
"currency": "USD",
|
|
"imgs": ["https://...", "https://..."],
|
|
"tags": ["new", "featured"],
|
|
"simpleDescription": "Latest iPhone...",
|
|
"description": [
|
|
{ "key": "Color", "value": "Black" },
|
|
{ "key": "Storage", "value": "256GB" }
|
|
],
|
|
"subcategoryId": "sub1",
|
|
"comments": [
|
|
{
|
|
"id": "c1",
|
|
"text": "Great product!",
|
|
"author": "John Doe",
|
|
"stars": 5,
|
|
"createdAt": "2024-01-10T10:30:00Z"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"total": 150,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"hasMore": true
|
|
}
|
|
```
|
|
|
|
### Get Single Item
|
|
```
|
|
GET /api/items/:itemId
|
|
|
|
Response: (item object with all fields)
|
|
```
|
|
|
|
### Create Item
|
|
```
|
|
POST /api/subcategories/:subcategoryId/items
|
|
|
|
Body:
|
|
{
|
|
"name": "New Product",
|
|
"visible": true,
|
|
"priority": 10,
|
|
"quantity": 100,
|
|
"price": 999,
|
|
"currency": "USD",
|
|
"imgs": ["https://..."],
|
|
"tags": ["new"],
|
|
"simpleDescription": "Product description",
|
|
"description": [
|
|
{ "key": "Size", "value": "Large" }
|
|
]
|
|
}
|
|
|
|
Response: (created item object)
|
|
```
|
|
|
|
### Update Item
|
|
```
|
|
PATCH /api/items/:itemId
|
|
|
|
Body: (any field to update)
|
|
{
|
|
"name": "Updated Name",
|
|
"price": 899,
|
|
"quantity": 80,
|
|
"visible": false
|
|
}
|
|
|
|
Response: (updated item object)
|
|
```
|
|
|
|
**Example: Update only images**
|
|
```
|
|
PATCH /api/items/item123
|
|
|
|
Body:
|
|
{
|
|
"imgs": ["https://new-image1.jpg", "https://new-image2.jpg"]
|
|
}
|
|
|
|
Note: Send the complete array of images (not just changed ones)
|
|
Response: (updated item object)
|
|
```
|
|
|
|
### Delete Item
|
|
```
|
|
DELETE /api/items/:itemId
|
|
|
|
Response: 204 No Content
|
|
```
|
|
|
|
### Bulk Update Items
|
|
```
|
|
PATCH /api/items/bulk
|
|
|
|
Body:
|
|
{
|
|
"itemIds": ["item1", "item2", "item3"],
|
|
"data": {
|
|
"visible": true
|
|
}
|
|
}
|
|
|
|
Response: 204 No Content
|
|
```
|
|
|
|
## Upload
|
|
|
|
### Upload Image
|
|
```
|
|
POST /api/upload
|
|
|
|
Body: multipart/form-data
|
|
- image: File
|
|
|
|
Response:
|
|
{
|
|
"url": "https://cdn.example.com/image.jpg"
|
|
}
|
|
```
|
|
|
|
## Notes
|
|
|
|
- All endpoints return JSON
|
|
- Use PATCH for partial updates
|
|
- Priority: lower numbers = appears first
|
|
- Currency codes: USD, EUR, RUB, GBP, UAH
|
|
- Images: array of URLs
|
|
- Description: array of key-value pairs
|
|
- Auto-save triggers PATCH with single field every 500ms
|
|
### Business Rules
|
|
|
|
1. **Nested Subcategories**
|
|
- Subcategories can have unlimited nesting levels
|
|
- A subcategory with items (`hasItems: true`) cannot have child subcategories
|
|
- Creating a subcategory under a parent with items will fail
|
|
|
|
2. **Item Management**
|
|
- When first item is created in a subcategory, `hasItems` is set to true
|
|
- When last item is deleted, `hasItems` is set to false
|
|
- Items belong to the deepest subcategory in the hierarchy
|
|
|
|
3. **Comments**
|
|
- Stars field is optional (1-5 rating)
|
|
- createdAt is ISO 8601 timestamp
|
|
- author is optional (can be anonymous)
|
|
|
|
4. **URL Structure for Marketplace**
|
|
- Items: `/{categoryId}/{subcategoryId}/.../{itemId}`
|
|
- Example: `/electronics/smartphones/iphone-15`
|
|
- Example nested: `/electronics/smartphones/apple/iphone-15` |