Files
market-backOfficce/API.md
sdarbinyan 083b270c74 boooomb
2026-02-20 01:46:14 +04:00

9.1 KiB

API Documentation

Endpoint reference for the Marketplace Backoffice.
Base URL: https://your-api-domain.com/api


Projects

Get All Projects

GET /api/projects

Response 200:
[
  {
    "id": "dexar",
    "name": "dexar",
    "displayName": "Dexar Marketplace",
    "active": true,
    "logoUrl": "https://..."
  }
]

Categories

Get Categories for Project

GET /api/projects/:projectId/categories

Response 200:
[
  {
    "id": "cat1",
    "name": "Electronics",
    "visible": true,
    "priority": 1,
    "img": "https://...",
    "projectId": "dexar",
    "subcategories": [ ...Subcategory[] ]
  }
]

Get Single Category

GET /api/categories/:categoryId

Response 200:
{
  "id": "cat1",
  "name": "Electronics",
  "visible": true,
  "priority": 1,
  "img": "https://...",
  "projectId": "dexar",
  "subcategories": [ ...Subcategory[] ]
}

Create Category

POST /api/projects/:projectId/categories

Body:
{
  "name": "New Category",        // required
  "visible": true,
  "priority": 10,
  "img": "https://..."
}

Response 201: (created category object)

Update Category

PATCH /api/categories/:categoryId

Body: (any subset of fields)
{
  "name": "Updated Name",
  "visible": false,
  "priority": 5
}

Response 200: (updated category object)

Delete Category

DELETE /api/categories/:categoryId

Response 204 No Content

Note: Cascades and deletes all subcategories and items under this category

Subcategories

Subcategories are recursive - they can be nested under a root Category or under another Subcategory. The nesting depth is unlimited, with one constraint: a subcategory that already contains items cannot have child subcategories (and vice versa).

Subcategory Object

{
  "id": "sub1",
  "name": "Smartphones",
  "visible": true,
  "priority": 1,
  "img": "https://...",
  "categoryId": "cat1",        // always the ROOT category ID
  "parentId": "cat1",          // direct parent ID (category OR subcategory)
  "itemCount": 15,
  "hasItems": true,
  "subcategories": []          // nested children (empty when hasItems = true)
}

categoryId is always the root-level category this subtree belongs to. parentId is the direct parent - it can be either a category ID or a subcategory ID.


Get Subcategories Under a Category

GET /api/categories/:categoryId/subcategories

Response 200: Subcategory[] (nested subcategories populated recursively)

Get Single Subcategory

GET /api/subcategories/:subcategoryId

Response 200: Subcategory object (with nested subcategories if any)

Create Subcategory Under a Category (level 1)

POST /api/categories/:categoryId/subcategories

Body:
{
  "id": "custom-id",     // optional, auto-generated if omitted (used in URL routing)
  "name": "Smartphones", // required
  "visible": true,
  "priority": 10
}

Response 201: (created subcategory object)
Error 400: if category does not exist

Create Subcategory Under a Parent Subcategory (level 2+, nested)

POST /api/subcategories/:parentSubcategoryId/subcategories

Body:
{
  "id": "custom-id",    // optional, auto-generated if omitted (used in URL routing)
  "name": "Apple",      // required
  "visible": true,
  "priority": 10
}

Response 201: (created subcategory object)
Error 400: if parent subcategory has items (hasItems = true)
Error 404: if parent subcategory does not exist

Update Subcategory

PATCH /api/subcategories/:subcategoryId

Body: (any subset of fields)
{
  "id": "new-slug",     // ID is editable - used for marketplace URL routing
  "name": "Updated Name",
  "visible": false,
  "priority": 3
}

Response 200: (updated subcategory object)

Delete Subcategory

DELETE /api/subcategories/:subcategoryId

Response 204 No Content

Note: Cascades and deletes all nested subcategories and items under this subcategory

Items

Items always belong to the deepest subcategory in the hierarchy (a leaf node). A subcategory with at least one item has hasItems: true and cannot have child subcategories.

Get Items (Paginated)

GET /api/subcategories/:subcategoryId/items

Query Params:
  page     number   (default: 1)
  limit    number   (default: 20)
  search   string   optional - filters by name (case-insensitive)
  visible  boolean  optional - filter by visibility
  tags     string   optional - comma-separated tag list

Response 200:
{
  "items": [
    {
      "id": "item1",
      "name": "iPhone 15 Pro",
      "visible": true,
      "priority": 1,
      "quantity": 50,
      "price": 1299,
      "currency": "USD",
      "imgs": ["https://...", "https://..."],
      "tags": ["new", "featured"],
      "badges": ["new", "exclusive"],
      "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 200: (full item object)

Create Item

POST /api/subcategories/:subcategoryId/items

Body:
{
  "name": "New Product",          // required
  "visible": true,
  "priority": 10,
  "quantity": 100,
  "price": 999,
  "currency": "USD",              // USD | EUR | RUB | GBP | UAH
  "imgs": ["https://..."],
  "tags": ["new"],
  "badges": ["new", "exclusive"],      // optional - predefined or custom badge labels
  "simpleDescription": "Short description",
  "description": [
    { "key": "Size", "value": "Large" }
  ]
}

Response 201: (created item object)

Side effect: Sets hasItems = true on the subcategory.
             The subcategory can no longer receive child subcategories.

Update Item

PATCH /api/items/:itemId

Body: (any subset of fields)
{
  "name": "Updated Name",
  "price": 899,
  "quantity": 80,
  "visible": false
}

Response 200: (updated item object)

Updating images - always send the full array:

PATCH /api/items/:itemId

Body:
{
  "imgs": ["https://new1.jpg", "https://new2.jpg"]
}

Response 200: (updated item object)

Delete Item

DELETE /api/items/:itemId

Response 204 No Content

Side effect: If no items remain in the subcategory, sets hasItems = false.
             The subcategory can then receive child subcategories again.

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 201:
{
  "url": "https://cdn.example.com/uploads/abc123.jpg"
}

Notes

  • All responses are JSON.
  • Use PATCH for partial updates - send only the fields you want to change.
  • priority: lower number = appears first in the list.
  • currency supported values: USD, EUR, RUB, GBP, UAH.
  • badges: optional string array. Predefined values with UI colors: new, sale, exclusive, hot, limited, bestseller, featured. Custom strings are also allowed.
  • imgs: always send the complete array on update, not individual images.
  • description: array of { key, value } pairs - free-form attributes per item.
  • Auto-save from the backoffice fires PATCH with a single field every ~500 ms.

Business Rules

Nested Subcategories

The hierarchy works like this:

Category (e.g. Electronics)
  Subcategory L1 (e.g. Kitchen)          <- can add more children OR items, not both
    Subcategory L2 (e.g. Big Kitchen)    <- same rule
      Subcategory L3 (e.g. Ovens)        <- if this has items, it is a leaf
        Items...

Rules:

  • A category can always receive new subcategories (categories never hold items directly).
  • A subcategory that has items (hasItems: true) cannot receive child subcategories.
    • POST /api/subcategories/:id/subcategories on a node with hasItems: true -> 400 Bad Request.
  • A subcategory that has children cannot have items added to it (items only go to leaf nodes).
  • When the first item is created in a subcategory -> hasItems becomes true.
  • When the last item is deleted -> hasItems becomes false; child subcategories can be added again.

URL Structure (Marketplace Frontend)

Subcategory and item id fields are used directly in the marketplace URL path:

/{categoryId}/{sub1Id}/{sub2Id}/.../{itemId}

Examples:
  /electronics/smartphones/iphone-15
  /electronics/smartphones/apple/iphone-15-pro
  /furniture/living-room/sofas/corner-sofa-modelo

The id field on subcategories is editable via PATCH to allow renaming slugs.

Comments

  • stars is optional, integer 1-5.
  • author is optional (anonymous comments allowed).
  • createdAt is ISO 8601 string.

Cascade Deletes

Delete target Also deletes
Category all subcategories (recursive) and their items
Subcategory all nested subcategories (recursive) and their items
Item nothing else