{
  "openapi": "3.0.3",
  "info": {
    "title": "Ecom & FileManager API Documentation",
    "version": "1.0.0",
    "license": {
      "name": "MIT",
      "url": "https://github.com/thaihadefi/Ecom/blob/main/LICENSE"
    },
    "description": "Documentation of every API endpoint of the Ecom web application (port 3000) and the FileManager microservice (port 4000). Server-rendered HTML pages are out of scope, apart from the few read-only ones described under Response conventions.\n\n### Base URLs\n- Web application: `http://localhost:3000`\n- FileManager microservice: `http://localhost:4000` (operations under `/files` and `/folders` are served only there)\n\n### Authentication\n- **Customer** and **admin** JSON endpoints (`/api`, `/admin/api`) accept either the HTTP-only cookie (`tokenUser`, `tokenAdmin`), which browsers use, or `Authorization: Bearer <accessToken>`, which API clients use. The login endpoints return `accessToken` in the body and set the cookie; a request that carries an `Authorization` header is authenticated by it alone and its cookies are ignored. The token lasts one day (`expiresIn` says how long); there is no refresh for Bearer clients, so log in again on 401.\n- **FileManager** `/files` and `/folders` endpoints use `Authorization: Bearer <FILE_MANAGER_SECRET>`. `/media` is public. Use a random secret of at least 32 characters; repeated wrong secrets from one address are answered with HTTP 429.\n- Admin endpoints also check a permission (shown on each operation). Every admin write is recorded in the admin activity log.\n\n### Trying requests\nThe Web application serves this documentation itself at `/api-docs/`, which is the place to try customer and admin endpoints: log in through the login endpoint (the cookie is then sent automatically), or paste the returned `accessToken` under \"Authorize\". The Web application sends CORS headers on non-admin routes, so the Vercel copy can reach storefront endpoints with a Bearer token; admin endpoints skip CORS on purpose, so try those from this same-origin copy instead. The FileManager bearer endpoints also work from the Vercel copy when FileManager lists its origin in `FILE_MANAGER_CORS_ORIGINS`.\n\n### Response conventions\n- A successful JSON response has HTTP 200 and `{ \"code\": \"success\", \"message\": \"...\", ...data }`.\n- An error has the matching HTTP status and `{ \"code\": \"error\", \"message\": \"...\" }`: **400** invalid request, **401** not logged in, **403** no permission or not allowed, **404** record not found, **409** conflict with the current state (duplicate value, missing stock, a change that is not allowed), **429** too many attempts (see `Retry-After`), **500** unexpected failure, **502** a service the application depends on (FileManager, email, the shipping carrier) failed, and **503** the store is not fully configured yet for the request (for example, checkout without a warehouse location set).\n- JSON endpoints (`/api`, `/admin/api`) never redirect: without a valid login they answer 401, and without the permission 403, whatever the method. Server-rendered page requests are redirected (302) to the login page, unless they send an `Authorization` header, `Accept: application/json` without `text/html`, or `X-Requested-With: XMLHttpRequest`, which get the same 401 or 403 as the JSON endpoints. FileManager answers 401 when the bearer secret is missing or wrong.\n- The storefront is server-rendered. The few page routes that act as read endpoints (catalog, articles, cart, flagged orders, payment and OAuth redirects) are documented with `text/html` or redirect responses; the other pages are not part of the API.\n- JSON endpoints are plural resources under `/api` (storefront) and `/admin/api` (admin). The HTTP method states the action: `POST` creates, `PUT` and `PATCH` change, `DELETE` removes, and `GET` never changes data. Payment-gateway and OAuth callbacks keep the URLs their providers call.\n- Trash lifecycle of admin resources: `DELETE /{id}` moves a record to the trash, `POST /{id}/restore` restores it and `DELETE /{id}?permanent=true` deletes it for good. The bulk variants take `{ \"ids\": [...] }` on the collection: `POST /trash`, `POST /restore` and `DELETE /`.\n\n### Optional modules\nEach store switches optional modules on or off with `FEATURE_*` environment variables (see the Ecom README). An endpoint of a switched-off module answers **404** like a route that does not exist: chat (`/api/chat-rooms`, `/admin/api/chat-rooms`), AI chat helpers, flagged orders, recommendation jobs, blog (`/api/articles`, `/api/article-categories`, `/admin/api/articles`, `/admin/api/article-categories`), wishlist, compare, reviews (`/api/reviews`, `/admin/api/reviews`), coupons (`/api/coupon-checks`, `/admin/api/coupons`; checkout then refuses a coupon with 400) and loyalty points (checkout ignores `usePoint`).\n\n### Real-time chat (Socket.IO, same origin as the Web app)\nConnect with the auth cookie and `auth: { role: \"user\" | \"admin\", roomId? }`.\n- Client to server: `CLIENT_SEND_MESSAGE`, `CLIENT_TYPING`, `CLIENT_OPEN_CHAT`, `CLIENT_DELETE_MESSAGE`, `ADMIN_OPEN_CHAT`, `ADMIN_TYPING`, `ADMIN_DELETE_ROOM`.\n- Server to client: `SERVER_SEND_MESSAGE`, `SERVER_SEND_STATUS`, `SERVER_MESSAGE_DELIVERED`, `SERVER_DELETE_MESSAGE`, `SERVER_DELETE_ROOM`, `SERVER_ROOM_ASSIGNED`, `SERVER_SEND_CLIENT_TYPING`, `SERVER_SEND_ADMIN_TYPING`, `SERVER_CLIENT_READ`, `SERVER_ADMIN_READ`, `SERVER_ADMIN_STATUS`, `USER_STATUS_ONLINE`, `LIST_USER_ONLINE`."
  },
  "servers": [
    {
      "url": "http://localhost:3000",
      "description": "Ecom Web application (local)"
    }
  ],
  "tags": [
    {
      "name": "Payment & Logistics (VNPAY, ZaloPay, GoShip)",
      "description": "Payment gateway integrations (VNPAY, ZaloPay), webhooks, and GoShip automated courier rates"
    },
    {
      "name": "Client Auth",
      "description": "Customer registration, login, logout, password recovery & social OAuth"
    },
    {
      "name": "Client Products",
      "description": "Product catalog, search suggestions, reviews, and reports"
    },
    {
      "name": "Client Articles",
      "description": "Blog and editorial articles"
    },
    {
      "name": "Client Cart & Checkout",
      "description": "Cart quotes, GoShip logistics, coupon validation, and order creation"
    },
    {
      "name": "Client Wishlist & Compare",
      "description": "Product comparison and customer wishlist resolution"
    },
    {
      "name": "Client Dashboard",
      "description": "Profile, avatar upload, address book CRUD, and email change verification"
    },
    {
      "name": "Client Chat",
      "description": "Real-time customer support chat messages, file upload & rating"
    },
    {
      "name": "Client Contact & Pages",
      "description": "Customer contact inquiry submissions"
    },
    {
      "name": "Admin Auth",
      "description": "Administrative login and session termination"
    },
    {
      "name": "Admin Products",
      "description": "Product lifecycle, multi-status, SEO, recommendations ML, CSV import/export"
    },
    {
      "name": "Admin Categories & Attributes",
      "description": "Catalog taxonomy and variant attributes"
    },
    {
      "name": "Admin Orders",
      "description": "Fulfillment status, CSV export, and Isolation Forest ML bot detection queue"
    },
    {
      "name": "Admin Coupons",
      "description": "Coupon codes, discount types, validity ranges and usage limits"
    },
    {
      "name": "Admin Content & CMS",
      "description": "Articles, dynamic visual blocks, and page layout templates"
    },
    {
      "name": "Admin Access Control",
      "description": "Administrator accounts, customer accounts, and role permissions"
    },
    {
      "name": "Admin Settings & Ops",
      "description": "Third-party API keys (shipping, payment, email, OAuth) and cache flushing"
    },
    {
      "name": "Admin Contact Inquiries",
      "description": "Contact inquiry processing, status changes, and trash lifecycle"
    },
    {
      "name": "Admin Reviews",
      "description": "Review moderation (approve, reject, clear reports, delete)"
    },
    {
      "name": "Admin Chat",
      "description": "Admin side of the support chat: history, status, uploads and AI helpers (live messages use Socket.IO)"
    },
    {
      "name": "Admin File Manager",
      "description": "Admin proxy to the FileManager microservice: browse, upload, rename, move and delete files and folders"
    },
    {
      "name": "Admin Dashboard",
      "description": "Chart data for the admin dashboard"
    },
    {
      "name": "Site Endpoints",
      "description": "Sitemap, robots.txt and the PWA manifest"
    },
    {
      "name": "FileManager Microservice",
      "description": "The standalone media service (port 4000). Every /files and /folders call needs the shared bearer secret; /media is public"
    }
  ],
  "paths": {
    "/admin/api/admin-accounts": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Create admin account",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `account-admin-create`.\n\nThe `email` must not belong to another admin account, and the selected roles may only contain permissions the acting admin holds.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminAccountAdminCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminAccountAdminCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiAdminAccounts"
      },
      "delete": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Permanently delete selected admin accounts",
        "description": "Requires the admin permission `account-admin-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiAdminAccounts"
      }
    },
    "/admin/api/admin-accounts/restore": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Restore selected admin accounts from trash",
        "description": "Requires the admin permission `account-admin-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiAdminAccountsRestore"
      }
    },
    "/admin/api/admin-accounts/trash": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Move selected admin accounts to trash",
        "description": "Requires the admin permission `account-admin-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiAdminAccountsTrash"
      }
    },
    "/admin/api/admin-accounts/{id}": {
      "patch": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Edit admin account",
        "description": "Requires the admin permission `account-admin-edit`.\n\nA superadmin account can only be edited by that superadmin, and you cannot deactivate your own account. The `email` must not belong to another admin account, and the selected roles may only contain permissions the acting admin holds.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminAccountAdminEditByIdBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminAccountAdminEditByIdBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiAdminAccountsById"
      },
      "delete": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Move admin account to trash",
        "description": "Requires the admin permission `account-admin-delete`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiAdminAccountsById"
      }
    },
    "/admin/api/admin-accounts/{id}/password": {
      "put": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Change admin account password",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Password changed.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "accessToken": {
                          "type": "string",
                          "description": "Present only when the admin changed their own password: the tokens issued before the change stop working, so this is the new one."
                        },
                        "tokenType": {
                          "type": "string",
                          "enum": [
                            "Bearer"
                          ]
                        },
                        "expiresIn": {
                          "type": "integer"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `account-admin-change-password`. Rate limited (HTTP 429 when exceeded).\n\nThe password of a superadmin account can only be changed by that superadmin.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminAccountAdminChangePasswordByIdBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminAccountAdminChangePasswordByIdBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "putAdminApiAdminAccountsByIdPassword"
      }
    },
    "/admin/api/admin-accounts/{id}/restore": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Restore admin account from trash",
        "description": "Requires the admin permission `account-admin-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiAdminAccountsByIdRestore"
      }
    },
    "/admin/api/article-categories": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Create article category",
        "description": "Requires the admin permission `article-category-create`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticleCategories"
      },
      "delete": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Permanently delete selected article categories",
        "description": "Requires the admin permission `article-category-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiArticleCategories"
      }
    },
    "/admin/api/article-categories/restore": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Restore selected article categories from trash",
        "description": "Requires the admin permission `article-category-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticleCategoriesRestore"
      }
    },
    "/admin/api/article-categories/trash": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Move selected article categories to trash",
        "description": "Requires the admin permission `article-category-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticleCategoriesTrash"
      }
    },
    "/admin/api/article-categories/{id}": {
      "patch": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Edit article category",
        "description": "Requires the admin permission `article-category-edit`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiArticleCategoriesById"
      },
      "delete": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Move article category to trash",
        "description": "Requires the admin permission `article-category-delete`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiArticleCategoriesById"
      }
    },
    "/admin/api/article-categories/{id}/restore": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Restore article category from trash",
        "description": "Requires the admin permission `article-category-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticleCategoriesByIdRestore"
      }
    },
    "/admin/api/articles": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Create article",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `article-create`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticles"
      },
      "delete": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Permanently delete selected articles",
        "description": "Requires the admin permission `article-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiArticles"
      }
    },
    "/admin/api/articles/restore": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Restore selected articles from trash",
        "description": "Requires the admin permission `article-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticlesRestore"
      }
    },
    "/admin/api/articles/trash": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Move selected articles to trash",
        "description": "Requires the admin permission `article-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticlesTrash"
      }
    },
    "/admin/api/articles/{id}": {
      "patch": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Edit article",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `article-edit`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiArticlesById"
      },
      "delete": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Delete article",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `article-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiArticlesById"
      }
    },
    "/admin/api/articles/{id}/restore": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Restore article from trash",
        "description": "Requires the admin permission `article-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiArticlesByIdRestore"
      }
    },
    "/admin/api/articles/{id}/seo": {
      "patch": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Update article SEO and OpenGraph attributes",
        "description": "Requires the admin permission `article-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SeoBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/SeoBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiArticlesByIdSeo"
      }
    },
    "/admin/api/blocks": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Create visual CMS block with JSON editor payload",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `block-create`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminBlockCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiBlocks"
      }
    },
    "/admin/api/blocks/{id}": {
      "patch": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Edit visual CMS block",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `block-edit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminBlockCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiBlocksById"
      },
      "delete": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Delete visual CMS block",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `block-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiBlocksById"
      }
    },
    "/admin/api/cache": {
      "delete": {
        "tags": [
          "Admin Settings & Ops"
        ],
        "summary": "Clear the application caches (settings, catalog, dashboard)",
        "responses": {
          "200": {
            "description": "Cache cleared.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiCache"
      }
    },
    "/admin/api/chat-rooms/{id}/customer-emotion": {
      "get": {
        "tags": [
          "Admin Chat"
        ],
        "summary": "Analyze the customer's emotion with the AI assistant",
        "description": "Requires the admin permission `chat-list`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiChatRoomsByIdCustomerEmotion"
      }
    },
    "/admin/api/chat-rooms/{id}/reply-refinements": {
      "post": {
        "tags": [
          "Admin Chat"
        ],
        "summary": "Refine a draft reply with the AI assistant",
        "description": "Requires the admin permission `chat-reply`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminChatEditReplyByIdBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminChatEditReplyByIdBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiChatRoomsByIdReplyRefinements"
      }
    },
    "/admin/api/chat-rooms/{id}/reply-suggestion": {
      "get": {
        "tags": [
          "Admin Chat"
        ],
        "summary": "Suggest a reply with the AI assistant",
        "description": "Requires the admin permission `chat-reply`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiChatRoomsByIdReplySuggestion"
      }
    },
    "/admin/api/chat-rooms/{id}/summary": {
      "get": {
        "tags": [
          "Admin Chat"
        ],
        "summary": "Summarize the conversation with the AI assistant",
        "description": "Requires the admin permission `chat-list`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiChatRoomsByIdSummary"
      }
    },
    "/admin/api/chat-rooms/{roomId}": {
      "patch": {
        "tags": [
          "Admin Chat"
        ],
        "summary": "Open or lock a chat room",
        "description": "Requires the admin permission `chat-reply`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "locked"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiChatRoomsByRoomId",
        "parameters": [
          {
            "name": "roomId",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ]
      }
    },
    "/admin/api/chat-rooms/{roomId}/attachments": {
      "post": {
        "tags": [
          "Admin Chat"
        ],
        "summary": "Upload attachments to a chat room",
        "description": "Requires the admin permission `chat-reply`.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "files"
                ],
                "properties": {
                  "files": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Up to 10 files, 10 MB each"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/UploadRejected"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiChatRoomsByRoomIdAttachments",
        "parameters": [
          {
            "name": "roomId",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ]
      }
    },
    "/admin/api/chat-rooms/{roomId}/messages": {
      "get": {
        "tags": [
          "Admin Chat"
        ],
        "summary": "Load a page of messages of a chat room",
        "description": "Requires the admin permission `chat-list`.",
        "parameters": [
          {
            "name": "roomId",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "name": "lastMessageId",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            },
            "description": "Return messages older than this one"
          }
        ],
        "responses": {
          "200": {
            "description": "Result of the action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "messages": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "userUnreadCount": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiChatRoomsByRoomIdMessages"
      }
    },
    "/admin/api/contact-inquiries": {
      "delete": {
        "tags": [
          "Admin Contact Inquiries"
        ],
        "summary": "Permanently delete selected contact inquiries",
        "description": "Requires the admin permission `contact-inquiry-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiContactInquiries"
      }
    },
    "/admin/api/contact-inquiries/restore": {
      "post": {
        "tags": [
          "Admin Contact Inquiries"
        ],
        "summary": "Restore selected contact inquiries from trash",
        "description": "Requires the admin permission `contact-inquiry-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiContactInquiriesRestore"
      }
    },
    "/admin/api/contact-inquiries/trash": {
      "post": {
        "tags": [
          "Admin Contact Inquiries"
        ],
        "summary": "Move selected contact inquiries to trash",
        "description": "Requires the admin permission `contact-inquiry-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiContactInquiriesTrash"
      }
    },
    "/admin/api/contact-inquiries/{id}": {
      "delete": {
        "tags": [
          "Admin Contact Inquiries"
        ],
        "summary": "Soft delete inquiry",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `contact-inquiry-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiContactInquiriesById"
      }
    },
    "/admin/api/contact-inquiries/{id}/restore": {
      "post": {
        "tags": [
          "Admin Contact Inquiries"
        ],
        "summary": "Restore inquiry from trash",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Restored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `contact-inquiry-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiContactInquiriesByIdRestore"
      }
    },
    "/admin/api/contact-inquiries/{id}/status/{status}": {
      "put": {
        "tags": [
          "Admin Contact Inquiries"
        ],
        "summary": "Update inquiry review status",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "status",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Status updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `contact-inquiry-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "putAdminApiContactInquiriesByIdStatusByStatus"
      }
    },
    "/admin/api/coupons": {
      "post": {
        "tags": [
          "Admin Coupons"
        ],
        "summary": "Create discount coupon",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `coupon-create`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminCouponCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminCouponCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiCoupons"
      },
      "delete": {
        "tags": [
          "Admin Coupons"
        ],
        "summary": "Permanently delete selected coupons",
        "description": "Requires the admin permission `coupon-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiCoupons"
      }
    },
    "/admin/api/coupons/restore": {
      "post": {
        "tags": [
          "Admin Coupons"
        ],
        "summary": "Restore selected coupons from trash",
        "description": "Requires the admin permission `coupon-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiCouponsRestore"
      }
    },
    "/admin/api/coupons/trash": {
      "post": {
        "tags": [
          "Admin Coupons"
        ],
        "summary": "Move selected coupons to trash",
        "description": "Requires the admin permission `coupon-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiCouponsTrash"
      }
    },
    "/admin/api/coupons/{id}": {
      "patch": {
        "tags": [
          "Admin Coupons"
        ],
        "summary": "Edit coupon",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `coupon-edit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminCouponCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminCouponCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiCouponsById"
      },
      "delete": {
        "tags": [
          "Admin Coupons"
        ],
        "summary": "Delete coupon",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `coupon-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiCouponsById"
      }
    },
    "/admin/api/coupons/{id}/restore": {
      "post": {
        "tags": [
          "Admin Coupons"
        ],
        "summary": "Restore coupon from trash",
        "description": "Requires the admin permission `coupon-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiCouponsByIdRestore"
      }
    },
    "/admin/api/customer-accounts": {
      "delete": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Permanently delete selected customer accounts",
        "description": "Requires the admin permission `account-user-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiCustomerAccounts"
      }
    },
    "/admin/api/customer-accounts/restore": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Restore selected customer accounts from trash",
        "description": "Requires the admin permission `account-user-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiCustomerAccountsRestore"
      }
    },
    "/admin/api/customer-accounts/trash": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Move selected customer accounts to trash",
        "description": "Requires the admin permission `account-user-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiCustomerAccountsTrash"
      }
    },
    "/admin/api/customer-accounts/{id}": {
      "delete": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Move customer account to trash",
        "description": "Requires the admin permission `account-user-delete`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiCustomerAccountsById"
      }
    },
    "/admin/api/customer-accounts/{id}/restore": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Restore customer account from trash",
        "description": "Requires the admin permission `account-user-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiCustomerAccountsByIdRestore"
      }
    },
    "/admin/api/files": {
      "post": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Upload files to the media store",
        "description": "Requires the admin permission `file-manager`.",
        "parameters": [
          {
            "name": "folderPath",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Target folder (default: root)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "files"
                ],
                "properties": {
                  "files": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Up to 20 files, 10 MB each"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/UploadRejected"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiFiles"
      },
      "delete": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Delete a file",
        "description": "Requires the admin permission `file-manager`.",
        "parameters": [
          {
            "name": "folder",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fileName",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiFiles"
      }
    },
    "/admin/api/files/location": {
      "patch": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Move a file to another folder",
        "description": "Requires the admin permission `file-manager`.\n\nMoving a file into the folder it is already in is rejected.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerMoveFileBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerMoveFileBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiFilesLocation"
      }
    },
    "/admin/api/files/name": {
      "patch": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Rename a file",
        "description": "Requires the admin permission `file-manager`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerChangeFileNameBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerChangeFileNameBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiFilesName"
      }
    },
    "/admin/api/flagged-orders/retraining": {
      "post": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Trigger manual retrain of anomaly detection model",
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `order-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiFlaggedOrdersRetraining"
      },
      "get": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Progress of the anomaly model retrain job",
        "description": "Requires the admin permission `order-edit`.",
        "responses": {
          "200": {
            "description": "Result of the action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "status": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiFlaggedOrdersRetraining"
      }
    },
    "/admin/api/flagged-orders/{id}": {
      "delete": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Dismiss anomaly flag from order",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Flag dismissed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `order-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiFlaggedOrdersById"
      }
    },
    "/admin/api/folders": {
      "post": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Create a folder",
        "description": "Requires the admin permission `file-manager`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminFileManagerFolderCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminFileManagerFolderCreateBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiFolders"
      },
      "delete": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Delete a folder",
        "description": "Requires the admin permission `file-manager`.",
        "parameters": [
          {
            "name": "folderPath",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiFolders"
      }
    },
    "/admin/api/folders/location": {
      "patch": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Move a folder",
        "description": "Requires the admin permission `file-manager`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerFolderMoveBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerFolderMoveBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiFoldersLocation"
      }
    },
    "/admin/api/folders/name": {
      "patch": {
        "tags": [
          "Admin File Manager"
        ],
        "summary": "Rename a folder",
        "description": "Requires the admin permission `file-manager`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerFolderRenameBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerFolderRenameBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiFoldersName"
      }
    },
    "/admin/api/orders": {
      "delete": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Permanently delete selected orders",
        "description": "Requires the admin permission `order-delete`.\n\n`ids` must be a non-empty array of ids.\n\nOnly orders whose status is `cancelled` or `returned` can be deleted; other orders are rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiOrders"
      }
    },
    "/admin/api/orders/csv": {
      "get": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Export orders to CSV with formula protection",
        "responses": {
          "200": {
            "description": "The CSV file, sent as an attachment named `orders.csv`.",
            "headers": {
              "Content-Disposition": {
                "description": "attachment; filename=\"orders.csv\"",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `order-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiOrdersCsv"
      }
    },
    "/admin/api/orders/restore": {
      "post": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Restore selected orders from trash",
        "description": "Requires the admin permission `order-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiOrdersRestore"
      }
    },
    "/admin/api/orders/trash": {
      "post": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Move selected orders to trash",
        "description": "Requires the admin permission `order-delete`.\n\n`ids` must be a non-empty array of ids.\n\nOnly orders whose status is `cancelled` or `returned` can be deleted; other orders are rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiOrdersTrash"
      }
    },
    "/admin/api/orders/{id}": {
      "patch": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Update order and payment status",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Cancelling or returning an order releases its stock, coupon usage and loyalty points exactly once. Completing a paid order grants loyalty points.\n\nRequires the admin permission `order-edit`.\n\nAn order that is `completed`, `cancelled` or `returned` can no longer change its status, and a `paid` order cannot be set back to `unpaid`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminOrderEditByIdBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminOrderEditByIdBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiOrdersById"
      },
      "delete": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Move order to trash",
        "description": "Requires the admin permission `order-delete`.\n\nOnly orders whose status is `cancelled` or `returned` can be deleted; other orders are rejected with `code: \"error\"`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiOrdersById"
      }
    },
    "/admin/api/orders/{id}/restore": {
      "post": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "Restore order from trash",
        "description": "Requires the admin permission `order-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiOrdersByIdRestore"
      }
    },
    "/admin/api/product-attributes": {
      "post": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Create product variant attribute",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-create`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductAttributeCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductAttributeCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductAttributes"
      }
    },
    "/admin/api/product-attributes/{id}": {
      "patch": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Edit product attribute",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-edit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductAttributeCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductAttributeCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiProductAttributesById"
      },
      "delete": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Delete product attribute",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiProductAttributesById"
      }
    },
    "/admin/api/product-attributes/{id}/restore": {
      "post": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Restore product attribute from trash",
        "description": "Requires the admin permission `product-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductAttributesByIdRestore"
      }
    },
    "/admin/api/product-categories": {
      "post": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Create category",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-create`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductCategories"
      },
      "delete": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Permanently delete selected product categories",
        "description": "Requires the admin permission `product-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiProductCategories"
      }
    },
    "/admin/api/product-categories/restore": {
      "post": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Restore selected product categories from trash",
        "description": "Requires the admin permission `product-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductCategoriesRestore"
      }
    },
    "/admin/api/product-categories/trash": {
      "post": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Move selected product categories to trash",
        "description": "Requires the admin permission `product-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductCategoriesTrash"
      }
    },
    "/admin/api/product-categories/{id}": {
      "patch": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Edit category",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-edit`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminArticleCategoryCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiProductCategoriesById"
      },
      "delete": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Soft delete category",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiProductCategoriesById"
      }
    },
    "/admin/api/product-categories/{id}/restore": {
      "post": {
        "tags": [
          "Admin Categories & Attributes"
        ],
        "summary": "Restore category",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Restored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductCategoriesByIdRestore"
      }
    },
    "/admin/api/products": {
      "post": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Create new product",
        "responses": {
          "200": {
            "description": "Product created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-create`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProducts"
      },
      "delete": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Permanently delete selected products",
        "description": "Requires the admin permission `product-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiProducts"
      }
    },
    "/admin/api/products/csv": {
      "post": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Import products from CSV file upload",
        "responses": {
          "200": {
            "description": "Import status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/UploadRejected"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-create`.\n\nSend the file in the `file` field as `multipart/form-data`. It must be a `text/csv` file of at most 5 MB.",
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The CSV file (`text/csv`), at most 5 MB."
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductsCsv"
      },
      "get": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Export product catalog to CSV with formula injection neutralization",
        "responses": {
          "200": {
            "description": "The CSV file, sent as an attachment named `products.csv`.",
            "headers": {
              "Content-Disposition": {
                "description": "attachment; filename=\"products.csv\"",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiProductsCsv"
      }
    },
    "/admin/api/products/restore": {
      "post": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Restore selected products from trash",
        "description": "Requires the admin permission `product-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductsRestore"
      }
    },
    "/admin/api/products/trash": {
      "post": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Move selected products to trash",
        "description": "Requires the admin permission `product-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductsTrash"
      }
    },
    "/admin/api/products/{id}": {
      "patch": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Update product",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-edit`.\n\nThe `slug` must be unique; a slug already used by another record is rejected with `code: \"error\"`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminProductCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiProductsById"
      },
      "delete": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Move product to trash",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Soft deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiProductsById"
      }
    },
    "/admin/api/products/{id}/restore": {
      "post": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Restore product from trash",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Restored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiProductsByIdRestore"
      }
    },
    "/admin/api/products/{id}/seo": {
      "patch": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Update product SEO and OpenGraph attributes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SEO updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `product-edit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductSeoBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ProductSeoBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiProductsByIdSeo"
      }
    },
    "/admin/api/recommendation-jobs": {
      "post": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Trigger ML Item-based Collaborative Filtering recompute",
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `product-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiRecommendationJobs"
      }
    },
    "/admin/api/recommendation-jobs/latest": {
      "get": {
        "tags": [
          "Admin Products"
        ],
        "summary": "Progress of the recommendation recompute job",
        "description": "Requires the admin permission `product-edit`.",
        "responses": {
          "200": {
            "description": "Result of the action.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "status": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiRecommendationJobsLatest"
      }
    },
    "/admin/api/reviews": {
      "delete": {
        "tags": [
          "Admin Reviews"
        ],
        "summary": "Permanently delete selected reviews",
        "description": "Requires the admin permission `review-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiReviews"
      }
    },
    "/admin/api/reviews/{id}": {
      "delete": {
        "tags": [
          "Admin Reviews"
        ],
        "summary": "Permanently delete a review",
        "description": "Requires the admin permission `review-delete`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiReviewsById"
      }
    },
    "/admin/api/reviews/{id}/reports": {
      "delete": {
        "tags": [
          "Admin Reviews"
        ],
        "summary": "Clear the customer reports on a review",
        "description": "Requires the admin permission `review-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiReviewsByIdReports"
      }
    },
    "/admin/api/reviews/{id}/status/{status}": {
      "put": {
        "tags": [
          "Admin Reviews"
        ],
        "summary": "Approve or reject a review",
        "description": "Requires the admin permission `review-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "status",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "approved",
                "rejected"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "putAdminApiReviewsByIdStatusByStatus"
      }
    },
    "/admin/api/roles": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Create administrative role",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `role-create`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminRoleCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminRoleCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiRoles"
      },
      "delete": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Permanently delete selected roles",
        "description": "Requires the admin permission `role-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiRoles"
      }
    },
    "/admin/api/roles/restore": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Restore selected roles from trash",
        "description": "Requires the admin permission `role-edit`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiRolesRestore"
      }
    },
    "/admin/api/roles/trash": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Move selected roles to trash",
        "description": "Requires the admin permission `role-delete`.\n\n`ids` must be a non-empty array of ids.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdsBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiRolesTrash"
      }
    },
    "/admin/api/roles/{id}": {
      "patch": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Edit administrative role",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `role-edit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminRoleCreateBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminRoleCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiRolesById"
      },
      "delete": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Move role to trash",
        "description": "Requires the admin permission `role-delete`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          },
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "description": "`true` deletes the record permanently instead of moving it to the trash.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiRolesById"
      }
    },
    "/admin/api/roles/{id}/restore": {
      "post": {
        "tags": [
          "Admin Access Control"
        ],
        "summary": "Restore role from trash",
        "description": "Requires the admin permission `role-edit`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiRolesByIdRestore"
      }
    },
    "/admin/api/sessions": {
      "post": {
        "tags": [
          "Admin Auth"
        ],
        "summary": "Admin credentials login",
        "responses": {
          "200": {
            "description": "Admin authenticated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginBody"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/LoginBody"
              }
            }
          }
        },
        "security": [],
        "operationId": "postAdminApiSessions"
      }
    },
    "/admin/api/sessions/current": {
      "delete": {
        "tags": [
          "Admin Auth"
        ],
        "summary": "Admin sign out",
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiSessionsCurrent"
      }
    },
    "/admin/api/settings/email": {
      "patch": {
        "tags": [
          "Admin Settings & Ops"
        ],
        "summary": "Configure Gmail app password for OTP delivery",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminSettingApiAppPasswordBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiSettingsEmail"
      }
    },
    "/admin/api/settings/general": {
      "patch": {
        "tags": [
          "Admin Settings & Ops"
        ],
        "summary": "Update website branding, logo, and title",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminSettingGeneralBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiSettingsGeneral"
      }
    },
    "/admin/api/settings/payment": {
      "patch": {
        "tags": [
          "Admin Settings & Ops",
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "Choose checkout payment methods and configure VNPAY and ZaloPay credentials",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminSettingApiPaymentBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiSettingsPayment"
      }
    },
    "/admin/api/settings/shipping": {
      "patch": {
        "tags": [
          "Admin Settings & Ops",
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "Configure GoShip and the default parcel weight",
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "defaultItemWeight": {
                    "oneOf": [
                      {
                        "type": "number",
                        "minimum": 0,
                        "maximum": 10000000
                      },
                      {
                        "type": "string",
                        "enum": [
                          ""
                        ]
                      }
                    ],
                    "description": "Grams per unit for products without their own weight; an empty string clears it."
                  },
                  "goshipApiUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 500
                  },
                  "tokenGoShip": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiSettingsShipping"
      }
    },
    "/admin/api/settings/storefront": {
      "patch": {
        "tags": [
          "Admin Settings & Ops"
        ],
        "summary": "Set the theme, currency, locale, time zone and loyalty point rates",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminSettingStorefrontBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`. The store currency is what prices are entered in and orders are charged in; changing it does not convert existing prices.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiSettingsStorefront"
      }
    },
    "/admin/api/settings/pages": {
      "patch": {
        "tags": [
          "Admin Settings & Ops"
        ],
        "summary": "Set the text of the About, FAQ and policy pages",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminSettingPagesBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`. The HTML is sanitized when shown; an empty page keeps its default text.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiSettingsPages"
      }
    },
    "/admin/api/settings/social-login": {
      "patch": {
        "tags": [
          "Admin Settings & Ops"
        ],
        "summary": "Configure Google & Facebook OAuth app credentials",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminSettingApiLoginSocialBody"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `setting-edit`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiSettingsSocialLogin"
      }
    },
    "/admin/api/slugs": {
      "post": {
        "tags": [
          "Admin Settings & Ops"
        ],
        "summary": "Generate unique SEO slug for entity title",
        "description": "Requires an admin session; no specific permission is checked.",
        "responses": {
          "200": {
            "description": "Generated slug.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "modalName": {
                    "type": "string"
                  },
                  "string": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiSlugs"
      }
    },
    "/admin/api/statistics/orders": {
      "get": {
        "tags": [
          "Admin Dashboard"
        ],
        "summary": "Order statistics for a custom date range",
        "description": "Requires the admin permission `dashboard`.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD"
          }
        ],
        "responses": {
          "200": {
            "description": "Chart data (`code: error` for an invalid range)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiStatisticsOrders"
      }
    },
    "/admin/api/statistics/revenue-by-time": {
      "get": {
        "tags": [
          "Admin Dashboard"
        ],
        "summary": "Revenue series for a custom date range",
        "description": "Requires the admin permission `dashboard`.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD (year 2000 or later, not after next year)"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD, not before `from`"
          }
        ],
        "responses": {
          "200": {
            "description": "Chart data (`code: error` for an invalid range)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "granularity": {
                      "type": "string",
                      "enum": [
                        "hour",
                        "day",
                        "month"
                      ]
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "getAdminApiStatisticsRevenueByTime"
      }
    },
    "/admin/api/templates": {
      "post": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Create page layout template with ordered block sequences",
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `template-create`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminTemplateCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "postAdminApiTemplates"
      }
    },
    "/admin/api/templates/{id}": {
      "patch": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Edit page layout template",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `template-edit`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminTemplateCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "patchAdminApiTemplatesById"
      },
      "delete": {
        "tags": [
          "Admin Content & CMS"
        ],
        "summary": "Delete page layout template",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Requires the admin permission `template-delete`.",
        "security": [
          {
            "AdminCookie": []
          },
          {
            "AdminBearer": []
          }
        ],
        "operationId": "deleteAdminApiTemplatesById"
      }
    },
    "/admin/order/flagged": {
      "get": {
        "tags": [
          "Admin Orders"
        ],
        "summary": "List orders flagged by Isolation Forest fraud detection",
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          },
          "302": {
            "$ref": "#/components/responses/RedirectToLogin"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          }
        },
        "description": "Requires the admin permission `order-edit`.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "security": [
          {
            "AdminCookie": []
          }
        ],
        "operationId": "getAdminOrderFlagged"
      }
    },
    "/api/article-categories/{slug}/views": {
      "post": {
        "tags": [
          "Client Articles"
        ],
        "summary": "Count a view of an article category",
        "description": "Called by the page once it has loaded, because opening a page (GET) never changes data. A browser is counted once per 30 minutes.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "operationId": "postApiArticleCategoriesBySlugViews",
        "security": []
      }
    },
    "/api/articles/{slug}/views": {
      "post": {
        "tags": [
          "Client Articles"
        ],
        "summary": "Count a view of an article",
        "description": "Called by the page once it has loaded, because opening a page (GET) never changes data. A browser is counted once per 30 minutes.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "operationId": "postApiArticlesBySlugViews",
        "security": []
      }
    },
    "/api/cart/quote": {
      "post": {
        "tags": [
          "Client Cart & Checkout",
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "Get verified cart lines and shipping options",
        "responses": {
          "200": {
            "description": "Cart quote with verified prices and shipping options.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CartQuoteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "cart"
                ],
                "properties": {
                  "cart": {
                    "type": "array",
                    "maxItems": 100,
                    "items": {
                      "type": "object",
                      "required": [
                        "productId",
                        "quantity"
                      ],
                      "properties": {
                        "productId": {
                          "type": "string"
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "variant": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    }
                  },
                  "userAddress": {
                    "type": "object",
                    "properties": {
                      "latitude": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                      },
                      "longitude": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "operationId": "postApiCartQuote",
        "security": []
      }
    },
    "/api/chat-rooms/current/attachments": {
      "post": {
        "tags": [
          "Client Chat"
        ],
        "summary": "Upload images or files to chat room",
        "responses": {
          "200": {
            "description": "Uploaded chat attachments.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/UploadRejected"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "files"
                ],
                "properties": {
                  "files": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Up to 10 files, 10 MB each; only allowed file types."
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "postApiChatRoomsCurrentAttachments"
      }
    },
    "/api/chat-rooms/current/messages": {
      "get": {
        "tags": [
          "Client Chat"
        ],
        "summary": "Fetch paginated chat messages for current session",
        "responses": {
          "200": {
            "description": "Chat message history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "parameters": [
          {
            "name": "lastMessageId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "operationId": "getApiChatRoomsCurrentMessages",
        "security": []
      }
    },
    "/api/chat-rooms/current/rating": {
      "put": {
        "tags": [
          "Client Chat"
        ],
        "summary": "Rate the support conversation",
        "responses": {
          "200": {
            "description": "Rating saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "stars"
                ],
                "properties": {
                  "stars": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "comment": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "putApiChatRoomsCurrentRating"
      }
    },
    "/api/compare/lookup": {
      "post": {
        "tags": [
          "Client Wishlist & Compare"
        ],
        "summary": "Fetch multi-product comparison specs by IDs",
        "responses": {
          "200": {
            "description": "Resolved comparison matrix.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostCompareListBody"
              }
            }
          }
        },
        "operationId": "postApiCompareLookup",
        "security": []
      }
    },
    "/api/contact-inquiries": {
      "post": {
        "tags": [
          "Client Contact & Pages"
        ],
        "summary": "Submit contact inquiry message (rate-limited)",
        "responses": {
          "200": {
            "description": "Inquiry saved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 5,
                    "maxLength": 50
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "subject": {
                    "type": "string",
                    "minLength": 5,
                    "maxLength": 100,
                    "description": "Empty string allowed."
                  },
                  "message": {
                    "type": "string",
                    "minLength": 10,
                    "maxLength": 500
                  }
                },
                "required": [
                  "name",
                  "email",
                  "message"
                ]
              }
            }
          }
        },
        "operationId": "postApiContactInquiries",
        "security": []
      }
    },
    "/api/coupon-checks": {
      "post": {
        "tags": [
          "Client Cart & Checkout"
        ],
        "summary": "Verify discount coupon code and return discount amount",
        "responses": {
          "200": {
            "description": "Coupon validity and discount value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "coupon": {
                    "type": "string"
                  }
                },
                "required": [
                  "coupon"
                ]
              }
            }
          }
        },
        "operationId": "postApiCouponChecks",
        "security": []
      }
    },
    "/api/customers": {
      "post": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Register customer account",
        "responses": {
          "200": {
            "description": "Registration response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fullName": {
                    "type": "string",
                    "minLength": 5,
                    "maxLength": 50
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 8
                  }
                },
                "required": [
                  "fullName",
                  "email",
                  "phone",
                  "password"
                ]
              }
            }
          }
        },
        "operationId": "postApiCustomers",
        "security": []
      }
    },
    "/api/customers/me": {
      "patch": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Update customer profile information",
        "responses": {
          "200": {
            "description": "Profile updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fullName": {
                    "type": "string",
                    "minLength": 5,
                    "maxLength": 50
                  },
                  "phone": {
                    "type": "string",
                    "description": "Empty string allowed."
                  }
                },
                "required": [
                  "fullName"
                ]
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "patchApiCustomersMe"
      }
    },
    "/api/customers/me/addresses": {
      "post": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Add delivery address",
        "responses": {
          "200": {
            "description": "Address created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostDashboardAddressCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "postApiCustomersMeAddresses"
      }
    },
    "/api/customers/me/addresses/{id}": {
      "patch": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Edit delivery address",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Address updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostDashboardAddressCreateBody"
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "patchApiCustomersMeAddressesById"
      },
      "delete": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Delete delivery address",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Address deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "deleteApiCustomersMeAddressesById"
      }
    },
    "/api/customers/me/addresses/{id}/default": {
      "put": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Set address as default shipping address",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Default address updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "putApiCustomersMeAddressesByIdDefault"
      }
    },
    "/api/customers/me/avatar": {
      "put": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Upload and update customer profile avatar",
        "responses": {
          "200": {
            "description": "Avatar updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/UploadRejected"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "avatar"
                ],
                "properties": {
                  "avatar": {
                    "type": "string",
                    "format": "binary",
                    "description": "A JPG, PNG, GIF or WEBP image, at most 5 MB."
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "putApiCustomersMeAvatar"
      }
    },
    "/api/customers/me/email": {
      "put": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Verify OTP and confirm email change",
        "description": "The code is valid for 10 minutes and accepts at most 5 attempts.",
        "responses": {
          "200": {
            "description": "Email updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "otp": {
                    "type": "string",
                    "maxLength": 6,
                    "minLength": 6
                  }
                },
                "required": [
                  "otp"
                ]
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "putApiCustomersMeEmail"
      }
    },
    "/api/customers/me/email-changes": {
      "post": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Request email change OTP code",
        "responses": {
          "200": {
            "description": "OTP sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).\n\nThe new email must differ from the current one and must not belong to another account. The code sent to it is valid for 10 minutes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "newEmail": {
                    "type": "string",
                    "format": "email"
                  }
                },
                "required": [
                  "newEmail"
                ]
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "postApiCustomersMeEmailChanges"
      }
    },
    "/api/customers/me/password": {
      "put": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Set new password after OTP verification",
        "responses": {
          "200": {
            "description": "Password reset successful.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminAccountAdminChangePasswordByIdBody"
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "putApiCustomersMePassword"
      }
    },
    "/api/orders": {
      "post": {
        "tags": [
          "Client Cart & Checkout"
        ],
        "summary": "Create and place order (COD, VNPAY, ZaloPay) with atomic loyalty point deduction",
        "description": "The order is rejected when an item is no longer available or when the coupon has reached its usage limit.",
        "responses": {
          "200": {
            "description": "Order created; `redirectUrl` says where the customer goes next.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreatedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fullName": {
                    "type": "string",
                    "minLength": 5,
                    "maxLength": 50
                  },
                  "phone": {
                    "type": "string"
                  },
                  "address": {
                    "type": "string"
                  },
                  "longitude": {
                    "type": "number"
                  },
                  "latitude": {
                    "type": "number"
                  },
                  "note": {
                    "type": "string",
                    "description": "Empty string allowed."
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "productId": {
                          "type": "string"
                        },
                        "quantity": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 999
                        },
                        "checked": {
                          "type": "boolean"
                        },
                        "variant": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "attrId": {
                                "type": "string"
                              },
                              "value": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "attrType": {
                                "type": "string",
                                "description": "Empty string allowed."
                              }
                            },
                            "required": [
                              "attrId",
                              "value",
                              "label"
                            ]
                          }
                        }
                      },
                      "required": [
                        "productId",
                        "quantity"
                      ]
                    },
                    "minItems": 1
                  },
                  "coupon": {
                    "type": "string",
                    "description": "Empty string allowed."
                  },
                  "paymentMethod": {
                    "type": "string",
                    "enum": [
                      "money",
                      "vnpay",
                      "zalopay"
                    ]
                  },
                  "shippingMethod": {
                    "type": "string",
                    "description": "The `id` of a rate from the cart quote's `shippingOptions`."
                  },
                  "usePoint": {
                    "type": "boolean"
                  },
                  "usedPoint": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Number of loyalty points to redeem."
                  }
                },
                "required": [
                  "fullName",
                  "phone",
                  "address",
                  "longitude",
                  "latitude",
                  "items",
                  "paymentMethod",
                  "shippingMethod"
                ]
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "postApiOrders"
      }
    },
    "/api/password-resets": {
      "post": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Request OTP password reset code",
        "responses": {
          "200": {
            "description": "Generic confirmation message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).\n\nThe code is valid for 5 minutes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        },
        "operationId": "postApiPasswordResets",
        "security": []
      }
    },
    "/api/password-resets/verification": {
      "post": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Verify password reset OTP",
        "responses": {
          "200": {
            "description": "OTP verified.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).\n\nThe code is valid for 5 minutes and accepts at most 5 attempts.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "otp": {
                    "type": "string"
                  }
                },
                "required": [
                  "email",
                  "otp"
                ]
              }
            }
          }
        },
        "operationId": "postApiPasswordResetsVerification",
        "security": []
      }
    },
    "/api/product-categories/{slug}/views": {
      "post": {
        "tags": [
          "Client Products"
        ],
        "summary": "Count a view of a product category",
        "description": "Called by the page once it has loaded, because opening a page (GET) never changes data. A browser is counted once per 30 minutes.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "operationId": "postApiProductCategoriesBySlugViews",
        "security": []
      }
    },
    "/api/product-suggestions": {
      "get": {
        "tags": [
          "Client Products"
        ],
        "summary": "Realtime auto-complete search suggestions",
        "parameters": [
          {
            "name": "keyword",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of matching product suggestions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "operationId": "getApiProductSuggestions",
        "security": []
      }
    },
    "/api/products/{slug}/views": {
      "post": {
        "tags": [
          "Client Products"
        ],
        "summary": "Count a view of a product",
        "description": "Called by the page once it has loaded, because opening a page (GET) never changes data. A browser is counted once per 30 minutes. It also adds the product to the recently viewed list kept in a cookie.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "operationId": "postApiProductsBySlugViews",
        "security": []
      }
    },
    "/api/reviews": {
      "post": {
        "tags": [
          "Client Dashboard"
        ],
        "summary": "Submit product review with photo uploads from order history",
        "description": "Only products from `completed` orders can be reviewed. To attach photos, send the request as `multipart/form-data` with up to 5 JPG, PNG, GIF or WEBP images (5 MB each) in the `images` field.",
        "responses": {
          "200": {
            "description": "Review submitted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/UploadRejected"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "502": {
            "$ref": "#/components/responses/BadGateway"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orderId": {
                    "type": "string"
                  },
                  "orderItemId": {
                    "type": "string"
                  },
                  "rating": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "comment": {
                    "type": "string",
                    "maxLength": 300
                  }
                },
                "required": [
                  "orderId",
                  "orderItemId",
                  "rating",
                  "comment"
                ]
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "orderId": {
                    "type": "string"
                  },
                  "orderItemId": {
                    "type": "string"
                  },
                  "rating": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "comment": {
                    "type": "string",
                    "maxLength": 300
                  },
                  "images": {
                    "type": "array",
                    "maxItems": 5,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Up to 5 JPG, PNG, GIF or WEBP images, at most 5 MB each."
                  }
                },
                "required": [
                  "orderId",
                  "orderItemId",
                  "rating",
                  "comment"
                ]
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "postApiReviews"
      }
    },
    "/api/reviews/{id}/reports": {
      "post": {
        "tags": [
          "Client Products"
        ],
        "summary": "Report an inappropriate product review",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/ObjectId"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Report registered.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "UserCookie": []
          },
          {
            "UserBearer": []
          }
        ],
        "operationId": "postApiReviewsByIdReports"
      }
    },
    "/api/sessions": {
      "post": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Customer login",
        "responses": {
          "200": {
            "description": "Login response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/PermissionDenied"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginBody"
              }
            }
          }
        },
        "operationId": "postApiSessions",
        "security": []
      }
    },
    "/api/sessions/current": {
      "delete": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Customer sign out",
        "description": "Ends the session, clears the auth cookies and revokes the refresh token. State-changing, so it is POST only.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/StandardResult"
          }
        },
        "operationId": "deleteApiSessionsCurrent",
        "security": []
      },
      "get": {
        "tags": [
          "Client Chat"
        ],
        "summary": "Verify or create support chat session",
        "responses": {
          "200": {
            "description": "Session data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          }
        },
        "operationId": "getApiSessionsCurrent",
        "security": []
      }
    },
    "/api/wishlist/lookup": {
      "post": {
        "tags": [
          "Client Wishlist & Compare"
        ],
        "summary": "Fetch product details for wishlist item IDs",
        "responses": {
          "200": {
            "description": "Resolved wishlist items.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostCompareListBody"
              }
            }
          }
        },
        "operationId": "postApiWishlistLookup",
        "security": []
      }
    },
    "/article": {
      "get": {
        "tags": [
          "Client Articles"
        ],
        "summary": "List blog and news articles",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          },
          "302": {
            "description": "Redirect (record not found, not signed in, or wrong state)"
          }
        },
        "operationId": "getArticle",
        "security": []
      }
    },
    "/article/detail/{slug}": {
      "get": {
        "tags": [
          "Client Articles"
        ],
        "summary": "Read article detail by slug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          },
          "302": {
            "description": "Redirect (record not found, not signed in, or wrong state)"
          }
        },
        "operationId": "getArticleDetailBySlug",
        "security": []
      }
    },
    "/auth/facebook": {
      "get": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Initiate Facebook OAuth2 authentication flow",
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          }
        },
        "operationId": "getAuthFacebook",
        "security": []
      }
    },
    "/auth/facebook/callback": {
      "get": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Facebook OAuth callback",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to the storefront after sign-in, or to /auth/login on failure"
          }
        },
        "operationId": "getAuthFacebookCallback",
        "security": []
      }
    },
    "/auth/google": {
      "get": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Initiate Google OAuth2 authentication flow",
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          }
        },
        "operationId": "getAuthGoogle",
        "security": []
      }
    },
    "/auth/google/callback": {
      "get": {
        "tags": [
          "Client Auth"
        ],
        "summary": "Google OAuth callback",
        "parameters": [
          {
            "name": "code",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirects to the storefront after sign-in, or to /auth/login on failure"
          }
        },
        "operationId": "getAuthGoogleCallback",
        "security": []
      }
    },
    "/cart": {
      "get": {
        "tags": [
          "Client Cart & Checkout"
        ],
        "summary": "View shopping cart",
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          }
        },
        "operationId": "getCart",
        "security": []
      }
    },
    "/files": {
      "post": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Upload files to the media store",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Upload result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "saveLinks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "files"
                ],
                "properties": {
                  "files": {
                    "type": "array",
                    "maxItems": 20,
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Up to 20 files, 10 MB each; only allowed file types"
                  },
                  "folderPath": {
                    "type": "string",
                    "description": "Target folder (default: root)"
                  }
                }
              }
            }
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "postFmFiles"
      },
      "get": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "List files of a folder (paginated)",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "folderPath",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "getFmFiles"
      },
      "delete": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Delete a file",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "deleteFmFiles",
        "parameters": [
          {
            "name": "folder",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fileName",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/files/location": {
      "patch": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Move a file to another folder",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Moved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerMoveFileBody"
              }
            }
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "patchFmFilesLocation"
      }
    },
    "/files/name": {
      "patch": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Rename a file",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Renamed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchFileManagerChangeFileNameBody"
              }
            }
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "patchFmFilesName"
      }
    },
    "/folders": {
      "post": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Create a folder",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Folder created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PostAdminFileManagerFolderCreateBody"
              }
            }
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "postFmFolders"
      },
      "get": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "List sub-folders",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "folderPath",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Folder to list (default: root)"
          }
        ],
        "responses": {
          "200": {
            "description": "Folder list.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "getFmFolders"
      },
      "delete": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Delete a folder",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Folder deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "deleteFmFolders",
        "parameters": [
          {
            "name": "folderPath",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/folders/location": {
      "patch": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Move a folder",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Folder moved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerFolderMoveBody"
              }
            }
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "patchFmFoldersLocation"
      }
    },
    "/folders/name": {
      "patch": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Rename a folder",
        "security": [
          {
            "FileManagerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Folder renamed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidBearerSecret"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          },
          "409": {
            "$ref": "#/components/responses/FileManagerConflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyFailedAttempts"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAdminFileManagerFolderRenameBody"
              }
            }
          }
        },
        "servers": [
          {
            "url": "http://localhost:4000",
            "description": "FileManager Microservice"
          }
        ],
        "operationId": "patchFmFoldersName"
      }
    },
    "/manifest.webmanifest": {
      "get": {
        "tags": [
          "Site Endpoints"
        ],
        "summary": "PWA web app manifest generated from the store settings",
        "responses": {
          "200": {
            "description": "Web App Manifest",
            "content": {
              "application/manifest+json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "operationId": "getManifestWebmanifest",
        "security": []
      }
    },
    "/media/{subPath}": {
      "get": {
        "tags": [
          "FileManager Microservice"
        ],
        "summary": "Stream media asset directly from disk",
        "parameters": [
          {
            "name": "subPath",
            "in": "path",
            "required": true,
            "description": "File path below the media root, for example `users/abc/photo.png`. Slashes may be sent as `/` or `%2F`. Paths with a `temp` folder or that leave the media root are rejected.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "`download` forces a file download. Without it, images, video, audio and PDF are shown inline and every other type is sent as an attachment.",
            "schema": {
              "type": "string",
              "enum": [
                "download"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file. Errors are real HTTP statuses (400, 403, 404) with a JSON body `{ \"code\": \"error\", \"message\": \"...\" }`.",
            "headers": {
              "Content-Disposition": {
                "description": "Present when the file is sent as an attachment.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "video/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "audio/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/FileManagerBadRequest"
          },
          "403": {
            "$ref": "#/components/responses/FileManagerForbidden"
          },
          "404": {
            "$ref": "#/components/responses/FileManagerNotFound"
          }
        },
        "description": "Served by the Web app (proxy to the media store); FileManager serves the same path on port 4000.",
        "operationId": "getMediaBySubPath",
        "security": []
      }
    },
    "/order/payment-{method}": {
      "get": {
        "tags": [
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "Start (or retry) the payment of an order on an online gateway",
        "parameters": [
          {
            "name": "method",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "vnpay",
                "zalopay"
              ]
            },
            "description": "An online payment method that is enabled at checkout"
          },
          {
            "name": "orderCode",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "AB123456"
            },
            "description": "Order tracking code"
          },
          {
            "name": "phone",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "0901234567"
            },
            "description": "Customer checkout phone number"
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to the gateway, to the order summary when it is already paid, or home when the order or method is not available"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "description": "Rate limited (HTTP 429 when exceeded). The checkout response's `redirectUrl` points here for online methods.",
        "operationId": "getOrderPaymentByMethod",
        "security": []
      }
    },
    "/order/payment-vnpay-ipn": {
      "get": {
        "tags": [
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "VNPay IPN (server-to-server payment notification)",
        "description": "Called by VNPay, not by browsers. Verifies the HMAC-SHA512 signature and the amount, then marks the order paid. VNPay retries until it receives `RspCode` 00 or 02. The IPN URL must be registered in the VNPay merchant portal and reachable from the internet.",
        "parameters": [
          {
            "name": "vnp_Amount",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vnp_BankCode",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vnp_ResponseCode",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vnp_TransactionNo",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vnp_TransactionStatus",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vnp_TxnRef",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vnp_SecureHash",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "VNPay acknowledgement",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "RspCode": {
                      "type": "string",
                      "enum": [
                        "00",
                        "01",
                        "02",
                        "04",
                        "97",
                        "99"
                      ],
                      "description": "00 confirmed, 01 order not found, 02 already confirmed, 04 invalid amount, 97 invalid signature, 99 unknown error"
                    },
                    "Message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "operationId": "getOrderPaymentVnpayIpn",
        "security": []
      }
    },
    "/order/payment-vnpay-result": {
      "get": {
        "tags": [
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "VNPAY return callback: verifies the HMAC-SHA512 signature (vnp_SecureHash) and the amount, then marks the order paid and redirects to the order page",
        "parameters": [
          {
            "name": "vnp_ResponseCode",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "00"
            },
            "description": "00 indicates successful transaction"
          },
          {
            "name": "vnp_TxnRef",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "ORD-123456"
            },
            "description": "Order code"
          },
          {
            "name": "vnp_Amount",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "10000000"
            },
            "description": "Amount in VND x 100"
          },
          {
            "name": "vnp_SecureHash",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "HMAC-SHA512 signature"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          },
          "302": {
            "description": "Redirect (record not found, not signed in, or wrong state)"
          }
        },
        "operationId": "getOrderPaymentVnpayResult",
        "security": []
      }
    },
    "/order/payment-zalopay-callback": {
      "post": {
        "tags": [
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "ZaloPay secondary merchant callback endpoint",
        "responses": {
          "200": {
            "description": "Callback received.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StandardResponse"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "string"
                  },
                  "mac": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "operationId": "postOrderPaymentZalopayCallback",
        "security": []
      }
    },
    "/order/payment-zalopay-result": {
      "post": {
        "tags": [
          "Payment & Logistics (VNPAY, ZaloPay, GoShip)"
        ],
        "summary": "ZaloPay Webhook / IPN notification callback",
        "responses": {
          "200": {
            "description": "Webhook acknowledgment to ZaloPay server",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "return_code": {
                      "type": "integer",
                      "example": 1
                    },
                    "return_message": {
                      "type": "string",
                      "example": "success"
                    }
                  }
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "data",
                  "mac"
                ],
                "properties": {
                  "data": {
                    "type": "string",
                    "description": "JSON string containing app_id, app_trans_id, amount, embed_data"
                  },
                  "mac": {
                    "type": "string",
                    "description": "HMAC-SHA256 verification hash"
                  },
                  "type": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "operationId": "postOrderPaymentZalopayResult",
        "security": []
      }
    },
    "/product": {
      "get": {
        "tags": [
          "Client Products"
        ],
        "summary": "Browse and search product catalog",
        "parameters": [
          {
            "name": "keyword",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortKey",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sortValue",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          },
          {
            "name": "minPrice",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "maxPrice",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          },
          "302": {
            "description": "Redirect (record not found, not signed in, or wrong state)"
          }
        },
        "operationId": "getProduct",
        "security": []
      }
    },
    "/product/category/{slug}": {
      "get": {
        "tags": [
          "Client Products"
        ],
        "summary": "Filter products by category slug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          },
          "302": {
            "description": "Redirect (record not found, not signed in, or wrong state)"
          }
        },
        "operationId": "getProductCategoryBySlug",
        "security": []
      }
    },
    "/product/detail/{slug}": {
      "get": {
        "tags": [
          "Client Products"
        ],
        "summary": "View product details by slug",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/HtmlPage"
          },
          "302": {
            "description": "Redirect (record not found, not signed in, or wrong state)"
          }
        },
        "operationId": "getProductDetailBySlug",
        "security": []
      }
    },
    "/robots.txt": {
      "get": {
        "tags": [
          "Site Endpoints"
        ],
        "summary": "Robots.txt",
        "responses": {
          "200": {
            "description": "Robots rules",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "operationId": "getRobotsTxt",
        "security": []
      }
    },
    "/sitemap.xml": {
      "get": {
        "tags": [
          "Site Endpoints"
        ],
        "summary": "XML sitemap (cached for one hour)",
        "responses": {
          "200": {
            "description": "Sitemap",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        },
        "operationId": "getSitemapXml",
        "security": []
      }
    }
  },
  "components": {
    "securitySchemes": {
      "UserCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "tokenUser",
        "description": "Customer access token cookie (browsers). Set by the login endpoints; HTTP-only."
      },
      "AdminCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "tokenAdmin",
        "description": "Admin access token cookie (browsers). Set by the login endpoint; HTTP-only."
      },
      "FileManagerBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "The shared FILE_MANAGER_SECRET"
      },
      "UserBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Customer access token from `accessToken` in the login response, sent as `Authorization: Bearer <token>`. When this header is present the cookies are ignored."
      },
      "AdminBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Admin access token from `accessToken` in the login response, sent as `Authorization: Bearer <token>`. When this header is present the cookies are ignored."
      }
    },
    "schemas": {
      "StandardResponse": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "success"
            ]
          },
          "message": {
            "type": "string",
            "example": "Action completed successfully!"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "error"
            ]
          },
          "message": {
            "type": "string",
            "example": "Invalid data!"
          }
        }
      },
      "ObjectId": {
        "type": "string",
        "pattern": "^[0-9a-fA-F]{24}$",
        "description": "MongoDB ObjectId"
      },
      "IdsBody": {
        "type": "object",
        "required": [
          "ids"
        ],
        "properties": {
          "ids": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/ObjectId"
            },
            "description": "Ids of the records to act on"
          }
        }
      },
      "SeoBody": {
        "type": "object",
        "properties": {
          "seoTitle": {
            "type": "string",
            "description": "Meta title"
          },
          "seoDescription": {
            "type": "string",
            "description": "Meta description"
          },
          "seoKeywords": {
            "type": "string",
            "description": "JSON array string or single keyword"
          },
          "seoRobotsIndex": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          "seoRobotsFollow": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          "seoOgTitle": {
            "type": "string"
          },
          "seoOgDescription": {
            "type": "string"
          },
          "seoOgImage": {
            "type": "string",
            "description": "Image path"
          }
        }
      },
      "ProductSeoBody": {
        "type": "object",
        "properties": {
          "seoTitle": {
            "type": "string",
            "maxLength": 60,
            "description": "Meta title"
          },
          "seoDescription": {
            "type": "string",
            "maxLength": 160,
            "description": "Meta description"
          },
          "seoKeywords": {
            "type": "string",
            "description": "JSON array string or single keyword"
          },
          "seoRobotsIndex": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          "seoRobotsFollow": {
            "type": "string",
            "enum": [
              "true",
              "false"
            ]
          },
          "seoOgTitle": {
            "type": "string",
            "maxLength": 95
          },
          "seoOgDescription": {
            "type": "string",
            "maxLength": 200
          },
          "seoOgImage": {
            "type": "string",
            "description": "Image path"
          }
        }
      },
      "PatchAdminAccountAdminChangePasswordByIdBody": {
        "type": "object",
        "properties": {
          "password": {
            "type": "string",
            "minLength": 8
          }
        },
        "required": [
          "password"
        ]
      },
      "PostAdminAccountAdminCreateBody": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string",
            "minLength": 5,
            "maxLength": 50
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "minLength": 8
          },
          "status": {
            "type": "string",
            "enum": [
              "initial",
              "active",
              "inactive",
              ""
            ]
          },
          "avatar": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "roles": {
            "type": "string",
            "description": "Empty string allowed."
          }
        },
        "required": [
          "fullName",
          "email",
          "password"
        ]
      },
      "PatchAdminAccountAdminEditByIdBody": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string",
            "minLength": 5,
            "maxLength": 50
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "status": {
            "type": "string",
            "enum": [
              "initial",
              "active",
              "inactive",
              ""
            ]
          },
          "avatar": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "roles": {
            "type": "string",
            "description": "Empty string allowed."
          }
        },
        "required": [
          "fullName",
          "email"
        ]
      },
      "LoginBody": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "example": "customer@example.com"
          },
          "password": {
            "type": "string",
            "example": "MyPassw0rd!"
          },
          "rememberPassword": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "email",
          "password"
        ]
      },
      "PostAdminArticleCategoryCreateBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "maxLength": 200,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
          },
          "parent": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              ""
            ]
          },
          "avatar": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "description": {
            "type": "string",
            "description": "Empty string allowed."
          }
        },
        "required": [
          "name",
          "slug"
        ]
      },
      "PostAdminArticleCreateBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "maxLength": 200,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
          },
          "category": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "archived",
              ""
            ]
          },
          "avatar": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "description": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "content": {
            "type": "string",
            "description": "Empty string allowed."
          }
        },
        "required": [
          "name",
          "slug"
        ]
      },
      "PostAdminBlockCreateBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "fileName": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              ""
            ]
          },
          "data": {
            "type": "object"
          }
        },
        "required": [
          "name",
          "fileName"
        ]
      },
      "PostAdminChatEditReplyByIdBody": {
        "type": "object",
        "required": [
          "content"
        ],
        "properties": {
          "content": {
            "type": "string",
            "description": "Draft reply"
          }
        }
      },
      "PostAdminCouponCreateBody": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "typeDiscount": {
            "type": "string",
            "enum": [
              "percentage",
              "fixed",
              ""
            ]
          },
          "value": {
            "type": "number",
            "minimum": 0,
            "description": "Empty string allowed."
          },
          "minOrderValue": {
            "type": "number",
            "minimum": 0,
            "description": "Empty string allowed."
          },
          "maxDiscountValue": {
            "type": "number",
            "minimum": 0,
            "description": "Empty string allowed."
          },
          "usageLimit": {
            "type": "integer",
            "minimum": 0,
            "description": "Empty string allowed."
          },
          "typeDisplay": {
            "type": "string",
            "enum": [
              "public",
              "private",
              ""
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              ""
            ]
          },
          "startDate": {
            "type": "string",
            "pattern": "^(\\d{4}-\\d{2}-\\d{2}|\\d{2}\\/\\d{2}\\/\\d{4})$",
            "description": "ISO 8601 date (YYYY-MM-DD) preferred. DD/MM/YYYY also accepted via form submission."
          },
          "endDate": {
            "type": "string",
            "pattern": "^(\\d{4}-\\d{2}-\\d{2}|\\d{2}\\/\\d{2}\\/\\d{4})$",
            "description": "ISO 8601 date (YYYY-MM-DD) preferred. DD/MM/YYYY also accepted via form submission."
          },
          "description": {
            "type": "string",
            "description": "Empty string allowed."
          }
        },
        "required": [
          "code",
          "name"
        ]
      },
      "PatchAdminFileManagerChangeFileNameBody": {
        "type": "object",
        "required": [
          "folder",
          "oldFileName",
          "newFileName"
        ],
        "properties": {
          "folder": {
            "type": "string"
          },
          "oldFileName": {
            "type": "string"
          },
          "newFileName": {
            "type": "string",
            "maxLength": 255,
            "pattern": "^[^/\\\\:*?\"<>|]+$",
            "description": "A file name without any of `/ \\ : * ? \" < > |`."
          }
        }
      },
      "PatchFileManagerChangeFileNameBody": {
        "type": "object",
        "required": [
          "folder",
          "oldFileName",
          "newFileName"
        ],
        "properties": {
          "folder": {
            "type": "string"
          },
          "oldFileName": {
            "type": "string"
          },
          "newFileName": {
            "type": "string",
            "description": "A plain file name without a path. Its extension must be one the media store allows."
          }
        }
      },
      "PostAdminFileManagerFolderCreateBody": {
        "type": "object",
        "required": [
          "folderName"
        ],
        "properties": {
          "folderName": {
            "type": "string",
            "pattern": "^(?!.*\\.\\.)[^/\\\\:*?\"<>|]+$",
            "description": "Cannot contain `/ \\ : * ? \" < > |` or `..`. The name `temp` is reserved."
          },
          "folderPath": {
            "type": "string",
            "description": "Parent folder"
          }
        }
      },
      "PatchAdminFileManagerFolderMoveBody": {
        "type": "object",
        "required": [
          "folderPath"
        ],
        "properties": {
          "folderPath": {
            "type": "string"
          },
          "targetFolder": {
            "type": "string",
            "description": "Destination folder. Omit it to use the media root."
          }
        }
      },
      "PatchAdminFileManagerFolderRenameBody": {
        "type": "object",
        "required": [
          "folderPath",
          "newFolderName"
        ],
        "properties": {
          "folderPath": {
            "type": "string"
          },
          "newFolderName": {
            "type": "string",
            "pattern": "^(?!.*\\.\\.)[^/\\\\:*?\"<>|]+$",
            "description": "Cannot contain `/ \\ : * ? \" < > |` or `..`."
          }
        }
      },
      "PatchAdminFileManagerMoveFileBody": {
        "type": "object",
        "required": [
          "folder",
          "fileName"
        ],
        "properties": {
          "folder": {
            "type": "string"
          },
          "fileName": {
            "type": "string"
          },
          "targetFolder": {
            "type": "string",
            "description": "Destination folder. Omit it to use the media root."
          }
        }
      },
      "PatchAdminOrderEditByIdBody": {
        "type": "object",
        "required": [
          "orderStatus",
          "paymentStatus"
        ],
        "properties": {
          "orderStatus": {
            "type": "string",
            "enum": [
              "pending",
              "confirmed",
              "shipping",
              "completed",
              "cancelled",
              "returned"
            ]
          },
          "paymentStatus": {
            "type": "string",
            "enum": [
              "unpaid",
              "paid",
              "refunded"
            ]
          },
          "note": {
            "type": "string",
            "description": "Internal note"
          }
        }
      },
      "PostAdminProductAttributeCreateBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "select",
              "color",
              ""
            ]
          },
          "options": {
            "type": "string",
            "description": "Empty string allowed."
          }
        },
        "required": [
          "name"
        ]
      },
      "PostAdminProductCreateBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "maxLength": 200,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "Accepts both integer and string-encoded integer via multipart."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "inactive",
              ""
            ]
          },
          "category": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "description": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "content": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "images": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "priceOld": {
            "type": "number",
            "minimum": 0,
            "description": "In the store currency, rounded to its decimals. Accepts a number or a string-encoded number via multipart."
          },
          "priceNew": {
            "type": "number",
            "minimum": 0,
            "description": "In the store currency, rounded to its decimals. Accepts a number or a string-encoded number via multipart."
          },
          "attributes": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "variants": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "stock": {
            "type": "integer",
            "minimum": 0,
            "description": "Accepts both integer and string-encoded integer via multipart."
          },
          "weight": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000000,
            "description": "Shipping weight of one unit in grams; empty uses the store default."
          },
          "tags": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "boughtTogether": {
            "type": "string",
            "description": "Empty string allowed."
          }
        },
        "required": [
          "name",
          "slug"
        ]
      },
      "PostAdminRoleCreateBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "permissions": {
            "type": "string",
            "description": "Empty string allowed."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              ""
            ]
          }
        },
        "required": [
          "name"
        ]
      },
      "PostAdminTemplateCreateBody": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200
          },
          "slug": {
            "type": "string",
            "maxLength": 200
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              ""
            ]
          },
          "blocks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "blockId": {
                  "type": "string",
                  "maxLength": 24,
                  "minLength": 24
                },
                "position": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "required": [
                "blockId",
                "position"
              ]
            }
          }
        },
        "required": [
          "name",
          "slug"
        ]
      },
      "PostCompareListBody": {
        "type": "object",
        "properties": {
          "ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "PostDashboardAddressCreateBody": {
        "type": "object",
        "properties": {
          "fullName": {
            "type": "string",
            "minLength": 5,
            "maxLength": 50
          },
          "phone": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "longitude": {
            "type": "number"
          },
          "latitude": {
            "type": "number"
          },
          "isDefault": {
            "type": "boolean"
          }
        },
        "required": [
          "fullName",
          "phone",
          "address",
          "longitude",
          "latitude",
          "isDefault"
        ]
      },
      "PatchAdminSettingGeneralBody": {
        "type": "object",
        "properties": {
          "websiteName": {
            "type": "string",
            "maxLength": 100
          },
          "domainWebsite": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "logo": {
            "type": "string",
            "maxLength": 500
          },
          "favicon": {
            "type": "string",
            "maxLength": 500
          },
          "shopSenderName": {
            "type": "string",
            "maxLength": 100
          },
          "shopSenderPhone": {
            "type": "string",
            "maxLength": 30
          },
          "shopSenderAddress": {
            "type": "string",
            "maxLength": 300
          },
          "contactEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "shopLat": {
            "oneOf": [
              {
                "type": "number",
                "minimum": -90,
                "maximum": 90
              },
              {
                "type": "string",
                "enum": [
                  ""
                ]
              }
            ],
            "description": "A number, or an empty string to clear it."
          },
          "shopLng": {
            "oneOf": [
              {
                "type": "number",
                "minimum": -180,
                "maximum": 180
              },
              {
                "type": "string",
                "enum": [
                  ""
                ]
              }
            ],
            "description": "A number, or an empty string to clear it."
          },
          "storeDescription": {
            "type": "string",
            "maxLength": 300,
            "description": "Short text under the footer logo."
          },
          "facebookUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "instagramUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "youtubeUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "tiktokUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "linkedinUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "xUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          }
        }
      },
      "PatchAdminSettingApiPaymentBody": {
        "type": "object",
        "properties": {
          "zaloPayAppId": {
            "type": "string",
            "maxLength": 100
          },
          "zaloPayKey1": {
            "type": "string",
            "maxLength": 500,
            "format": "password"
          },
          "zaloPayKey2": {
            "type": "string",
            "maxLength": 500,
            "format": "password"
          },
          "zaloPayDomain": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "zaloPayEndpoint": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "vnPayTmnCode": {
            "type": "string",
            "maxLength": 100
          },
          "vnPayHashSecret": {
            "type": "string",
            "maxLength": 500,
            "format": "password"
          },
          "vnPayURL": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "enabledMethods": {
            "type": "array",
            "uniqueItems": true,
            "description": "Payment methods offered at checkout. Unset means every method whose keys are filled in; a method whose keys are missing, or that cannot charge the store currency, is never offered.",
            "items": {
              "type": "string",
              "enum": [
                "money",
                "vnpay",
                "zalopay"
              ]
            }
          }
        }
      },
      "PatchAdminSettingStorefrontBody": {
        "type": "object",
        "properties": {
          "primaryColor": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$"
          },
          "secondaryColor": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$"
          },
          "headingFont": {
            "type": "string",
            "maxLength": 60,
            "pattern": "^[A-Za-z0-9 ]*$",
            "description": "A Google Fonts family name; empty keeps the theme font."
          },
          "bodyFont": {
            "type": "string",
            "maxLength": 60,
            "pattern": "^[A-Za-z0-9 ]*$",
            "description": "A Google Fonts family name; empty keeps the theme font."
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 code, e.g. VND."
          },
          "displayCurrencies": {
            "oneOf": [
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              {
                "type": "string"
              }
            ],
            "description": "ISO 4217 codes shoppers may view prices in, as a list or comma-separated text."
          },
          "locale": {
            "type": "string",
            "maxLength": 20,
            "description": "BCP 47 locale for numbers and dates, e.g. vi-VN."
          },
          "timezone": {
            "type": "string",
            "maxLength": 60,
            "description": "IANA time zone, e.g. Asia/Ho_Chi_Minh."
          },
          "language": {
            "type": "string",
            "pattern": "^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{2,8})?$",
            "description": "The storefront html lang attribute."
          },
          "moneyPerPoint": {
            "type": "number",
            "exclusiveMinimum": true,
            "minimum": 0,
            "maximum": 1000000000000,
            "description": "Order value that earns one loyalty point."
          },
          "pointValue": {
            "type": "number",
            "exclusiveMinimum": true,
            "minimum": 0,
            "maximum": 1000000000000,
            "description": "Discount one loyalty point is worth."
          }
        }
      },
      "PatchAdminSettingPagesBody": {
        "type": "object",
        "properties": {
          "about": {
            "type": "string",
            "maxLength": 60000
          },
          "faq": {
            "type": "string",
            "maxLength": 60000
          },
          "privacyPolicy": {
            "type": "string",
            "maxLength": 60000
          },
          "termsAndConditions": {
            "type": "string",
            "maxLength": 60000
          },
          "returnPolicy": {
            "type": "string",
            "maxLength": 60000
          }
        }
      },
      "ShippingRate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Pass it back as `shippingMethod` when placing the order (\"<provider>:<rate>\").",
            "example": "goship:12345"
          },
          "provider": {
            "type": "string",
            "example": "goship"
          },
          "carrierName": {
            "type": "string",
            "example": "J&T Express"
          },
          "service": {
            "type": "string"
          },
          "expected": {
            "type": "string",
            "description": "Expected delivery time as the carrier words it."
          },
          "fee": {
            "type": "number"
          }
        }
      },
      "CartQuoteResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardResponse"
          },
          {
            "type": "object",
            "properties": {
              "cart": {
                "type": "array",
                "items": {
                  "type": "object"
                },
                "description": "The cart lines with current product details and quantities capped at the stock."
              },
              "shippingOptions": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ShippingRate"
                },
                "description": "Cheapest first. Carriers that price by address (GoShip) appear only once `userAddress` is sent."
              },
              "point": {
                "type": "object",
                "properties": {
                  "canUsePoint": {
                    "type": "integer"
                  },
                  "POINT_TO_MONEY": {
                    "type": "number"
                  }
                }
              }
            }
          }
        ]
      },
      "OrderCreatedResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardResponse"
          },
          {
            "type": "object",
            "properties": {
              "orderCode": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              },
              "total": {
                "type": "number"
              },
              "paymentStatus": {
                "type": "string",
                "enum": [
                  "unpaid",
                  "paid"
                ]
              },
              "redirectUrl": {
                "type": "string",
                "description": "Where to send the customer next, the order summary or the payment gateway start page.",
                "example": "/order/payment-vnpay?orderCode=AB123456&phone=0901234567"
              }
            }
          }
        ]
      },
      "PatchAdminSettingApiLoginSocialBody": {
        "type": "object",
        "properties": {
          "googleClientId": {
            "type": "string",
            "maxLength": 500
          },
          "googleClientSecret": {
            "type": "string",
            "maxLength": 500,
            "format": "password"
          },
          "googleCallbackUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          },
          "facebookAppId": {
            "type": "string",
            "maxLength": 500
          },
          "facebookAppSecret": {
            "type": "string",
            "maxLength": 500,
            "format": "password"
          },
          "facebookCallbackUrl": {
            "type": "string",
            "format": "uri",
            "maxLength": 500
          }
        }
      },
      "PatchAdminSettingApiAppPasswordBody": {
        "type": "object",
        "properties": {
          "gmailUser": {
            "type": "string",
            "maxLength": 200
          },
          "gmailPassword": {
            "type": "string",
            "maxLength": 200,
            "format": "password"
          }
        }
      },
      "SessionResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/StandardResponse"
          },
          {
            "type": "object",
            "required": [
              "accessToken",
              "tokenType"
            ],
            "properties": {
              "accessToken": {
                "type": "string",
                "description": "JWT for `Authorization: Bearer <token>`. It is also set in the HttpOnly cookie, which is what browsers use.",
                "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
              },
              "tokenType": {
                "type": "string",
                "enum": [
                  "Bearer"
                ]
              },
              "expiresIn": {
                "type": "integer",
                "description": "Seconds until the access token expires. There is no refresh for Bearer clients: log in again on 401."
              }
            }
          }
        ]
      }
    },
    "responses": {
      "StandardResult": {
        "description": "Result of the action.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "success"
                  ]
                },
                "message": {
                  "type": "string"
                },
                "content": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "BadRequest": {
        "description": "Invalid request: validation failed or the input is malformed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Not logged in. Page requests are redirected to the login page instead.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "The record does not exist.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Conflict": {
        "description": "The request conflicts with the current state, for example a duplicate value, missing stock or a change that is not allowed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServerError": {
        "description": "Unexpected failure.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "BadGateway": {
        "description": "A service the application depends on (FileManager, email, GoShip) failed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RedirectToLogin": {
        "description": "Not logged in; redirected to the login page.",
        "headers": {
          "Location": {
            "description": "The login page.",
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "PermissionDenied": {
        "description": "The admin lacks the permission, or the action is not allowed for this account. API calls get `{ \"code\": \"error\", \"message\": \"...\" }`; page requests get an HTML 403 page.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many attempts. The `Retry-After` header holds the seconds to wait; the body is `{ \"code\": \"error\", \"message\": \"...\" }`.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before trying again.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "UploadRejected": {
        "description": "Invalid request, or the upload was rejected (type, size or file count).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "HtmlPage": {
        "description": "HTML page",
        "content": {
          "text/html": {
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "FileManagerBadRequest": {
        "description": "Invalid request or the operation failed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InvalidBearerSecret": {
        "description": "Missing or wrong bearer secret.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "TooManyFailedAttempts": {
        "description": "Too many failed bearer attempts from this address; retry after the number of seconds in the `Retry-After` header. Requests with the correct secret are never blocked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "FileManagerForbidden": {
        "description": "Path outside the media root or not allowed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "FileManagerNotFound": {
        "description": "File or folder not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "FileManagerConflict": {
        "description": "A file or folder with that name already exists.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The store is not fully configured yet (warehouse location, sender phone or address missing in Settings > General), so the request cannot be completed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    }
  }
}
