{
  "openapi": "3.0.1",
  "info": {
    "title": "Nesika Web API",
    "description": "Reference for the Nesika Web API -- the endpoints that power the Nesika application and are available for programmatic integration.\n\nAuthenticate with either an Azure AD (Entra) bearer token (`Authorization: Bearer <token>`, used by the web app) or an API key issued from your account dashboard (`X-API-Key` header). Either scheme is accepted.\n\nRequests are rate-limited and metered by plan. A request that exceeds its quota can return **429 Too Many Requests** with rate-limit headers describing the current limit state.\n\nSystem-administration, internal/diagnostic, webhook, and authentication-callback endpoints are intentionally excluded from this document.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://nesika-ase-prod-webapi-prod.azurewebsites.net/"
    }
  ],
  "paths": {
    "/api/ai-insights/weekly-report": {
      "get": {
        "tags": [
          "AIInsights"
        ],
        "summary": "Generates the AI weekly pricing report.",
        "description": "Returns a narrative report generated from weekly price and match data for the current workspace.\n\nCall `GET /api/ai-insights/weekly-report` when a client needs an AI-written summary of recent competitive pricing movements rather than individual structured Insight Cards. Optional filters narrow the source data by scan, competitor list, category, and whether similar matches are included.\n\nThis endpoint generates content on demand. Use `scanId` to focus the report on a specific scan, `competitors` as a comma-separated competitor list, `category` to narrow product scope, and `includeSimilar=true` to include similar matches alongside perfect matches.",
        "parameters": [
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "competitors",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.AIInsights.AIInsightsResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.AIInsights.AIInsightsResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.AIInsights.AIInsightsResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/alert-rules": {
      "get": {
        "tags": [
          "AlertRules"
        ],
        "summary": "List alert rules for the active workspace.",
        "description": "Returns all `AlertRuleDto` records for the authenticated user's active workspace.\nThe Settings - Alerts screen calls `GET /api/alert-rules` to render the rule list,\nenabled state, condition type, condition parameters, delivery channels, and last\ntriggered timestamp.\n\nAlert rules are evaluated after scans complete. Enabled rules can create in-app\nnotifications and, when configured and allowed by user preferences, email alerts. If the\nservice cannot resolve an active workspace, it returns an empty list rather than exposing\nrules from another workspace.",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Create a new alert rule.",
        "description": "Creates an alert rule in the active workspace and returns the created\n`AlertRuleDto`. The Settings - Alerts screen calls `POST /api/alert-rules`\nwhen a user defines a custom trigger for scan results.\n\nRequired fields include `name` and `conditionType`. Supported condition types\nare `price_below`, `price_above`, `availability_change`,\n`product_available`, `product_unavailable`, `any_price_change`, and\n`competitor_found`. All currently supported condition types require\n`conditionParams.productId`. Price threshold rules also require\n`conditionParams.thresholdValue`. Omit `deliveryChannels` to default to\n`in_app`, or provide values such as `in_app` and `email`.\n\nThe workspace can have up to 100 alert rules. Validation failures return `400`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.CreateAlertRuleDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.CreateAlertRuleDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.CreateAlertRuleDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/alert-rules/{id}": {
      "get": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Get one alert rule by ID.",
        "description": "Returns a single `AlertRuleDto` from the active workspace. The Settings - Alerts UI\nuses `GET /api/alert-rules/{id}` when it needs to refresh one rule before editing or\nafter a navigation deep link.\n\nRule lookup is workspace-scoped. Unknown IDs, rules from another workspace, or missing\nworkspace context return `404`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Update an existing alert rule.",
        "description": "Applies a partial update to an alert rule in the active workspace and returns the updated\n`AlertRuleDto`. The Settings - Alerts screen calls\n`PUT /api/alert-rules/{id}` when a user edits a rule name, condition type,\nthreshold, product scope, competitor scope, delivery channel, or enabled state.\n\nOnly provided fields are changed. Condition parameter updates preserve omitted existing\nvalues while still allowing explicit null clears for competitor and threshold fields.\nChanging the condition type revalidates the effective condition parameters. Supported\ndelivery channels are `in_app` and `email`.\n\nUnknown IDs return `404`. Validation failures, such as missing product scope or a\nmissing threshold for price rules, return `400`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.UpdateAlertRuleDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.UpdateAlertRuleDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.UpdateAlertRuleDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Delete an alert rule.",
        "description": "Permanently removes an alert rule from the active workspace. The Settings - Alerts screen\ncalls `DELETE /api/alert-rules/{id}` when a user chooses to remove a rule.\n\nDeleting a rule stops future evaluation and notification creation for that rule. Existing\nnotification records are not deleted by this controller. Successful deletion returns\n`204 No Content`; unknown IDs or missing workspace context return `404`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/alert-rules/{id}/notifications": {
      "get": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Get notification history for one alert rule.",
        "description": "Returns notifications triggered by the specified alert rule, including unread, read, and\ndismissed notifications ordered newest first. The Settings - Alerts UI uses\n`GET /api/alert-rules/{id}/notifications` to let users review why a rule fired in\nprevious scans.\n\nThe controller first verifies that the rule exists in the active workspace, then reads\nnotifications for that rule. Use the optional `limit` query parameter to cap the\nhistory length; it defaults to `50`. A missing rule returns `404`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.NotificationDto"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.NotificationDto"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.NotificationDto"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/alert-rules/{id}/toggle": {
      "patch": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Enable or disable an alert rule.",
        "description": "Updates only the `enabled` state of an alert rule and returns the updated\n`AlertRuleDto`. The Settings - Alerts screen uses\n`PATCH /api/alert-rules/{id}/toggle` for the inline enable/disable switch.\n\nDisabled rules remain stored but are not evaluated during scan completion. Re-enabling a\nrule makes it eligible for future scans; it does not replay historical scan results.\nUnknown IDs return `404`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.ToggleAlertRuleDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.ToggleAlertRuleDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.ToggleAlertRuleDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/api-keys": {
      "post": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Generate a new API key for the current user in their active workspace",
        "description": "The raw key value is returned ONLY in this response. Store it securely — it cannot be retrieved again.\nRequires workspace membership. Maximum of 10 active keys per user per workspace.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.GenerateApiKeyRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.GenerateApiKeyRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.GenerateApiKeyRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyGenerationResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyGenerationResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyGenerationResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "get": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "List API keys created by the current user in their active workspace",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfApiKeyDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfApiKeyDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfApiKeyDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/api-keys/{keyId}": {
      "delete": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Revoke an API key (soft delete). Users can only revoke their own keys.",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      },
      "patch": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Update an API key's metadata (name, expiration). Users can only update their own keys.",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.UpdateApiKeyRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.UpdateApiKeyRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.UpdateApiKeyRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/api-keys/{keyId}/rotate": {
      "post": {
        "tags": [
          "ApiKeys"
        ],
        "summary": "Rotate an API key: revokes the old key and generates a new one with the same name.\nUsers can only rotate their own keys.",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyGenerationResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyGenerationResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfApiKeyGenerationResultDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/chat/message": {
      "post": {
        "tags": [
          "Chat"
        ],
        "summary": "Send a chat message.",
        "description": "Processes a user chat message and returns an assistant response, creating a conversation automatically when `conversationId` is omitted.\n\nCall `POST /api/chat/message` with `ChatMessageRequest`. Include `conversationId` for follow-up messages and `agentType` when the UI lets the user choose a specialist agent.\n\nUse this for the non-streaming AI assistant path. Conversation ownership is checked by user ID, and unauthorized conversation access is returned as not found.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatMessageRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatMessageRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatMessageRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatMessageResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/chat/message/stream": {
      "post": {
        "tags": [
          "Chat"
        ],
        "summary": "Stream a chat message response.",
        "description": "Streams assistant output as Server-Sent Events for clients that want incremental chat responses instead of waiting for the complete answer.\n\nCall `POST /api/chat/message/stream` with the same `ChatMessageRequest` shape used by `POST /api/chat/message`. The response uses `text/event-stream` and emits events followed by a final `done` event.\n\nUse this when `ChatAI:StreamingEnabled` is enabled and the chat UI can handle SSE. The endpoint sends an `error` event for recoverable failures after headers have been written.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatMessageRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatMessageRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatMessageRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": { }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/chat/conversations": {
      "get": {
        "tags": [
          "Chat"
        ],
        "summary": "List chat conversations.",
        "description": "Returns all conversations owned by the current authenticated user.\n\nCall `GET /api/chat/conversations`. The chat history sidebar uses this endpoint to show previous retail analytics conversations and resume work.\n\nUse this after sending, renaming, or deleting conversations so the sidebar reflects the latest title, message count, and timestamps.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ConversationResponse"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/chat/conversations/{id}": {
      "get": {
        "tags": [
          "Chat"
        ],
        "summary": "Get a chat conversation.",
        "description": "Returns one conversation when it belongs to the current authenticated user.\n\nCall `GET /api/chat/conversations/{id}`. Unknown or unauthorized conversation IDs return `404`.\n\nUse this when opening a conversation deep link or refreshing conversation metadata before loading messages.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ConversationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "Chat"
        ],
        "summary": "Update a chat conversation.",
        "description": "Updates conversation metadata, such as renaming a conversation in the chat history sidebar.\n\nCall `PUT /api/chat/conversations/{id}` with an `UpdateConversationDto` body. The conversation must belong to the current user.\n\nUse this when a user edits a conversation title or when the UI persists metadata changes. Unknown conversations return `404`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.UpdateConversationRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.UpdateConversationRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.UpdateConversationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ConversationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Chat"
        ],
        "summary": "Delete a chat conversation.",
        "description": "Deletes one conversation and its messages for the current authenticated user.\n\nCall `DELETE /api/chat/conversations/{id}`. The endpoint returns `204 No Content` on success and `404` when the conversation is not found or not owned by the user.\n\nUse this from chat history delete actions. Refresh the conversation list after a successful delete.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content",
            "content": {
              "application/json": { }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/chat/conversations/{id}/messages": {
      "get": {
        "tags": [
          "Chat"
        ],
        "summary": "List conversation messages.",
        "description": "Returns a paginated message history for one conversation owned by the current authenticated user.\n\nCall `GET /api/chat/conversations/{id}/messages?page=1&pageSize=50`. The endpoint normalizes `page` to at least 1 and caps `pageSize` at 100.\n\nUse this when opening a conversation, scrolling history, or rehydrating the chat panel after a refresh.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/chat/agents": {
      "get": {
        "tags": [
          "Chat"
        ],
        "summary": "List available chat agents.",
        "description": "Returns metadata for the built-in AI assistant agents, including names, capabilities, and specializations.\n\nCall `GET /api/chat/agents`. This action is marked `AllowAnonymous`, so clients can show agent choices before authentication or before loading user chat configuration.\n\nUse this for agent pickers, onboarding copy, and developer previews. Plan-specific availability and quotas are returned by `GET /api/chat/configuration`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.AgentListResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/chat/configuration": {
      "get": {
        "tags": [
          "Chat"
        ],
        "summary": "Get chat configuration and quotas.",
        "description": "Returns chat feature configuration for the current user, including available agents, multi-agent support, monthly conversation quota, and per-conversation message limits.\n\nCall `GET /api/chat/configuration`. The frontend chat service caches this response briefly to avoid repeated quota lookups while the chat panel is open.\n\nUse this before enabling chat controls, creating conversations, or showing upgrade prompts tied to usage-plan chat fields.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatConfigurationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/chat/conversations/{conversationId}/messages/{messageId}/feedback": {
      "post": {
        "tags": [
          "Chat"
        ],
        "summary": "Submit AI message feedback.",
        "description": "Records thumbs-up or thumbs-down feedback for an assistant message inside a conversation owned by the current user.\n\nCall `POST /api/chat/conversations/{conversationId}/messages/{messageId}/feedback` with `MessageFeedbackRequest`. The target message must be an assistant message.\n\nUse this from chat response feedback buttons to improve answer quality and support triage. Unauthorized conversation access returns `404`, and invalid feedback returns `400`.",
        "parameters": [
          {
            "name": "conversationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "messageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageFeedbackRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageFeedbackRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageFeedbackRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageFeedbackResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-config/primary-vendor": {
      "get": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Get the primary vendor configuration for the active workspace.",
        "description": "Returns the current primary vendor configuration used by scans and pricing workflows. The settings data-source screen uses this to show whether the workspace is configured for CSV, vendor ID, URL, or no primary vendor.\n\nCall `GET /api/company-config/primary-vendor` with the normal bearer token. The service scopes the lookup to the authenticated user's active workspace.\n\nThis endpoint is read-only. A workspace without a configured primary vendor returns `404`, which the frontend treats as a valid unconfigured state.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.PrimaryVendorDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Set the primary vendor configuration for the active workspace.",
        "description": "Creates or updates the primary vendor configuration used by scans and pricing workflows. The settings data-source screen uses this when an administrator saves the selected vendor source.\n\nCall `PUT /api/company-config/primary-vendor` with a `SetPrimaryVendorDto` body. The service validates the requested configuration before saving it for the active workspace.\n\nThis endpoint has a side effect: it changes how the workspace identifies primary-vendor data for future workflows. Validation failures return `400`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.SetPrimaryVendorDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.SetPrimaryVendorDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.SetPrimaryVendorDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.PrimaryVendorDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Delete the primary vendor configuration for the active workspace.",
        "description": "Removes the workspace's primary vendor configuration, effectively returning it to an unconfigured state. The settings data-source screen uses this when an administrator clears the selected primary vendor.\n\nCall `DELETE /api/company-config/primary-vendor` with the normal bearer token. The service scopes the operation to the active workspace.\n\nThis endpoint has a side effect: it deletes the current primary-vendor setting. It returns `404` if there is no configuration to delete.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": { }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-config/vendor-systems": {
      "get": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Get available vendor system options.",
        "description": "Returns the vendor-system choices that can be selected as a primary vendor source. The settings data-source screen uses this list to populate the vendor selector and descriptions.\n\nCall `GET /api/company-config/vendor-systems` with the normal bearer token.\n\nThis endpoint is read-only and not paginated in the controller.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.VendorSystemOptionDto"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-config/insights": {
      "get": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Get insights configuration for the active workspace.",
        "description": "Returns configuration that controls insights behavior for the workspace. The insights settings tab uses this to populate the current thresholds or feature settings, creating defaults through the service if necessary.\n\nCall `GET /api/company-config/insights` with the normal bearer token. The endpoint requires an active workspace and scopes the configuration to that workspace.\n\nThis endpoint is read-only from the caller's perspective. A missing active workspace returns `400`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.InsightsConfigDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Update insights configuration for the active workspace.",
        "description": "Saves insights configuration for the workspace. The insights settings tab uses this when an administrator changes how insights should be generated or displayed.\n\nCall `PUT /api/company-config/insights` with an `UpdateInsightsConfigDto` body. The endpoint requires an active workspace and validates the configuration before saving it.\n\nThis endpoint has a side effect: it persists the workspace's insights settings for future insight calculations and UI reads. Validation failures return `400`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.UpdateInsightsConfigDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.UpdateInsightsConfigDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.UpdateInsightsConfigDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.InsightsConfigDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-config/domain-overrides": {
      "get": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Get domain field extraction overrides for the active workspace.",
        "description": "Returns all domain-specific field extraction overrides configured for the active workspace. The advanced field overrides UI uses this to list custom extraction rules for competitor domains.\n\nCall `GET /api/company-config/domain-overrides` with the normal bearer token. The endpoint requires an active workspace. The advanced field overrides feature must be enabled for the workspace unless the caller is a `SystemAdministrator`.\n\nThis endpoint is read-only. A disabled feature returns `403`; a missing active workspace returns `400`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-config/domain-overrides/{domain}": {
      "get": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Get field extraction overrides for one domain.",
        "description": "Returns the domain-specific extraction override for a single competitor domain. The advanced field overrides UI uses this when opening or refreshing one domain's override editor.\n\nCall `GET /api/company-config/domain-overrides/{domain}`. The endpoint requires an active workspace. The advanced field overrides feature must be enabled for the workspace unless the caller is a `SystemAdministrator`.\n\nThis endpoint is read-only. It returns `404` when no override exists for the requested domain.",
        "parameters": [
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Create or update field extraction overrides for one domain.",
        "description": "Saves a domain-specific field extraction override for the active workspace. The advanced field overrides UI uses this when an administrator configures custom selectors or extraction fields for a competitor domain.\n\nCall `PUT /api/company-config/domain-overrides/{domain}` with a `FieldOverridesDto` body. The endpoint requires an active workspace. The advanced field overrides feature must be enabled for the workspace unless the caller is a `SystemAdministrator`.\n\nThis endpoint has a side effect: it creates or replaces override configuration for the domain. Validation failures return `400`; missing company configuration returns `404`.",
        "parameters": [
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Delete field extraction overrides for one domain.",
        "description": "Deletes a domain-specific extraction override from the active workspace. The advanced field overrides UI uses this when an administrator removes custom extraction behavior for a competitor domain.\n\nCall `DELETE /api/company-config/domain-overrides/{domain}`. The endpoint requires an active workspace. The advanced field overrides feature must be enabled for the workspace unless the caller is a `SystemAdministrator`.\n\nThis endpoint has a side effect: it removes the override so future extraction uses default behavior. It returns `404` when no override exists for the domain.",
        "parameters": [
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content",
            "content": {
              "application/json": { }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-config/marketplace-filter-default": {
      "get": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Get the default marketplace-product exclusion setting.",
        "description": "Returns whether the active workspace excludes marketplace or third-party listing products by default. Competitor and product settings screens use this to display the workspace-wide marketplace filtering toggle.\n\nCall `GET /api/company-config/marketplace-filter-default` with the normal bearer token. The endpoint derives the active workspace from the current user.\n\nThis endpoint is read-only. When the value is true, marketplace products are excluded by default across read paths for competitors unless more specific behavior overrides it.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.MarketplaceFilterDefaultDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "patch": {
        "tags": [
          "CompanyConfiguration"
        ],
        "summary": "Set the default marketplace-product exclusion setting.",
        "description": "Updates whether the active workspace excludes marketplace or third-party listing products by default. Competitor and product settings screens use this when an administrator saves the workspace-wide marketplace filtering toggle.\n\nCall `PATCH /api/company-config/marketplace-filter-default` with a `SetMarketplaceFilterDefaultDto` body. The endpoint derives the active workspace from the current user.\n\nThis endpoint has a side effect: it changes filtering behavior for future read paths in the workspace. Missing workspace context returns `400`; missing company configuration returns `404`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.SetMarketplaceFilterDefaultDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.SetMarketplaceFilterDefaultDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.SetMarketplaceFilterDefaultDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.MarketplaceFilterDefaultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/companies/current": {
      "get": {
        "tags": [
          "Company"
        ],
        "summary": "Get company data for the current active workspace.",
        "description": "Returns company metadata for the authenticated user's active workspace. The Nesika web app uses this on settings and workspace-aware screens when it needs the workspace's company name, contact details, website, logo, or related display information.\n\nCall `GET /api/companies/current` with the normal bearer token. The endpoint derives the workspace from the current user's active workspace, then loads the matching company record.\n\nThis endpoint is read-only. It returns `404` when the user has no active workspace or the company cannot be found.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompanyDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitor-detail/{vendorId}/summary": {
      "get": {
        "tags": [
          "CompetitorDetail"
        ],
        "summary": "Gets the KPI summary for one competitor.",
        "description": "Returns header metrics for the Competitor Detail page, including the current workspace's relationship with the selected retailer.\n\nThe web app calls `GET /api/competitor-detail/{vendorId}/summary` when a user opens a competitor detail page from the Competitors screen. Use the retailer's vendor ID in the route. The route value is trimmed and must not be empty.\n\nA missing competitor returns `404 Not Found`. If the authenticated user has no active workspace, the response is `401 Unauthorized` with a `No active workspace` message.",
        "parameters": [
          {
            "name": "vendorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorDetailSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorDetailSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorDetailSummaryDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitor-detail/{vendorId}/perfect-matches": {
      "get": {
        "tags": [
          "CompetitorDetail"
        ],
        "summary": "Lists perfect product matches for one competitor.",
        "description": "Returns exact or confirmed competitor matches for the Matches tab on the Competitor Detail page.\n\nThe frontend calls `GET /api/competitor-detail/{vendorId}/perfect-matches` with query filters for paging, category, price gap, promo status, stock visibility, search, and sorting. Categories can be sent as a comma-separated list. `page` is forced to at least `1`, and `pageSize` is clamped to `1` through `100`.\n\nSorting accepts `gap_absolute` or `gap_percent`; any other value falls back to `gap_absolute`. Sorting direction accepts `asc`; any other value falls back to `desc`. Set `showOos=false` to hide out-of-stock rows.",
        "parameters": [
          {
            "name": "vendorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "priceGap",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "promo",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "showOos",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "sortBy",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "gap_absolute"
            }
          },
          {
            "name": "sortDir",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "desc"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfCompetitorMatchRowDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfCompetitorMatchRowDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfCompetitorMatchRowDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitor-detail/{vendorId}/similar-matches": {
      "get": {
        "tags": [
          "CompetitorDetail"
        ],
        "summary": "Lists similar product matches for one competitor.",
        "description": "Returns fuzzy or AI-assisted product matches for the Similar Matches tab on the Competitor Detail page.\n\nThe frontend calls `GET /api/competitor-detail/{vendorId}/similar-matches` with the same paging, category, price gap, promo, stock, search, and sort filters as perfect matches. It can also filter by `matchConfidence` and `variantDiff` so users can review match quality and product differences.\n\n`page` is forced to at least `1`, `pageSize` is clamped to `1` through `100`, and unsupported sort values fall back to `gap_absolute` and `desc`.",
        "parameters": [
          {
            "name": "vendorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "priceGap",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "promo",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "showOos",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "sortBy",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "gap_absolute"
            }
          },
          {
            "name": "sortDir",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "desc"
            }
          },
          {
            "name": "matchConfidence",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "variantDiff",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfCompetitorMatchRowDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfCompetitorMatchRowDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfCompetitorMatchRowDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitor-detail/{vendorId}/sensitivity": {
      "get": {
        "tags": [
          "CompetitorDetail"
        ],
        "summary": "Gets sensitivity analysis for one competitor.",
        "description": "Returns the exposure and risk data used by the Sensitivity Analysis tab on the Competitor Detail page.\n\nThe frontend calls `GET /api/competitor-detail/{vendorId}/sensitivity` to render category overlap, undercut distribution, and promo-aggression sections for the selected retailer. Use the optional `sections` query parameter when a client only needs a subset of the sensitivity response.\n\nResults are scoped to the caller's active workspace. If no active workspace can be resolved, the action returns `401 Unauthorized`.",
        "parameters": [
          {
            "name": "vendorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sections",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorSensitivityDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorSensitivityDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorSensitivityDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitor-detail/{vendorId}/insights": {
      "get": {
        "tags": [
          "CompetitorDetail"
        ],
        "summary": "Lists risk and opportunity insights for one competitor.",
        "description": "Returns paginated insight cards for the Risks and Insights tab on the Competitor Detail page.\n\nThe frontend calls `GET /api/competitor-detail/{vendorId}/insights` when users review retailer-specific risks, opportunities, anomalies, and recommendations. Send `page` and `pageSize` as query parameters. `page` is normalized to at least `1`, and `pageSize` is clamped between `1` and `100`.\n\nThis is a read-only endpoint. It does not mark global Insight Cards as viewed or actioned.",
        "parameters": [
          {
            "name": "vendorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfObject"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfObject"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfObject"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitor-detail/{vendorId}/product/{productId}": {
      "get": {
        "tags": [
          "CompetitorDetail"
        ],
        "summary": "Gets product drawer details for a competitor match.",
        "description": "Returns detailed side-panel data for a matched competitor product, including the source product, competitor product, prices, and supporting match metadata.\n\nThe frontend calls `GET /api/competitor-detail/{vendorId}/product` with a `mappingId` query parameter when a user opens a row from the Matches tab. The route also supports `GET /api/competitor-detail/{vendorId}/product/{productId}` when a product ID is available.\n\nEither `mappingId` or `productId` is required. If both are missing, the endpoint returns `400 Bad Request`. If the selected mapping or product is not found for the competitor, it returns `404 Not Found`.",
        "parameters": [
          {
            "name": "vendorId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "mappingId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.ProductDrawerDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.ProductDrawerDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.ProductDrawerDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitors": {
      "get": {
        "tags": [
          "Competitors"
        ],
        "summary": "Lists competitors configured for the current workspace.",
        "description": "Returns the competitor catalog used by the Competitors page, overview filters, charts, and scan configuration workflows.\n\nThe Nesika web app calls `GET /api/competitors` to render competitor cards and to populate controls that let users compare prices by retailer. Results are scoped to the caller's active workspace and come from the workspace company configuration.\n\nCall this endpoint without a request body. Optional query parameters accepted by the frontend service are forwarded as normal query string values, but the current controller action does not bind or validate them directly. A missing company configuration returns `404 Not Found`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorsListResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorsListResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorsListResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitors/add": {
      "put": {
        "tags": [
          "Competitors"
        ],
        "summary": "Adds a competitor to the current workspace.",
        "description": "Creates a competitor entry that the web app can show in competitor management, overview charts, and future scan setup.\n\nThe frontend calls `PUT /api/competitors/add` from the competitor form with a JSON body containing `vendor_id`, `name`, `base_url`, optional `onboarding_status`, optional `notes`, and optional `custom_color`. The request is rejected when the workspace has no company configuration or has reached its competitor limit.\n\nThis action has a side effect: it updates the workspace's competitor catalog. The frontend clears its competitor cache after a successful response so subsequent reads include the new competitor.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.AddCompetitorRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.AddCompetitorRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.AddCompetitorRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitors/{id}": {
      "patch": {
        "tags": [
          "Competitors"
        ],
        "summary": "Updates competitor metadata for the current workspace.",
        "description": "Updates display and matching preferences for an existing competitor used throughout the web app.\n\nThe frontend calls `PATCH /api/competitors/{id}` when a user edits a competitor name, website URL, notes, chart color, or marketplace exclusion setting. Send only the fields that should change in the JSON body. An empty `custom_color` clears the configured color.\n\nThis action has a side effect: it changes the competitor catalog for the active workspace. The frontend clears competitor caches after success so cards, filters, and charts use the updated metadata.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.UpdateCompetitorRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.UpdateCompetitorRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.UpdateCompetitorRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Competitors"
        ],
        "summary": "Deletes a competitor from the current workspace.",
        "description": "Removes a competitor entry from the authenticated workspace's competitor catalog.\n\nThe web app calls `DELETE /api/competitors/{id}` from competitor management screens when a user removes a retailer from their monitored set. A successful delete returns `204 No Content`; missing IDs or unknown competitors return client errors.\n\nThis action has a side effect: the competitor is removed from future competitor lists and downstream UI filters. Existing historical scan data may still contain observations from earlier scans.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/competitors/usage": {
      "get": {
        "tags": [
          "Competitors"
        ],
        "summary": "Gets competitor usage and plan limits for the current workspace.",
        "description": "Returns the number of competitors currently configured and the maximum allowed by the workspace plan.\n\nThe frontend calls `GET /api/competitors/usage` to decide whether the add-competitor workflow should be enabled and to show usage messaging near competitor management controls. If a bulk-onboarded workspace has no usage plan, the action returns a safe fallback with `Used` and `Max` set to `0` rather than failing the page.\n\nCall this endpoint without a request body. Results are scoped to the caller's active workspace.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Usage.CompetitorUsageDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Usage.CompetitorUsageDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Usage.CompetitorUsageDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/contact-requests": {
      "post": {
        "tags": [
          "ContactRequest"
        ],
        "summary": "Submit a contact or demo request.",
        "description": "Creates a contact request from the public marketing contact or book-demo form and returns the saved `ContactRequestDTO` wrapped in `ApiResponse<T>`.\n\nCall `POST /api/contact-requests` without authentication. This action is marked `AllowAnonymous` and is protected by the `ContactFormSubmit` rate-limit policy.\n\nThe service saves the lead before sending the Customer.io admin notification. If persistence fails, the endpoint returns `500` and skips the notification so browser retries do not create duplicate admin alerts.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ContactRequest.CreateContactRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ContactRequest.CreateContactRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ContactRequest.CreateContactRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO"
                }
              }
            }
          }
        }
      }
    },
    "/api/csv-config/analyze": {
      "post": {
        "tags": [
          "CsvConfiguration"
        ],
        "summary": "Analyze a sample CSV file for mapping suggestions.",
        "description": "Returns detected column names, sample rows, the expected CSV field schema, AI-generated standard\nfield suggestions, custom field suggestions, unmapped columns, confidence scores, and reasoning.\n\nThe Nesika web app calls this from the Settings Data Sources CSV configuration wizard after a user\nselects CSV as their data source and uploads a sample file. The response pre-fills the mapping step\nso the user can confirm which incoming columns map to Nesika fields before enabling CSV upload mode.\n\nCall `POST /api/csv-config/analyze` as `multipart/form-data` with a `file` part. The\ncontroller accepts the configured CSV upload extensions, defaulting to `.csv` and `.txt`,\nand enforces the configured sample-file size limit before reading the file.\n\nNotable behavior: the file is copied to memory so it can be read multiple times, only sample rows\nare returned for preview, and validation failures return `400 Bad Request`.",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvAnalysisResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvAnalysisResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvAnalysisResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/csv-config/save": {
      "post": {
        "tags": [
          "CsvConfiguration"
        ],
        "summary": "Save the CSV column mapping configuration.",
        "description": "Creates or updates the active workspace's CSV column mapping and returns the persisted\nconfiguration. Standard mappings connect Nesika fields to uploaded CSV headers; custom field\nmappings connect workspace-specific fields to uploaded headers.\n\nThe web app calls this from the final step of the Settings Data Sources CSV configuration wizard\nafter the user reviews AI suggestions and confirms the required mappings. The frontend then sets\nCSV as the primary vendor data source.\n\nCall `POST /api/csv-config/save` with `columnMappings`, `customFieldMappings`, and\n`isEnabled`. The service requires standard mappings for `product_id`, `name`,\n`description`, `brand`, `price`, and `currency`. Missing required mappings return\n`400 Bad Request`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.SaveCsvMappingDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.SaveCsvMappingDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.SaveCsvMappingDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvColumnMappingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvColumnMappingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvColumnMappingDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/csv-config": {
      "get": {
        "tags": [
          "CsvConfiguration"
        ],
        "summary": "Get the saved CSV column mapping configuration.",
        "description": "Returns the current workspace CSV mapping configuration when one has been saved. The response\nincludes standard field mappings, custom field mappings, required columns, and timestamps.\n\nThe web app calls this from the Settings Data Sources screen to determine whether CSV mode is\nalready configured, to show configuration status, and to decide whether the user should upload\nprices, view upload history, or run the CSV configuration wizard.\n\nCall `GET /api/csv-config`. If no mapping exists for the authenticated user's company, the\nendpoint returns `404 Not Found` with `CONFIGURATION_NOT_FOUND`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvColumnMappingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvColumnMappingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvColumnMappingDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "CsvConfiguration"
        ],
        "summary": "Delete the saved CSV column mapping configuration.",
        "description": "Removes the active workspace's CSV column mapping configuration and returns\n`204 No Content` when a configuration was deleted.\n\nThe web app calls this from the Settings Data Sources screen when a user removes the CSV data\nsource configuration. This resets CSV mapping setup; it does not delete uploaded price history.\n\nCall `DELETE /api/csv-config`. If no configuration exists, the endpoint returns\n`404 Not Found`.",
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/csv-prices/upload": {
      "post": {
        "tags": [
          "CsvPrices"
        ],
        "summary": "Upload product prices from a CSV file.",
        "description": "Parses a CSV price file using the workspace's saved CSV column mapping and stores one price record\nper valid row. The response includes total rows, success and error counts, stored record count,\nupload ID, upload timestamp, effective date, and row-level errors.\n\nThe Nesika web app calls this from Settings Data Sources when CSV is configured as the primary data\nsource and the user uploads updated product prices. The effective date lets users backdate or\nschedule when the uploaded prices should apply.\n\nCall `POST /api/csv-prices/upload` as `multipart/form-data` with a `file` part and\noptional query parameter `effectiveDate`. If `effectiveDate` is omitted, the server uses\nthe current UTC time. A CSV mapping must already exist through `POST /api/csv-config/save`.\n\nNotable behavior: the controller enforces configured file size and extension limits, defaults to\n`.csv` and `.txt` when extensions are not configured, returns row errors instead of\nfailing the whole upload where possible, and returns `400 Bad Request` if CSV configuration is\nmissing or the file is invalid.",
        "parameters": [
          {
            "name": "effectiveDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvPriceUploadResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvPriceUploadResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvPriceUploadResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/csv-prices/history": {
      "get": {
        "tags": [
          "CsvPrices"
        ],
        "summary": "Get paginated CSV price upload history.",
        "description": "Returns one history item per upload ID for the active workspace, ordered by most recent upload.\nEach item includes upload ID, upload date, effective date, uploader, record count, and CSV file name.\n\nThe web app calls this in the CSV Upload History tab under Settings Data Sources to show previous\nuploads and to let users drill into, download, or delete a specific upload.\n\nCall `GET /api/csv-prices/history?page=1&pageSize=20`. Page values below 1 are normalized\nto `1`. Page sizes below 1 or above 100 are normalized to `20`.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadHistoryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadHistoryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadHistoryDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/csv-prices/uploads/{uploadId}": {
      "get": {
        "tags": [
          "CsvPrices"
        ],
        "summary": "Get details for a CSV price upload.",
        "description": "Returns upload metadata plus a paginated list of product price records that were stored for the\nspecified upload ID.\n\nThe web app calls this when a user opens an upload from the CSV Upload History tab. It powers the\ndetails view and product-level pagination before a user decides to download or delete the upload.\n\nCall `GET /api/csv-prices/uploads/{uploadId}?page=1&pageSize=50`. Page values below 1 are\nnormalized to `1`. Page sizes below 1 or above 100 are normalized to `50`. The upload must\nbelong to the authenticated user's company, otherwise the endpoint returns `404 Not Found`.",
        "parameters": [
          {
            "name": "uploadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadDetailsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadDetailsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadDetailsDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "CsvPrices"
        ],
        "summary": "Delete a CSV price upload and its records.",
        "description": "Deletes every price record associated with the specified upload ID for the authenticated user's\ncompany and returns the number of deleted records.\n\nThe web app calls this from the CSV Upload History tab after the user confirms deletion of an\nupload. This removes the uploaded price records from CSV history; it does not remove the saved CSV\ncolumn mapping configuration.\n\nCall `DELETE /api/csv-prices/uploads/{uploadId}`. If the upload ID does not exist for the\ncurrent company, the endpoint returns `404 Not Found`.",
        "parameters": [
          {
            "name": "uploadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/csv-prices/uploads/{uploadId}/download": {
      "get": {
        "tags": [
          "CsvPrices"
        ],
        "summary": "Download a generated CSV for a previous upload.",
        "description": "Reconstructs a CSV file from all price records stored for the specified upload and streams it as\n`text/csv`. The download file name uses the original uploaded file name when available, or a\ndate-based fallback.\n\nThe web app calls this from the CSV Upload History tab when the user clicks the download action for\nan upload. The browser receives a blob and saves it as a CSV file.\n\nCall `GET /api/csv-prices/uploads/{uploadId}/download`. The generated file includes columns\nsuch as `product_id`, `name`, `price`, `was_price`, `brand`,\n`currency`, product URLs, measurement fields, promotion fields, availability fields, SKU, and\n`effective_date`. If the upload has no records for the current company, the endpoint returns\n`404 Not Found`.",
        "parameters": [
          {
            "name": "uploadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-configuration/custom-fields": {
      "get": {
        "tags": [
          "CustomFields"
        ],
        "summary": "Returns custom field definitions for the active workspace.",
        "description": "Product catalog filters, edit drawers, insights, and settings screens call this endpoint to discover which custom fields can be displayed or used as filters for tracked products.\n\nThe response is wrapped in the standard API response object. Definitions include display metadata such as name, filterability, display order, and creation time. Results are scoped to the caller's active workspace.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCustomFieldDefinitionDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCustomFieldDefinitionDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "CustomFields"
        ],
        "summary": "Creates a custom field definition for the active workspace.",
        "description": "Settings and filter-layout screens call this endpoint when an admin adds a new metadata field that can later be populated on tracked products or mapped from CSV imports.\n\nThe request supplies the stable field ID, display name, and whether the field is filterable. Duplicate field IDs or invalid input return 400. Existing tracked products are not modified by creating a definition.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.CreateCustomFieldDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.CreateCustomFieldDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.CreateCustomFieldDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-configuration/custom-fields/{fieldId}": {
      "put": {
        "tags": [
          "CustomFields"
        ],
        "summary": "Updates a custom field definition's display metadata.",
        "description": "Settings and filter-layout screens call this endpoint when an admin renames a field, changes whether it appears in filters, or adjusts display order.\n\nThe `fieldId` route value identifies the existing field definition. The update changes the definition metadata only; values already stored on tracked products remain attached to the same field ID.",
        "parameters": [
          {
            "name": "fieldId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.UpdateCustomFieldDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.UpdateCustomFieldDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.UpdateCustomFieldDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "CustomFields"
        ],
        "summary": "Deletes a custom field definition from the active workspace.",
        "description": "Settings and filter-layout screens call this endpoint when an admin removes a custom metadata field from future product forms and filters.\n\nDeleting the definition does not remove values already stored on existing tracked products. Those values are ignored because the definition no longer exists, so clients should refresh custom-field caches after a successful delete.",
        "parameters": [
          {
            "name": "fieldId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content",
            "content": {
              "application/json": { }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Dashboard/summary": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Gets dashboard summary metrics for an optional date range.",
        "description": "Returns a generic dashboard summary payload from the dashboard service.\n\nCall `GET /api/dashboard/summary` with optional `startDate` and `endDate` query parameters when building a custom dashboard card over a bounded reporting period. Dates are passed through to the service as nullable `DateTime` values.\n\nThe current frontend service layer primarily uses `/api/overview/*` for the active market overview workflow; no current frontend call to this dashboard summary route was found. The response is wrapped by the service in an `ApiResponse`-style object.",
        "parameters": [
          {
            "name": "startDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "endDate",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Dashboard/trends": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Gets trend data for a metric and time period.",
        "description": "Returns a generic trend payload for dashboard charts.\n\nCall `GET /api/dashboard/trends` with a required `metric` query parameter and an optional `period`. The default period is `7d`. The controller passes both values to the dashboard service without additional validation.\n\nThe current frontend service layer primarily uses `/api/overview/basket-analysis/trends` and `/api/overview/competitor-price/trends` for active market charts; no current frontend call to this legacy dashboard route was found.",
        "parameters": [
          {
            "name": "metric",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "7d"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Dashboard/price-table": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Gets dashboard price-table data for a product category and product name.",
        "description": "Returns table headers and price rows for a category/product lookup.\n\nCall `GET /api/dashboard/price-table` with `productCategory` and `productName` query parameters. The controller creates a `PriceTableRequest` and delegates to the dashboard service. The service requires `productCategory` and returns a bad-request response when it is missing.\n\nThe current frontend service layer uses `/api/overview/product-price-table` for the main paginated price table and export workflows; no current frontend call to this legacy dashboard price-table route was found.",
        "parameters": [
          {
            "name": "productCategory",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "productName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTableDataResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTableDataResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTableDataResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/billing/usage": {
      "get": {
        "tags": [
          "DataPointsBilling"
        ],
        "summary": "Get current data-point usage.",
        "description": "Returns consumed data points, quota, percentage used, and current cycle dates for the authenticated active workspace.\n\nCall `GET /api/billing/usage`. The Nesika web app polls this endpoint from the Settings billing data-points usage card about every 60 seconds while the card is mounted.\n\nUse this to show quota burn-down and overage risk. The endpoint only returns data for DataPoints-billing customers and returns `400` otherwise.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointUsageDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointUsageDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointUsageDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/billing/projection": {
      "get": {
        "tags": [
          "DataPointsBilling"
        ],
        "summary": "Get projected data-point consumption.",
        "description": "Returns an estimate of current-cycle data-point consumption based on scheduled scan configuration, assigned products, competitors, and scan profiles.\n\nCall `GET /api/billing/projection`. The Settings billing data-points projection widget polls it about every 60 seconds so users can see likely end-of-cycle consumption.\n\nProjection is advisory. It reflects current scheduled-scan configuration and excludes system ad-hoc scans that are not billed as scheduled data points.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointProjectionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointProjectionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointProjectionDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/billing/trace": {
      "get": {
        "tags": [
          "DataPointsBilling"
        ],
        "summary": "Get billed data-point trace entries.",
        "description": "Returns a paginated trace of scheduled-scan data-point consumption, with optional filters for date range, product, competitor, and scan profile.\n\nCall `GET /api/billing/trace` with query parameters such as `dateFrom`, `dateTo`, `productId`, `competitorId`, `scanProfileId`, `page`, and `pageSize`. Send `Accept: text/csv` to download the same trace as `data-point-trace.csv`.\n\nThe endpoint clamps `page` to at least 1 and `pageSize` to 1 through 200. Use it for billing audit tables and exports.",
        "parameters": [
          {
            "name": "dateFrom",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "dateTo",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "competitorId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "scanProfileId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointTracePageDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointTracePageDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointTracePageDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/billing/scan-profiles/{id}/estimation": {
      "get": {
        "tags": [
          "DataPointsBilling"
        ],
        "summary": "Estimate a scan profile data-point cost.",
        "description": "Returns the monthly estimated data-point consumption for one scan profile based on the products currently assigned to it and their competitor counts.\n\nCall `GET /api/billing/scan-profiles/{id}/estimation` before saving or reviewing a scan profile. Unknown scan profiles return `404`.\n\nUse this to show users the billing impact of scheduled scan-profile configuration before they create or change recurring scans.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.ScanProfileEstimationDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.ScanProfileEstimationDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.ScanProfileEstimationDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/exchange-rates": {
      "get": {
        "tags": [
          "ExchangeRate"
        ],
        "summary": "Get latest exchange rates for a base currency.",
        "description": "Returns the base currency, a currency-code-to-rate dictionary, timestamp, expiry, provider, and\n`isStale` flag. Rates are cached for the configured cache duration, which defaults to 3 hours.\n\nNesika pricing screens and export workflows rely on the same exchange-rate service server-side when\nprices from different currencies need to be converted into a workspace display currency. This\nendpoint exposes those cached rates to authenticated clients that need the same conversion context\nfor multi-currency display or diagnostics.\n\nCall `GET /api/exchange-rates?base=AUD`. The `base` query parameter defaults to\n`AUD`. Provider behavior is automatic: the service tries the primary provider first, falls\nback to a secondary provider, then returns stale cached rates when both providers fail. If no rates\nare available, the response contains an empty `rates` object with `isStale` set to\n`true`.",
        "parameters": [
          {
            "name": "base",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "AUD"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExchangeRateResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExchangeRateResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExchangeRateResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/exploration/search": {
      "get": {
        "tags": [
          "Exploration"
        ],
        "summary": "Search the product exploration universe.",
        "description": "Returns an `ExplorationSearchResultDto` containing a page of products, aggregate\nstatistics, per-vendor breakdown data, and pagination metadata. The result combines the\nactive workspace's own tracked products, confirmed competitor matches, AI-suggested\nmatches, and broader competitor catalog rows.\n\nThe Products - Exploration page calls `GET /api/exploration/search` on load, when\nusers change tabs, when they type in search, when filters change, and when infinite\nscrolling requests the next page. The frontend passes `page`, `pageSize`,\n`tab`, `sortBy`, `sortDir`, and optional filters such as vendors,\ncategories, brands, price range, source, tracking status, and mapping status.\n\n`page` is 1-based and `pageSize` must be from 1 through 200. Source mappings\nin each row can be capped for payload size; when `totalSourceMappingsCount` is\nlarger than the returned mapping list, call `GET /api/exploration/product-mappings`\nfor the full mapping set.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 100
            }
          },
          {
            "name": "tab",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "all"
            }
          },
          {
            "name": "vendors",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "categories",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "brands",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "priceMin",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double",
              "default": null
            }
          },
          {
            "name": "priceMax",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double",
              "default": null
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "trackingStatus",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "all"
            }
          },
          {
            "name": "sortBy",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "name"
            }
          },
          {
            "name": "sortDir",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "asc"
            }
          },
          {
            "name": "mappingStatus",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "all"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationSearchResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/exploration/statistics": {
      "get": {
        "tags": [
          "Exploration"
        ],
        "summary": "Get aggregate product exploration statistics.",
        "description": "Returns `ExplorationStatisticsDto` for the active workspace, including total\nproducts, total vendors, average price, total categories, tracked count, and untracked\ncount.\n\nThe Products - Exploration page calls `GET /api/exploration/statistics` on load to\npopulate the summary cards above the table. The backend caches the statistics to reduce\ndatabase load, and the frontend also keeps a short client-side cache during a browser\nsession.\n\nIf the current user has no active workspace or company association, the endpoint returns\n`403`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationStatisticsDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/exploration/filters": {
      "get": {
        "tags": [
          "Exploration"
        ],
        "summary": "Get available product exploration filters.",
        "description": "Returns `ExplorationFilterOptionsDto` for the active workspace, including distinct\nvendors, categories, brands, and the available price range.\n\nThe Products - Exploration page calls `GET /api/exploration/filters` on load so the\nfilter panel can render only options that exist in the workspace's exploration universe.\nResults are cached server-side to reduce repeated database work during rapid filtering.\n\nUse the returned strings as query values for `GET /api/exploration/search`. If the\nuser has no active workspace or company association, the endpoint returns `403`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationFilterOptionsDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/exploration/track": {
      "post": {
        "tags": [
          "Exploration"
        ],
        "summary": "Track a competitor catalog product from exploration.",
        "description": "Creates a new tracked product in the active workspace from an existing\n`ProductDetails` row and returns the created `TrackedProductDto`. This endpoint\nis intended for exploration workflows where a user promotes a discovered competitor\ncatalog product into their workspace's tracked catalog.\n\nCall `POST /api/exploration/track` with `productId` and `vendorId`. The\nservice verifies that the product exists in `ProductDetails` for that vendor and\nthat the workspace is not already tracking it. A successful call creates the tracked\nproduct, clears exploration caches, and returns `201 Created`.\n\nMissing required fields return `400`, unknown catalog rows return `404`, and\nduplicate tracked products return `409`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackFromExplorationDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackFromExplorationDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackFromExplorationDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/exploration/product-mappings": {
      "get": {
        "tags": [
          "Exploration"
        ],
        "summary": "Get all source mappings for one exploration product.",
        "description": "Returns the full list of `ExplorationSourceMappingDto` records for a product and\nvendor in the active workspace. Source mappings explain which tracked products point to a\ncompetitor product and whether each relationship is a confirmed or suggested match.\n\nThe exploration UI calls `GET /api/exploration/product-mappings` from the tracking\nor linking modal when the search result has capped `sourceMappings`. Provide both\n`productId` and `vendorId` as query parameters. These values come from a row in\n`GET /api/exploration/search`.\n\nThis is a read-only lazy-load endpoint. Missing identifiers return `400`; no active\nworkspace or company association returns `403`.",
        "parameters": [
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vendorId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationSourceMappingDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/export/generate": {
      "post": {
        "tags": [
          "Export"
        ],
        "summary": "Generate an export file for a pricing page.",
        "description": "Returns a streamed file download plus response headers `X-Export-Row-Count` and\n`X-Export-Duration-Ms`. The file name is generated by the server and includes the\nrequested page type and a UTC timestamp.\n\nThe Nesika web app calls this endpoint from the unified Export Data modal after the user\nchooses a preset, file format, data scope, time period, filters, and column selections. It\nis used by the Overview price table, Product Catalog, Competitor Products, Insights, and\nProduct Detail export workflows.\n\nCall `POST /api/export/generate` with a JSON body. Supported `pageType` values\nare `overview`, `tracked-products`, `insights`, `competitor`, and\n`product-detail`. Supported `format` values are `csv`, `excel`, and\n`pdf`. Use `dataScope` to request `current-view`, `entire-catalog`, or\n`specific-categories`. Use `timePeriod``latest-scan` for a current snapshot\nor `historical` with `historicalRange` for date-range exports.\n\nNotable behavior: the endpoint applies any saved template named by `templateId` before\ninline column overrides, rejects historical requests without `historicalRange`, enforces\nrow limits for Excel and PDF exports, times out long data fetch or format conversion work, and\nlimits each user to 3 concurrent exports.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.GenerateExportRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.GenerateExportRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.GenerateExportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/FileStreamResult"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileStreamResult"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileStreamResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/export-templates": {
      "get": {
        "tags": [
          "ExportTemplate"
        ],
        "summary": "List export templates for the current user.",
        "description": "Returns the saved export configurations available to the authenticated user in the active\nworkspace. The response is wrapped in `ApiResponse` and contains template metadata plus\nthe opaque frontend-owned `config` object.\n\nThe web app calls this when the Export Data modal opens so the template selector can show\nreusable configurations for weekly reports, monthly audits, or page-specific exports. It is\nalso used after create, rename, and delete operations to refresh the selector state.\n\nCall `GET /api/export-templates`. Pass `pageType` to show templates relevant to a\nspecific export page. Supported page types match the export endpoint:\n`overview`, `tracked-products`, `insights`, `competitor`, and\n`product-detail`. Templates without a stored page type are always included.",
        "parameters": [
          {
            "name": "pageType",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfExportTemplateResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfExportTemplateResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfExportTemplateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "ExportTemplate"
        ],
        "summary": "Create an export template.",
        "description": "Creates a saved export configuration for the current user and active workspace. The backend\nvalidates the template name, stores the supplied `config` as JSON without interpreting it,\nand returns the created template in an `ApiResponse` wrapper.\n\nThe web app calls this from the save action in the Export Data modal after a user configures\ndata scope, time period, format, columns, and filters and wants to reuse that setup later.\n\nCall `POST /api/export-templates` with `name`, `config`, and optional\n`pageType`. Names must be unique for the user in the workspace and may contain letters,\nnumbers, spaces, hyphens, and underscores. A user can store up to 20 templates per workspace.\nDuplicate names return `409 Conflict`; a full template list returns `400 Bad Request`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.CreateExportTemplateRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.CreateExportTemplateRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.CreateExportTemplateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfExportTemplateResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfExportTemplateResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfExportTemplateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/export-templates/{id}": {
      "patch": {
        "tags": [
          "ExportTemplate"
        ],
        "summary": "Rename an export template.",
        "description": "Updates only the saved template name. The stored export configuration and page type remain\nunchanged.\n\nThe web app calls this from the template management controls in the Export Data modal when a\nuser wants a clearer label for a reusable export configuration.\n\nCall `PATCH /api/export-templates/{id}` with a JSON body containing `name`. The\ntemplate must belong to the authenticated user in the active workspace. Duplicate names return\n`409 Conflict`, missing templates return `404 Not Found`, and another user's template\nreturns `403 Forbidden`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.RenameExportTemplateRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.RenameExportTemplateRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.RenameExportTemplateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfExportTemplateResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfExportTemplateResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfExportTemplateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "ExportTemplate"
        ],
        "summary": "Delete an export template.",
        "description": "Deletes a saved export configuration for the authenticated user in the active workspace and\nreturns `204 No Content` when successful.\n\nThe web app calls this from the Export Data modal template selector when a user removes an\nobsolete saved configuration. Deleting a template does not affect previously generated files or\ncurrent export data.\n\nCall `DELETE /api/export-templates/{id}`. The template must belong to the current user and\nactive workspace. Missing templates return `404 Not Found`; templates owned by another user\nreturn `403 Forbidden`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/feedback": {
      "post": {
        "tags": [
          "Feedback"
        ],
        "summary": "Submit feedback.",
        "description": "Creates a feedback item from an authenticated user and returns the saved `FeedbackDTO` wrapped in `ApiResponse<T>`.\n\nCall `POST /api/feedback` with a `CreateFeedbackRequestDTO` body. The web app uses this from feedback and issue-reporting surfaces when users report incorrect product details, mapping problems, missing data, bugs, performance issues, or feature requests.\n\nThis endpoint requires authentication and validates the request model before saving. Administrative reads and workflow actions for submitted feedback are intentionally excluded from OpenAPI.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.CreateFeedbackRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.CreateFeedbackRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.CreateFeedbackRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-configuration/filter-layout": {
      "get": {
        "tags": [
          "FilterLayout"
        ],
        "summary": "Get the current filter layout.",
        "description": "Returns the active workspace's ordered filter layout, including filter IDs, standard or custom\nfilter type, display names, visibility flags, and last modification metadata.\n\nThe web app calls this through the filter layout service and `useFilterLayout` hook when\nrendering product, overview, and competitor filter bars. It also calls it in the Settings\nFilter Layout tab to seed the drag-and-drop editor.\n\nCall `GET /api/company-configuration/filter-layout`. If no custom layout has been saved,\nthe service returns a default layout instead of `404 Not Found`. Clients should preserve\n`lastModifiedAt` from this response before calling the update endpoint.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "FilterLayout"
        ],
        "summary": "Update the filter layout.",
        "description": "Persists the workspace's filter display order and visibility settings and returns the updated\nlayout. The backend derives display names and filter types from known standard filters and\ncustom field definitions.\n\nThe web app calls this when a user saves changes in the Settings Filter Layout tab after\nreordering filters, hiding filters, or adding custom field filters. Saved layouts are then used\nby filter bars across product and pricing screens.\n\nCall `PUT /api/company-configuration/filter-layout` with `lastModifiedAt` from the\nlatest GET response and an ordered `items` array containing `filterId`,\n`displayOrder`, and `visible`. Display order must be contiguous from `0`. All\nstandard filters and all existing custom fields must be present. If another user saved changes\nfirst, the endpoint returns `409 Conflict` for optimistic concurrency.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterLayout.UpdateFilterLayoutRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterLayout.UpdateFilterLayoutRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterLayout.UpdateFilterLayoutRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-configuration/filter-layout/reset": {
      "post": {
        "tags": [
          "FilterLayout"
        ],
        "summary": "Reset the filter layout to defaults.",
        "description": "Clears the saved layout configuration for the active workspace and returns the default filter\norder and visibility.\n\nThe web app calls this from the Settings Filter Layout tab when a user chooses to discard their\ncustomized filter layout. After reset, product and pricing screens fall back to the standard\nfilter ordering plus available custom fields.\n\nCall `POST /api/company-configuration/filter-layout/reset`. The endpoint records who made\nthe reset when the user email is available and returns the default layout in an\n`ApiResponse` wrapper.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/company-configuration/filter-layout/available-fields": {
      "get": {
        "tags": [
          "FilterLayout"
        ],
        "summary": "Get custom fields available for filter layout.",
        "description": "Returns unique custom field keys discovered across the active workspace's tracked products,\nwith a display name and an `alreadyInLayout` flag for each field.\n\nThe web app calls this when opening the Add Custom Filter dialog in the Settings Filter Layout\ntab. The frontend filters out fields already in the layout and offers the remaining fields as\ncandidates for new custom filters.\n\nCall `GET /api/company-configuration/filter-layout/available-fields`. The endpoint reads\ntracked product custom fields and the current company configuration, then marks fields that are\nalready represented by the saved layout or custom field definitions.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfAvailableCustomFieldDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfAvailableCustomFieldDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Insights": {
      "get": {
        "tags": [
          "Insights"
        ],
        "summary": "Queries Insight Cards for a workspace.",
        "description": "Returns a paged list of AI-generated pricing alerts for the Insights dashboard.\n\nThe web app calls `GET /api/insights` from the Insights page and passes the active `workspaceId` plus optional filters for status, type, severity, date range, product search, snoozed visibility, and pagination. The controller validates that the authenticated user can access the requested workspace before querying cards.\n\nUse `page` and `pageSize` for pagination. `q` searches insight/product text such as product name or SKU. Set `includeSnoozed=true` when building views that should include temporarily hidden cards.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "severity",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSnoozed",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Insights/{insightId}": {
      "get": {
        "tags": [
          "Insights"
        ],
        "summary": "Gets a single Insight Card and marks it as viewed.",
        "description": "Returns the full Insight Card document for a card detail view or expanded card interaction.\n\nThe web app calls `GET /api/insights/{insightId}` when a user opens an insight. The workspace is inferred from the authenticated user's active workspace, not from a query parameter.\n\nThis action has a side effect: after the card is found, it automatically records the current user as having viewed the insight. Use `POST /api/insights/{insightId}/viewed` when you need to explicitly mark the same state without fetching the card detail first.",
        "parameters": [
          {
            "name": "insightId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Insights/{insightId}/viewed": {
      "post": {
        "tags": [
          "Insights"
        ],
        "summary": "Marks an Insight Card as viewed.",
        "description": "Records that the current user has seen an Insight Card and returns the updated card.\n\nThe frontend calls `POST /api/insights/{insightId}/viewed` from card interaction handlers so read/unread UI state can stay in sync. The workspace is inferred from the active user context.\n\nThis action has a side effect: it updates the card lifecycle metadata with the current user's identity. The request does not require a JSON body.",
        "parameters": [
          {
            "name": "insightId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Insights/{insightId}/dismiss": {
      "post": {
        "tags": [
          "Insights"
        ],
        "summary": "Dismisses an Insight Card.",
        "description": "Marks an insight as dismissed so it no longer appears in active insight workflows.\n\nThe web app calls `POST /api/insights/{insightId}/dismiss` when a user dismisses a recommendation from the Insights page. Send a JSON body, even if it is an empty object, because the action binds the body with `[FromBody]`. The optional `reason` can capture why the user dismissed the card.\n\nThis action has a side effect: it updates card status and audit metadata for the current user. Cached insight lists should be refreshed after success.",
        "parameters": [
          {
            "name": "insightId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.DismissRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.DismissRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.DismissRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Insights/{insightId}/snooze": {
      "post": {
        "tags": [
          "Insights"
        ],
        "summary": "Snoozes an Insight Card for a fixed number of hours.",
        "description": "Temporarily hides an insight until the snooze period expires.\n\nThe frontend calls `POST /api/insights/{insightId}/snooze` from the Insights page when a user wants to revisit a recommendation later. Send a JSON body with `hours` greater than `0`. The workspace is inferred from the active user context.\n\nThis action has a side effect: it updates the card's snooze state and user audit metadata. Use `includeSnoozed=true` on the list endpoint to include snoozed cards in a review view.",
        "parameters": [
          {
            "name": "insightId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.SnoozeRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.SnoozeRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.SnoozeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/Insights/{insightId}/action": {
      "post": {
        "tags": [
          "Insights"
        ],
        "summary": "Records an action taken on an Insight Card.",
        "description": "Stores the business action a user took after reviewing an insight, such as repricing, ignoring, or following up offline.\n\nThe web app calls `POST /api/insights/{insightId}/action` from insight action controls. Send a JSON body with a required `action` value and optional `notes`. The workspace is inferred from the current user.\n\nThis action has a side effect: it appends or updates action metadata on the Insight Card and returns the updated card. Cached insight lists should be refreshed after success.",
        "parameters": [
          {
            "name": "insightId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.ActionRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.ActionRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Insights.ActionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/notifications": {
      "get": {
        "tags": [
          "Notifications"
        ],
        "summary": "List notifications.",
        "description": "Returns notifications for the current user, optionally filtered by read status and limited to a maximum number of items.\n\nCall `GET /api/notifications` with optional `status` values such as `unread` or `read`, and optional `limit`. The frontend notification service uses this for the notification bell and for alert-rule fallbacks when a dedicated notification route is not available.\n\nUse this to populate notification lists. Invalid service failures return a sanitized `500` response.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/notifications/unread-count": {
      "get": {
        "tags": [
          "Notifications"
        ],
        "summary": "Get unread notification count.",
        "description": "Returns the unread notification count for the current user as `{ count }`.\n\nCall `GET /api/notifications/unread-count`. The web app uses this for notification badges and header indicators so users can see pending unread items without loading the full list.\n\nUse this endpoint for lightweight polling or page-header refreshes.",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/notifications/{id}/read": {
      "patch": {
        "tags": [
          "Notifications"
        ],
        "summary": "Mark one notification as read.",
        "description": "Marks a single notification as read for the current user and returns `{ success: true }` when it exists.\n\nCall `PATCH /api/notifications/{id}/read` after a user opens or acknowledges a notification. Unknown notification IDs return `404`.\n\nUse this to keep notification read and unread state synchronized with the UI.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/notifications/mark-all-read": {
      "post": {
        "tags": [
          "Notifications"
        ],
        "summary": "Mark all notifications as read.",
        "description": "Marks every notification for the current user as read and returns `{ success: true }`.\n\nCall `POST /api/notifications/mark-all-read` when the user chooses a mark-all-read action from the notification center.\n\nUse this after bulk acknowledgement so the unread badge and notification list can be refreshed together.",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/notifications/{id}": {
      "delete": {
        "tags": [
          "Notifications"
        ],
        "summary": "Dismiss a notification.",
        "description": "Deletes or dismisses one notification for the current user. A successful dismissal returns `204 No Content`.\n\nCall `DELETE /api/notifications/{id}` when the user dismisses an item from the notification list. Unknown notification IDs return `404`.\n\nUse this for one-off dismiss actions; call the list or unread-count endpoints afterward if the UI needs refreshed state.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/valid-for-onboarding": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Check onboarding eligibility.",
        "description": "Returns whether the current authenticated user can start onboarding.\n\nCall `GET /api/onboarding/valid-for-onboarding` before showing the onboarding wizard or creating a session. The endpoint returns `409` when the user already exists, already completed onboarding, or otherwise cannot start a new onboarding flow.\n\nUse this to decide whether to send users to onboarding or to the main application.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/session": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Get the current onboarding session.",
        "description": "Returns the onboarding session for the current authenticated user, including saved stage data and discovered products.\n\nCall `GET /api/onboarding/session` when the onboarding wizard loads, refreshes, or needs to resume progress after navigation.\n\nUse this to rehydrate the wizard. A missing session returns `404`; create one with `POST /api/onboarding/session`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Create an onboarding session.",
        "description": "Creates a new onboarding session for the current authenticated user when they are eligible and do not already have one.\n\nCall `POST /api/onboarding/session` as the first write operation in the onboarding wizard. Existing sessions or ineligible users return `409`.\n\nUse this before saving stage data, running discovery, or collecting payment details.",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/stage/1": {
      "put": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Save onboarding company information.",
        "description": "Saves stage 1 company and website information for the current onboarding session.\n\nCall `PUT /api/onboarding/stage/1` with `Stage1CompanyInfoDTO`. When the saved stage includes a website URL, the controller also starts or resumes product discovery for the session.\n\nUse this after the user enters brand name and website details. Validation or company conflicts return `400` or `409`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage1CompanyInfoDTO2"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage1CompanyInfoDTO2"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage1CompanyInfoDTO2"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/stage/2": {
      "put": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Save onboarding brand details.",
        "description": "Saves stage 2 brand details for the current onboarding session.\n\nCall `PUT /api/onboarding/stage/2` with `Stage2BrandDetailsDTO` after the user reviews or edits discovered brand details.\n\nUse this to persist brand metadata before product and competitor selection.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage2BrandDetailsDTO2"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage2BrandDetailsDTO2"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage2BrandDetailsDTO2"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/stage/3": {
      "put": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Save onboarding product choices.",
        "description": "Saves stage 3 product data, including discovered products and selected product IDs for the current onboarding session.\n\nCall `PUT /api/onboarding/stage/3` with `Stage3ProductsUpdateDTO` after discovery results are reviewed or manual product validation adds products.\n\nUse this to preserve product selections that will later be converted to tracked products during onboarding finalization.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage3ProductsUpdateDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage3ProductsUpdateDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage3ProductsUpdateDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/stage/4": {
      "put": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Save onboarding competitor choices.",
        "description": "Saves stage 4 competitor data for the current onboarding session.\n\nCall `PUT /api/onboarding/stage/4` with `Stage4CompetitorsDTO` after the user selects competitor retailers or marketplaces.\n\nUse this to persist competitor choices before plan and payment selection.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO2"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO2"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO2"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/stage/5": {
      "put": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Save onboarding plan selection.",
        "description": "Saves stage 5 plan and payment-selection data for the current onboarding session.\n\nCall `PUT /api/onboarding/stage/5` with `Stage5PlanSelectionDTO` after the user selects a usage plan.\n\nUse this before payment setup or final onboarding completion so the backend can create the workspace with the chosen plan.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage5PlanSelectionDTO2"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage5PlanSelectionDTO2"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage5PlanSelectionDTO2"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/usage-plans": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "List usage plans for onboarding.",
        "description": "Returns usage plans wrapped in `ApiResponse<T>` for the onboarding plan-selection screen.\n\nCall `GET /api/onboarding/usage-plans` from the onboarding wizard when showing available plans. This endpoint is separate from plan-management routes and uses the onboarding response wrapper.\n\nUse this when a new user must choose a plan before payment setup and workspace creation.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfUsagePlanDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfUsagePlanDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfUsagePlanDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfUsagePlanDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfUsagePlanDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfUsagePlanDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/finish": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Finish onboarding.",
        "description": "Finalizes the current onboarding session and persists the collected user, organization, workspace, selected products, configuration, subscription, and membership data according to service rules.\n\nCall `POST /api/onboarding/finish` after all required stages are complete and payment requirements have been satisfied or are not required for the selected flow.\n\nThe service is designed to be idempotent across finalization steps. Incomplete or invalid sessions return `400`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/brand-discovery": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Discover brand details.",
        "description": "Discovers brand details from the website and company name saved in stage 1 of the current onboarding session.\n\nCall `POST /api/onboarding/brand-discovery` after stage 1 is saved. The action reads the current session instead of accepting company details directly in the request body.\n\nUse this to prefill brand details that the user can review in stage 2. Missing stage 1 data returns `400`; missing session returns `404`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/competitor-discovery": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Discover competitors.",
        "description": "Discovers competitor suggestions from a company name and optional website.\n\nCall `POST /api/onboarding/competitor-discovery` with `CompetitorDiscoveryRequest`. The frontend retries this operation for transient failures when building competitor suggestions.\n\nUse this in the competitor step to reduce manual entry. A missing company name returns `400`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CompetitorDiscoveryRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CompetitorDiscoveryRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CompetitorDiscoveryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/product-discovery": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Start or resume product discovery.",
        "description": "Creates or resumes a product discovery scan for the current onboarding session and returns the job response used for polling.\n\nCall `POST /api/onboarding/product-discovery` with an optional `CreateProductDiscoveryRequest` containing `crawlStrategy`. The wizard then polls `GET /api/onboarding/product-discovery/status`.\n\nUse this when the user asks Nesika to discover products from the saved website. Missing session returns `404`; validation failures return `400`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CreateProductDiscoveryRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CreateProductDiscoveryRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CreateProductDiscoveryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/product-discovery/status": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Get product discovery status.",
        "description": "Returns the current product discovery job status for the current onboarding session.\n\nCall `GET /api/onboarding/product-discovery/status` while the discovery scan is running. The response contains status information from the onboarding job record and can be used to drive progress indicators.\n\nUse this for polling until the discovery job is finished, failed, or missing. A missing job returns `404`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/product-discovery/results": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Get product discovery results.",
        "description": "Returns discovered products from the current onboarding session after product discovery has populated stage 3 data.\n\nCall `GET /api/onboarding/product-discovery/results` after status polling shows the scan is complete. The response includes products and count.\n\nUse this to render the product review and selection step. Missing session or missing job data returns `404`; incomplete discovery can return `400`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/product-validation": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Queue product URL validation.",
        "description": "Enqueues a manually entered product URL for validation during onboarding and returns a validation job ID.\n\nCall `POST /api/onboarding/product-validation` with `EnqueueProductValidationRequest`. The wizard polls `GET /api/onboarding/product-validation/status/{jobId}` and then reads `GET /api/onboarding/product-validation/result/{jobId}`.\n\nThe endpoint prevents blank URLs, duplicate discovered URLs, duplicate in-progress validations, completed validation duplicates, and excessive retries. Some validation-limit failures return `429`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.EnqueueProductValidationRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.EnqueueProductValidationRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.EnqueueProductValidationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/product-validation/status/{jobId}": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Get product validation status.",
        "description": "Returns the status for one onboarding product-validation job.\n\nCall `GET /api/onboarding/product-validation/status/{jobId}` after queuing a manual URL validation. Blank IDs return `400` and unknown jobs return `404`.\n\nUse this to update inline validation progress next to a manually entered product URL.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/product-validation/result/{jobId}": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Get product validation result.",
        "description": "Returns the result for a completed onboarding product-validation job and adds the validated product to discovered products when service rules allow it.\n\nCall `GET /api/onboarding/product-validation/result/{jobId}` after status indicates completion. Blank IDs return `400` and missing or incomplete results return `404`.\n\nUse this to move a successfully validated manual URL into the product review list.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/setup-payment": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Initialize onboarding payment setup.",
        "description": "Creates or retrieves the Stripe customer and Setup Intent needed to collect a payment method for the current onboarding session.\n\nCall `POST /api/onboarding/setup-payment` from the plan and payment step before collecting card details. Missing onboarding session returns `404`; invalid session or payment state returns `400`.\n\nUse this before calling `POST /api/onboarding/confirm-payment`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/confirm-payment": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Confirm onboarding payment.",
        "description": "Validates the Stripe Setup Intent and selected usage plan, then completes the payment-backed onboarding workflow.\n\nCall `POST /api/onboarding/confirm-payment` with `ConfirmPaymentRequest` containing the setup intent and usage plan identifiers. The response contains onboarding completion details.\n\nUse this after payment collection succeeds. Missing sessions return `404`; invalid payment or plan state returns `400`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Billing.ConfirmPaymentRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Billing.ConfirmPaymentRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Billing.ConfirmPaymentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/tutorial/progress": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Get tutorial progress.",
        "description": "Currently returns `501 Not Implemented` because tutorial progress persistence has not been wired to onboarding metadata.\n\nCall `GET /api/onboarding/tutorial/progress` only if the client can handle `501`. This route is reserved for future post-onboarding tutorial state.\n\nDo not rely on this endpoint for persisted onboarding state yet; use the onboarding session endpoints for current wizard progress.",
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Update tutorial progress.",
        "description": "Currently returns `501 Not Implemented` because tutorial progress persistence has not been wired to onboarding metadata.\n\nCall `PUT /api/onboarding/tutorial/progress` with `UpdateTutorialProgressRequest` only when the client can handle `501`. The action validates the model before returning the not-implemented response.\n\nThis route is reserved for future tutorial step completion after onboarding.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.UpdateTutorialProgressRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.UpdateTutorialProgressRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.UpdateTutorialProgressRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/onboarding/start-discovery": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Start crawl discovery.",
        "description": "Starts an OpenCrawl async crawl-discovery job for a company when crawl discovery is enabled in company configuration.\n\nCall `POST /api/onboarding/start-discovery` with `StartDiscoveryRequestDTO`. The request must include `companyId`; missing values return `400`.\n\nUse this for crawl-based discovery workflows that run after a company exists. The endpoint records current-user email and source IP for audit context before delegating to the crawl discovery service.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StartDiscoveryRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StartDiscoveryRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StartDiscoveryRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfStartDiscoveryResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfStartDiscoveryResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfStartDiscoveryResponseDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/me/context": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get the current user's active organization and workspace context.",
        "description": "Returns the organization and workspace that the API will use for workspace-scoped requests made by the authenticated user. The Nesika web app uses this data during app bootstrap, workspace switching, and settings navigation so the UI can show the active organization/workspace and route subsequent calls to the correct workspace.\n\nCall `GET /api/me/context` with the normal bearer token. The response is wrapped in `ApiResponse<UserContextDto>`. If no active context has been set, the endpoint returns `404`; if the token cannot be mapped to a user, it returns `401`.\n\nThe result is read-only. It does not switch context or create memberships.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfUserContextDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfUserContextDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfUserContextDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/me/active-context": {
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Switch the current user's active organization and workspace context.",
        "description": "Updates the authenticated user's active organization and workspace so later workspace-scoped APIs, such as products, competitors, company configuration, billing, and members, operate against the selected workspace. The Nesika web app calls this from the workspace switcher and organization navigation flows.\n\nCall `POST /api/me/active-context` with a `SwitchContextRequestDto` body containing the target organization and workspace identifiers. The service validates that the user can access the requested context before saving it.\n\nThis endpoint has a side effect: it persists the active context for the user. Failed validation returns `403`; malformed or missing users return the standard error wrapper.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.SwitchContextRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.SwitchContextRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.SwitchContextRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/{orgId}": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get organization details by organization ID.",
        "description": "Returns metadata for one organization. The web app uses it on organization settings and administration screens when it needs the organization name, status, billing boundary, or workspace relationship.\n\nCall `GET /api/organizations/{orgId}`. The caller must either have access to the organization or be a system administrator. The response is wrapped in `ApiResponse<Organization>`.\n\nThis is a read-only endpoint. It does not return all organizations and does not change the active workspace.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganization"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganization"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganization"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/{orgId}/workspaces": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get workspaces that belong to an organization.",
        "description": "Returns workspace summaries for the specified organization. The Nesika web app uses this for organization settings, workspace management, and organization dashboards where an administrator needs to view or choose workspaces under the organization.\n\nCall `GET /api/organizations/{orgId}/workspaces`. The caller must be able to administer organizations and must have access to the requested organization. Results are organization-scoped and do not include workspaces from other organizations.\n\nThis endpoint is read-only and is not paginated in the controller.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSummaryDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Organizations"
        ],
        "summary": "Create a workspace within an organization.",
        "description": "Creates a new workspace under the specified organization. The web app uses this from organization or admin workspace setup flows when an authorized administrator adds another workspace for a customer organization.\n\nCall `POST /api/organizations/{orgId}/workspaces` with a `CreateWorkspaceDto` body. The caller must have organization-administration permissions, such as `OrgAdmin`, compatible legacy admin roles, or system-level roles allowed by the authorization helper.\n\nThis endpoint has side effects: it creates workspace records and related setup handled by the organization service. Validation or business-rule failures return `400`; missing authorization returns `403`.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.CreateWorkspaceDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.CreateWorkspaceDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.CreateWorkspaceDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceSummaryDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/{orgId}/members": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get members of an organization.",
        "description": "Returns organization-level members for an organization administration view. The web app uses this on members or organization settings screens when administrators need to review access at the organization boundary.\n\nCall `GET /api/organizations/{orgId}/members`. The caller must have organization-administration permissions. Results are scoped to the supplied organization and are returned in an `ApiResponse<IEnumerable<MemberDto>>` wrapper.\n\nThis endpoint is read-only and does not include the richer workspace-by-workspace report; use `GET /api/organizations/{orgId}/members-report` for that report.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfMemberDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfMemberDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfMemberDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/{orgId}/billing-portal": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Create a Stripe billing portal URL for an organization.",
        "description": "Returns a short-lived billing portal URL that the Nesika web app can redirect an organization administrator to when they manage payment methods, invoices, and subscriptions from the billing settings screen.\n\nCall `GET /api/organizations/{orgId}/billing-portal?returnUrl={returnUrl}`. The caller must be an administrator for the organization, and `returnUrl` is required so Stripe can send the user back to the app.\n\nThis endpoint has a side effect outside the database: it asks the billing provider to create a portal session. Do not cache the returned URL for long-lived use.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "returnUrl",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBillingPortalDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBillingPortalDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBillingPortalDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/{orgId}/subscriptions": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get workspace subscription summaries for an organization.",
        "description": "Returns subscription details for each workspace under an organization. The billing settings and organization administration screens use this to display which workspaces are subscribed and how billing is configured.\n\nCall `GET /api/organizations/{orgId}/subscriptions`. The caller must be an administrator for the organization. Results are scoped to the organization and returned in an `ApiResponse<IEnumerable<WorkspaceSubscriptionDto>>` wrapper.\n\nThis endpoint is read-only. Use the billing portal endpoint when the user needs to make billing changes.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSubscriptionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSubscriptionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSubscriptionDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/analytics/current": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get analytics for the current user's active organization.",
        "description": "Returns a consolidated organization analytics payload for the authenticated user's active organization, including workspace, subscription, and membership details. The Nesika web app uses this for organization dashboards and settings pages that need a single organization overview without making many smaller calls.\n\nCall `GET /api/organizations/analytics/current`. The active context determines the organization. The caller must have access appropriate for the service-level organization analytics query.\n\nThis endpoint is read-only and uses the user's active context; switch context first if the user needs analytics for a different organization.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCurrentOrganizationAnalyticsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCurrentOrganizationAnalyticsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCurrentOrganizationAnalyticsDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/{orgId}/billing-report": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get a billing report for all workspaces in an organization.",
        "description": "Returns organization-level billing data across all workspaces. The billing settings and organization administration screens use this when administrators need a roll-up view of workspace plans, usage, and billing status.\n\nCall `GET /api/organizations/{orgId}/billing-report`. The caller must be an administrator for the organization. The response is wrapped in `ApiResponse<OrganizationBillingDto>`.\n\nThis endpoint is read-only and report-oriented. It does not open the billing portal or change subscriptions.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganizationBillingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganizationBillingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganizationBillingDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/organizations/{orgId}/members-report": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get a members report for all workspaces in an organization.",
        "description": "Returns member information and pending invitations grouped across the organization's workspaces. The members administration screen uses this report when administrators need to audit organization access and outstanding invitations.\n\nCall `GET /api/organizations/{orgId}/members-report`. The caller must be an administrator for the organization. The response is wrapped in `ApiResponse<OrganizationMembersDto>`.\n\nThis endpoint is read-only. Invitation creation, cancellation, and resend operations use the invitation endpoints.",
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganizationMembersDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganizationMembersDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOrganizationMembersDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/billing-report": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get a billing report for one workspace.",
        "description": "Returns billing details for a single workspace. The workspace billing panel uses this when an administrator drills into one workspace from organization billing or workspace settings.\n\nCall `GET /api/workspaces/{workspaceId}/billing-report`. The caller must pass the workspace-level admin validation used by this controller, which allows workspace administrators, organization administrators, and permitted system roles.\n\nThis endpoint is read-only and scoped to one workspace. It does not alter payment methods or subscriptions.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceBillingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceBillingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceBillingDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/members-report": {
      "get": {
        "tags": [
          "Organizations"
        ],
        "summary": "Get a members report for one workspace.",
        "description": "Returns members and pending invitations for a single workspace. The workspace members panel uses this when administrators manage or audit users in one workspace.\n\nCall `GET /api/workspaces/{workspaceId}/members-report`. The caller must pass workspace-level admin validation for the requested workspace.\n\nThis endpoint is read-only. Use the workspace members and invitations endpoints to add, update, remove, cancel, or resend records.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceMembersDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceMembersDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceMembersDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/statistics": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Get overview statistics",
        "description": "Returns the summary KPI values used at the top of the Overview market-analysis workflow.\n\nThe web app calls `GET /api/overview/statistics` when rendering overview cards such as tracked product counts, competitor coverage, and price-position summaries. Query filters can narrow the calculation by `scanId`, `competitors`, `category`, `includeSimilar`, `customFields`, `inStockOnly`, `currency`, `owner`, and `tags`.\n\nCustom field filters are validated against the caller's active workspace before the service runs. If the workspace cannot be resolved the action returns `403 Forbidden`; if no data matches the filters it returns a bad-request `ApiResponse` error.",
        "parameters": [
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/filters": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Get overview filters, optionally narrowed by active selections for cross-filter cascading",
        "description": "Returns available filter values for the Overview page and can cascade options based on active selections.\n\nThe frontend calls `GET /api/overview/filters` on page load to populate category, custom field, owner, and tag controls. It calls the same endpoint with active query selections when a user changes filters so the remaining options only include values that exist in the narrowed dataset.\n\nPass optional `scanId`, `category`, `customFields`, `owner`, and `tags` query parameters. This endpoint is read-only and disables response caching so filter options reflect the latest scan-backed data.",
        "parameters": [
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.OverviewFiltersDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.OverviewFiltersDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.OverviewFiltersDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/basket-analysis/trends": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Get basket analysis trends",
        "description": "Returns historical basket-analysis trend data for overview charts.\n\nThe web app calls `GET /api/overview/basket-analysis/trends` when rendering the Overview trend chart for a selected scan and filters. `scanId` is required. The request also supports competitor, category, similar-match, custom-field, in-stock, currency, owner, tag, and `limit` filters.\n\nThe `limit` value comes from `TrendsRequestDto` and is validated between `1` and `50`. Custom field filters are validated for the active workspace before data is queried.",
        "parameters": [
          {
            "name": "Limit",
            "in": "query",
            "schema": {
              "maximum": 50,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/basket-analysis/matrix": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Get basket analysis",
        "description": "Returns the basket-analysis matrix used to compare the workspace's basket against selected competitors.\n\nThe frontend calls `GET /api/overview/basket-analysis/matrix` for the market-analysis matrix on the Overview page. Query filters can narrow by scan, competitors, category, match quality via `includeSimilar`, custom fields, stock availability, currency, owner, and tags.\n\nUse this endpoint when a client needs aggregated basket-level comparison data rather than row-level product prices. Invalid custom field filters return a bad-request `ApiResponse` error before analytics are calculated.",
        "parameters": [
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/competitor-price/matrix": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Get competitor price matrix",
        "description": "Returns a competitor-by-product price matrix for the Overview comparison table.\n\nThe web app calls `GET /api/overview/competitor-price/matrix` to compare selected competitors across the workspace's products. Use the common overview filters to scope the matrix by scan, competitor list, category, similar-match inclusion, custom fields, stock state, currency, owner, and tags.\n\nThe endpoint returns matrix data wrapped in an `ApiResponse`. It is read-only and uses no-store response caching so the UI can refresh after new scan data arrives.",
        "parameters": [
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/competitor-price/trends": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Get competitor price trends",
        "description": "Returns historical competitor price trend data for overview charts.\n\nThe frontend calls `GET /api/overview/competitor-price/trends` when a chart needs retailer-level price movement over recent scans. `scanId` is required, and `limit` controls how many historical scans are included.\n\nThe request supports the common overview filters and validates custom fields before querying. Use `includeSimilar=true` when the chart should include similar matches as well as perfect matches.",
        "parameters": [
          {
            "name": "Limit",
            "in": "query",
            "schema": {
              "maximum": 50,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/product-price-table": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Get product price table",
        "description": "Returns the paginated row-level price table used by the Overview page.\n\nThe web app calls `GET /api/overview/product-price-table` to render product rows with competitor prices. Use `page` and `pageSize` for pagination, `query` to search product name, SKU, brand, or category, and `matchedOnly=true` to include only products with at least one competitor match for the selected competitors.\n\nCommon overview filters are also supported. `page` must be at least `1` and `pageSize` must be between `1` and `500`. Invalid custom field filters return a bad-request `ApiResponse` error.",
        "parameters": [
          {
            "name": "Query",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Page",
            "in": "query",
            "schema": {
              "maximum": 2147483647,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "PageSize",
            "in": "query",
            "schema": {
              "maximum": 500,
              "minimum": 1,
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "MatchedOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/product-price-table-export": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Export product price table in various formats (PDF, Excel, CSV)",
        "description": "Exports the overview product price table as a downloadable file.\n\nThe frontend calls `GET /api/overview/product-price-table-export` from the export modal after the user chooses a format. `format` must be `pdf`, `excel`, or `csv`. The endpoint applies the same scan, competitor, category, similar-match, custom-field, stock, currency, owner, and tag filters as the table, but exports all matching rows instead of the current page.\n\nThis action returns a file response with the generated content type and file name. It also sets `X-Export-Filters-Applied` to indicate whether narrowing filters were used. If no products match the filters, the endpoint returns `400 Bad Request`.",
        "parameters": [
          {
            "name": "Format",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/rolling-price-export": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Export rolling price data with 13w/52w metrics (v2 export)",
        "description": "Exports rolling price metrics as CSV, including 13-week and 52-week averages and discount-frequency fields.\n\nThe web app calls `GET /api/overview/rolling-price-export` from export workflows that need the extended market-analysis dataset. Send common overview filters plus `includeTotalMarket` and `timezone`. The timezone is used for ISO week calculations and defaults to `UTC`.\n\nBefore generating the file, the action validates custom fields, estimates row count, and rejects overly large synchronous exports. Requests above `50,000` estimated rows are rejected with guidance to apply filters; requests above the hard `200,000` row limit are also rejected. Client cancellation returns status `499`.",
        "parameters": [
          {
            "name": "IncludeTotalMarket",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Timezone",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/overview/historical-bulk-export": {
      "get": {
        "tags": [
          "Overview"
        ],
        "summary": "Export historical bulk price data in wide format (12-month, one row per article per scan week)",
        "description": "Exports historical bulk price data as CSV in a wide format with one row per article per scan week.\n\nThe frontend calls `GET /api/overview/historical-bulk-export` from export workflows that need a long-range dataset for offline analysis. Send common overview filters plus `timezone`, optional inclusive `startDate` and `endDate`, and optional `productSku` to limit output to a single source product.\n\nThe action validates custom fields, estimates row count, and rejects exports that are too large for synchronous generation. Requests above `50,000` estimated rows are rejected with guidance to apply filters; requests above the hard `200,000` row limit are also rejected. Client cancellation returns status `499`.",
        "parameters": [
          {
            "name": "Timezone",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "StartDate",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "EndDate",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ProductSku",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ScanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Competitors",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "IncludeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "CustomFields",
            "in": "query",
            "schema": {
              "type": "object",
              "additionalProperties": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          {
            "name": "InStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "Currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/plan-management/usage-plans": {
      "get": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "List usage plans.",
        "description": "Returns the configured usage plans that can be shown in billing, onboarding plan selection, and administrative plan-management UI.\n\nCall `GET /api/plan-management/usage-plans` with an authenticated request. The response is a raw list of `UsagePlanDto` items, not wrapped in `ApiResponse<T>`.\n\nUse this when the web app needs plan limits, feature flags, chat quotas, API-access flags, and add-on prices before rendering plan selection or comparison controls.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/plan-management/usage-plans/{planId}": {
      "get": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Get one usage plan.",
        "description": "Returns a single `UsagePlanDto` by plan identifier after validating that the current user has billing access to the active workspace.\n\nCall `GET /api/plan-management/usage-plans/{planId}`. The caller must have an active workspace context; missing workspace context returns forbidden and unknown plan IDs return `404`.\n\nUse this when the web app needs detailed plan limits for the currently selected or target plan.",
        "parameters": [
          {
            "name": "planId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/plan-management/company-usage": {
      "get": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Get current workspace plan usage.",
        "description": "Returns the active workspace plan, current usage counts, quotas, and feature limits used by the Settings billing screen.\n\nCall `GET /api/plan-management/company-usage` with an authenticated user that can access billing for the active workspace. The endpoint derives the workspace from the current user context.\n\nUse this before rendering quota bars, plan-limit warnings, or upgrade prompts. Missing workspace context returns forbidden; invalid subscription state returns `400`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanyPlanUsageDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanyPlanUsageDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanyPlanUsageDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/plan-management/subscriptions/{companyId}": {
      "get": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Get a workspace subscription.",
        "description": "Returns the subscription detail for the requested company or workspace after billing access validation.\n\nCall `GET /api/plan-management/subscriptions/{companyId}`. The `companyId` path value is validated against the caller billing permissions before subscription data is returned.\n\nUse this in billing administration or workspace settings when the UI needs the current plan, add-ons, Stripe-derived status fields, and quota configuration for one workspace.",
        "parameters": [
          {
            "name": "companyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanySubscriptionDetailDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanySubscriptionDetailDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanySubscriptionDetailDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Create a workspace subscription.",
        "description": "Creates the initial subscription record for a company or workspace using the supplied usage plan and add-on selection.\n\nCall `POST /api/plan-management/subscriptions/{companyId}` with a `CreateCompanySubscriptionRequestDto` body. The caller must have organization billing access for the active organization.\n\nUse this from billing administration when a workspace has no subscription yet. Duplicate or incompatible state returns `409`; missing company or plan data returns `404`.",
        "parameters": [
          {
            "name": "companyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CreateCompanySubscriptionRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CreateCompanySubscriptionRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CreateCompanySubscriptionRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanySubscriptionDetailDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanySubscriptionDetailDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.CompanySubscriptionDetailDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Cancel a workspace subscription.",
        "description": "Cancels the company or workspace subscription and may deactivate the workspace or cancel the linked Stripe subscription according to service rules.\n\nCall `DELETE /api/plan-management/subscriptions/{companyId}?immediately=false`. The optional `immediately` query value controls whether cancellation is requested immediately or at the end of the current period.\n\nUse this from billing settings when an administrator confirms cancellation. Invalid cancellation state returns `400`; missing subscription data returns `404`.",
        "parameters": [
          {
            "name": "companyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "immediately",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/plan-management/subscriptions/{companyId}/usage-plan": {
      "put": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Change a workspace usage plan.",
        "description": "Changes the usage plan for a company or workspace and lets the service calculate any required resource adjustments for the transition.\n\nCall `PUT /api/plan-management/subscriptions/{companyId}/usage-plan` with a `ChangeCompanyPlanRequestDto` body. Run `GET /api/plan-management/subscriptions/{companyId}/validate-plan-change/{targetPlanId}` first when the UI wants to preview conflicts.\n\nUse this from Settings billing when an org or workspace administrator confirms a plan change. Usage conflicts or invalid transitions return `400`.",
        "parameters": [
          {
            "name": "companyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.ChangeCompanyPlanRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.ChangeCompanyPlanRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.ChangeCompanyPlanRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanManagementResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanManagementResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanManagementResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/plan-management/subscriptions/{companyId}/validate-plan-change/{targetPlanId}": {
      "get": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Validate a plan change.",
        "description": "Checks whether the requested target plan can support the current workspace usage before the user commits a change.\n\nCall `GET /api/plan-management/subscriptions/{companyId}/validate-plan-change/{targetPlanId}`. A successful response includes validation details; usage conflicts return `400` with the validation errors.\n\nUse this to power confirmation dialogs and disabled states in Settings billing so users understand quota or feature conflicts before changing plans.",
        "parameters": [
          {
            "name": "companyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "targetPlanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanChangeValidationDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanChangeValidationDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanChangeValidationDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/plan-management/addons/{companyId}": {
      "put": {
        "tags": [
          "PlanManagement"
        ],
        "summary": "Update workspace add-ons.",
        "description": "Updates subscription add-ons and extra resource counts for an existing company or workspace subscription.\n\nCall `PUT /api/plan-management/addons/{companyId}` with an `UpdateCompanySubscriptionRequestDto` body. The response reloads the subscription detail after the update so the UI can refresh billing state immediately.\n\nUse this from billing administration or Settings billing when toggling daily refresh, advanced fields, data-point quota enforcement, or extra user, competitor, SKU, or data-point allowances.",
        "parameters": [
          {
            "name": "companyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UpdateCompanySubscriptionRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UpdateCompanySubscriptionRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UpdateCompanySubscriptionRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanManagementResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanManagementResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.PlanManagementResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/filter-options": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns cascading product-detail filter options for category, product, scan, and mapping-type selectors.",
        "description": "The Product Details screen calls this endpoint as users narrow the analysis context: initial load returns available categories, adding a `category` returns products, adding a `sku` returns scan choices, and adding a `scanId` returns mapping-type options.\n\nUse query parameters to build the cascade rather than posting UI state. `owner` is an exact case-insensitive filter, and `tags` is a comma-separated OR filter. Responses are not cached by the server so newly completed scans can appear after a client refresh.",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "productName",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sku",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "owner",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterOptionsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns detailed catalog metadata for a single source product.",
        "description": "Product detail drawers and mapping views call this endpoint after a user selects a product from the catalog or filter cascade. The response contains the product information needed to render the product header and downstream analysis cards.\n\nCall with the route value from the selected product or SKU: `GET /api/product-details/{productId}`. A missing product returns 404 rather than an empty product so clients can show a not-found state.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductDetailsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/competitor-products": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns a paginated table of competitor products matched to a source product.",
        "description": "Product Details, pricing drawers, and overview price tables use this endpoint to show the competitor rows behind summary metrics. It returns enriched competitor products with pagination so the UI can page through large match sets.\n\n`scanId` pins results to a scan; when omitted the service uses the latest available scan. `includeSimilar` expands beyond perfect matches. `inStockOnly`, `includeOutOfStock`, and `currency` control table filtering and currency presentation. Use `page` and `pageSize` for pagination.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          },
          {
            "name": "inStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeOutOfStock",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorProductTableDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/competitor-summary": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns aggregate competitor pricing metrics for a source product.",
        "description": "Product Details and catalog pricing drawers call this endpoint to populate average competitor price, price-position, and related summary cards before the user drills into row-level matches.\n\nOmit `scanId` to summarize the latest scan, or provide it for historical/deep-link views. `includeSimilar` controls whether similar matches influence the aggregation. `inStockOnly` and `currency` let the frontend keep summary cards aligned with table filters.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "inStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorSummaryDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/price-trends": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns historical competitor price trends for charting a source product.",
        "description": "Product timeline charts use this endpoint to plot competitor prices across previous scans. The selected `scanId` acts as the anchor point for looking backward; when omitted the latest scan is used.\n\n`limit` controls how many historical scans are included and must be between 1 and 1000. Use `includeSimilar`, `inStockOnly`, and `currency` to keep the chart aligned with the active analysis filters.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 5
            }
          },
          {
            "name": "inStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PriceTrendsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/unit-of-measure-price-trends": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns historical competitor prices normalized by unit of measure.",
        "description": "Unit-of-measure charts call this endpoint when the UI needs comparable prices such as per litre, per kilogram, or per millilitre across differently sized competitor products.\n\nThe endpoint uses `scanId` as the historical anchor, defaults to the latest scan when omitted, and validates `limit` from 1 to 1000. Use `includeSimilar`, `inStockOnly`, and `currency` to mirror the active product-analysis filters.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 5
            }
          },
          {
            "name": "inStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UnitOfMeasurePriceTrendsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/unit-price-trends": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns historical competitor prices normalized by bundle unit.",
        "description": "Product unit-price charts use this endpoint to compare price per item or bundle unit when competitor pack sizes differ. It is similar to unit-of-measure trends but normalizes by product quantity or bundle size.\n\nThe endpoint uses `scanId` as the historical anchor, defaults to the latest scan when omitted, and validates `limit` from 1 to 1000. Use `includeSimilar`, `inStockOnly`, and `currency` to keep chart data aligned with the current filters.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 5
            }
          },
          {
            "name": "inStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UnitPriceTrendsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/market-benchmarks": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns market benchmark averages and comparison metrics for a source product.",
        "description": "Market analysis cards call this endpoint to display current market average, rolling 13-week and 52-week averages, percentage movement, and comparison to the user's own price.\n\nProvide `scanId` to align benchmark calculations to a selected scan, or omit it for the latest context. `includeSimilar` controls match breadth, and `currency` requests converted benchmark values.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.MarketBenchmarksDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/promotion-frequency": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns promotion-frequency metrics for a source product.",
        "description": "Promotion analysis cards call this endpoint to show how often the market is discounted, whether the product is currently promoted, and how promotion frequency varies by retailer.\n\n`period` controls the lookback window and accepts values such as `1m`, `3m`, `6m`, `13w`, `52w`, and `all`. Provide `scanId`, `includeSimilar`, and `currency` to match the selected product-analysis context.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "period",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "13w"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PromotionFrequencyDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/promotion-breakdown": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Returns detailed promotion events and retailer-level promotion analytics for a source product.",
        "description": "The promotion breakdown panel calls this endpoint when a user expands from summary promotion frequency into discount events, discount patterns, and retailer-specific behaviour.\n\n`period` controls the lookback window and accepts values such as `1m`, `3m`, `6m`, `13w`, `52w`, and `all`. Provide `scanId`, `includeSimilar`, and `currency` to keep the breakdown aligned with the selected analysis context.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "period",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "13w"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PromotionBreakdownDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-details/{productId}/historical-export": {
      "get": {
        "tags": [
          "ProductDetails"
        ],
        "summary": "Exports 12 months of product historical price data as a wide-format CSV file.",
        "description": "Product detail export actions call this endpoint when a user downloads historical pricing for one source product. The service resolves the tracked product in the active workspace, generates a CSV, and streams it as a file response.\n\n`includeSimilar` controls whether similar matches are included in the export. `timezone` is used for ISO week calculations and defaults to `UTC`. If no rows are available, the endpoint returns 404. If the client disconnects, the endpoint may return 499.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "timezone",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "UTC"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping": {
      "get": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Returns enriched suggested product mappings for the active workspace.",
        "description": "Product Mapping, fine-tuning, and QA review screens call this endpoint to list candidate matches with product names, images, prices, confidence, validation state, and selection flags.\n\nPass `productId` to show mappings for one tracked product; otherwise use `query`, `owner`, and comma-separated `tags` for broader search. Results are paged and ordered by confidence. By default mappings such as wrong product and not found are filtered out; set `showAll=true` for review screens that need the full set.",
        "parameters": [
          {
            "name": "productId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 500
            }
          },
          {
            "name": "owner",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "showAll",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingsListDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingsListDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingsListDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Creates a confirmed product mapping between a source product and a competitor product.",
        "description": "Administrative or manual mapping workflows use this endpoint when the client already knows the source and target product identifiers and wants to persist a mapping relationship directly.\n\nSend an `UpdateProductMappingRequest` body containing source vendor/product details, target vendor/product details or URL, matching type, and customer context. The created mapping is returned with a 201 response and a location pointing to `GetMapping`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.UpdateProductMappingRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.UpdateProductMappingRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.UpdateProductMappingRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Entities.ProductMapping"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Entities.ProductMapping"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Entities.ProductMapping"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Updates a mapping's match classification or selected state.",
        "description": "Product Mapping screens call this endpoint when a user corrects the matching type or selects the best competitor match for a source product. At least one of `MatchingType` or `IsSelected` must be supplied.\n\nWhen `IsSelected=true`, the service automatically unselects competing mappings for the same source product and competitor so only one selected mapping remains. The response returns the updated enriched mapping for immediate UI refresh.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.UpdateMappingRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.UpdateMappingRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.UpdateMappingRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/{id}": {
      "get": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Returns one enriched product mapping by identifier.",
        "description": "Mapping detail and review tools call this endpoint when they need the current enriched state for a single suggested mapping after a selection, validation, or correction flow.\n\nCall with `GET /api/product-mapping/{id}`. The mapping is resolved within the caller's active workspace; a missing active workspace returns an authorization error, and a missing mapping returns 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Deletes a confirmed product mapping by identifier.",
        "description": "Maintenance workflows use this endpoint to remove an explicit mapping record when it should no longer participate in matching or analysis.\n\nCall with `DELETE /api/product-mapping/{id}`. The endpoint is destructive and returns 204 when the mapping is removed, or 404 when the identifier does not exist.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/suggested/{id}": {
      "delete": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Deletes a suggested mapping and excludes any related confirmed mapping from tracking.",
        "description": "Mapping review and fine-tuning screens use this endpoint when a user removes a suggested competitor match from the review set. If the suggestion had been tracked, the corresponding confirmed mapping is marked as user excluded instead of silently remaining active.\n\nThe operation is scoped to the active workspace. It returns 204 after cleanup, 403 without an active workspace, and 404 when the suggested mapping cannot be found.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/scan-url": {
      "post": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Starts an asynchronous URL scan to create a mapping from a competitor product URL.",
        "description": "Add Mapping dialogs call this endpoint when a user pastes a competitor URL instead of selecting a catalog search result. The API creates a scan job, queues the URL for extraction, and returns immediately with a job ID.\n\nThe request contains a tracked source product ID, competitor vendor ID, URL, and optional matching type. Poll the returned `pollUrl` or `/api/product-mapping/scan-url/job/{jobId}/poll` until the job completes. Mapping creation is eventually consistent because extraction runs outside the request.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanUrlForMappingRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanUrlForMappingRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanUrlForMappingRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted",
            "content": {
              "text/plain": {
                "schema": { }
              },
              "application/json": {
                "schema": { }
              },
              "text/json": {
                "schema": { }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/scan-url/job/{jobId}/poll": {
      "get": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Long-polls a URL scan job until completion or timeout.",
        "description": "The frontend mapping scan polling hook calls this endpoint after `scan-url` to reduce client-side polling noise. The server waits for the job to finish or until `timeoutSeconds` elapses, then returns the latest status.\n\n`timeoutSeconds` defaults to 60 and is capped at 120. A successful job can include the scanned product and created mapping identifiers; failed jobs include an error message. Use this endpoint for active waiting, and use the immediate status endpoint for lightweight refreshes.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "timeoutSeconds",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 60
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanJobStatusDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanJobStatusDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanJobStatusDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/scan-url/job/{jobId}": {
      "get": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Returns the current URL scan job status without waiting.",
        "description": "Mapping dialogs and diagnostics can call this endpoint when they need a quick status refresh for a URL scan job without holding the HTTP request open.\n\nUse `GET /api/product-mapping/scan-url/job/{jobId}` with a job ID returned by `scan-url`. The response reflects the last persisted status, so recently queued or completed work can appear after a short delay.",
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanJobStatusDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanJobStatusDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.ScanJobStatusDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/add-tracking": {
      "post": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Adds an extra competitor product to the tracked mapping set for a source product.",
        "description": "Product search and exploration dialogs call this endpoint when a user chooses an additional competitor result to monitor alongside existing matches. The new suggested mapping is flagged as additional tracking and counts toward the workspace SKU quota.\n\nThe request must include `SourceProductId`, `TargetProductId`, and `CompetitorVendorId`. Duplicate mappings return 409, and exhausted workspace quota returns 429.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.AddTrackingRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.AddTrackingRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.AddTrackingRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/set-primary": {
      "put": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Marks one competitor mapping as the primary match for statistics.",
        "description": "Product search and mapping screens call this endpoint when a user chooses which competitor product should drive comparison statistics for a source product and competitor vendor.\n\nThe request must include `SourceProductId`, `TargetProductId`, and `CompetitorVendorId`. Setting one mapping primary automatically unsets any previous primary for the same source product and competitor vendor.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.SetPrimaryRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.SetPrimaryRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductMappings.SetPrimaryRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "text/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-mapping/suggested/{id}/validate": {
      "put": {
        "tags": [
          "ProductMapping"
        ],
        "summary": "Marks a suggested mapping as human validated or unvalidated.",
        "description": "Product Mapping, QA review, and fine-tuning annotation screens call this endpoint to record whether a human has accepted a suggested source-to-target mapping label.\n\nThe request body supplies `validated` and may include `companyId` for admin review contexts. The response includes mapping validation state and product-level human validation state so clients can update row badges without reloading the full mapping list.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.ValidateHumanMappingRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.ValidateHumanMappingRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.ValidateHumanMappingRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/product-search": {
      "get": {
        "tags": [
          "ProductSearch"
        ],
        "summary": "Searches configured competitor catalogs for products matching a user query.",
        "description": "Add Competitor and Product Search dialogs call this endpoint while a user searches for competitor products to map or track. Results are limited to vendors configured as competitors for the active workspace.\n\n`query` is required and matches product names. `vendorId` narrows results to one competitor. `sourceProductId` lets the response flag products that are already mapped to the selected source product. Pagination is one-based; `pageSize` must be between 1 and 50.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "vendorId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          },
          {
            "name": "sourceProductId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductSearch.ProductSearchResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductSearch.ProductSearchResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductSearch.ProductSearchResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/scan-configuration": {
      "get": {
        "tags": [
          "ScanConfiguration"
        ],
        "summary": "Get the active workspace's global scan configuration.",
        "description": "Returns a `ScanConfigurationSuccessResponseDto` envelope containing the workspace's\ncurrent global scan settings: whether scanning is active, last and next scan times,\nschedule frequency, start date, timezone, optional custom schedule, and optional\n`activeScanProgress`.\n\nThe Nesika web app calls `GET /api/scan-configuration` from the dashboard status\nprovider and Settings - Scan Profiles area to show scan scheduling state. While a scan is\npending or in progress, `activeScanProgress` contains the scan ID, status, total\njobs, completed jobs, successful jobs, errored jobs, completion percentage, and start\ntime. The frontend polls this route more frequently while `activeScanProgress` is\npresent and less frequently when the workspace is idle.\n\nUse this endpoint before updating scan settings so clients can preserve server-calculated\nfields and display the next scheduled run. A missing workspace configuration returns\n`404`.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationSuccessResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationSuccessResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationSuccessResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "ScanConfiguration"
        ],
        "summary": "Update the active workspace's global scan configuration.",
        "description": "Updates the global schedule used for regular scans in the active workspace and returns\nthe updated configuration in a `ScanConfigurationSuccessResponseDto` envelope. The\nSettings - Scan Profiles UI uses this route for legacy/default schedule controls and for\nfields shared by the workspace's default profile.\n\nCall `PUT /api/scan-configuration` with a JSON body containing any supported fields:\n`isActive`, `scanScheduleFrequency`, `startDateUtc`, `timeZone`,\n`customSchedule`, and, for system administrators only, `nextScanDateUtc`.\nWorkspace administrators can update normal schedule fields, but attempts by non-system\nadministrators to set `nextScanDateUtc` return `403`.\n\nWhen `scanScheduleFrequency` is `Custom`, provide `customSchedule` with\nactive weekdays and one or more `HH:mm` scan times in the configured timezone.\nInvalid schedule values return `400`. The service recalculates schedule-derived\nfields where appropriate; callers should use the returned payload as the source of truth.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationUpdateRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationUpdateRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationUpdateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationSuccessResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationSuccessResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationSuccessResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/scan-profiles": {
      "get": {
        "tags": [
          "ScanProfiles"
        ],
        "summary": "List scan profiles for the active workspace.",
        "description": "Returns all scan profiles configured for the caller's active workspace. Each\n`ScanProfileDto` includes schedule settings, default-profile state, next and last\nscan timestamps, custom schedule data, and `linkedProductCount`.\n\nThe Settings - Scan Profiles screen calls `GET /api/scan-profiles` when it loads\nand after profile changes. The response drives the profile cards, product counts, active\ntoggles, schedule display, and the default profile fallback. If a workspace has no stored\ndefault profile, the service can synthesize `sp-default` from the global\n`scanConfiguration`.\n\nProfile schedules determine when assigned products are scanned. Product assignment is\nhandled by product endpoints; this route only returns profile metadata and counts.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "ScanProfiles"
        ],
        "summary": "Create a new scan profile.",
        "description": "Creates a non-default scan profile for the active workspace and returns the created\n`ScanProfileDto`. The Settings - Scan Profiles screen uses this endpoint when a\nworkspace administrator adds a schedule group such as high-priority products, seasonal\nproducts, or weekly products.\n\nCall `POST /api/scan-profiles` with `name`, `frequency`,\n`timezone`, optional `startDateUtc`, optional `isActive`, and optional\n`customSchedule`. Valid frequencies are `Hourly`, `Daily`,\n`Weekly`, `Monthly`, and `Custom`. When frequency is `Custom`, the\nrequest must include `customSchedule` with valid active days and scan times.\n\nThe service enforces unique profile names and a maximum of 10 non-default profiles per\nworkspace. New profiles start with no linked products; products are moved to a profile\nthrough product assignment workflows.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.CreateScanProfileDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.CreateScanProfileDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.CreateScanProfileDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/scan-profiles/{id}": {
      "get": {
        "tags": [
          "ScanProfiles"
        ],
        "summary": "Get one scan profile by ID.",
        "description": "Returns a single `ScanProfileDto` for the caller's active workspace. Use\n`GET /api/scan-profiles/{id}` when a client needs to refresh one expanded profile\nafter editing schedule fields or assigning products.\n\nThe route is workspace-scoped through the authenticated user. Unknown profile IDs return\n`404`. The default profile uses the canonical ID `sp-default` when synthesized\nfrom the workspace's global scan configuration.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "ScanProfiles"
        ],
        "summary": "Update an existing scan profile.",
        "description": "Updates schedule metadata for a scan profile in the active workspace and returns the\nupdated `ScanProfileDto`. The Settings - Scan Profiles screen calls this route when\nusers rename a profile, enable or disable it, change the frequency, adjust timezone, set\na start date, or configure a custom schedule.\n\nCall `PUT /api/scan-profiles/{id}` with only the fields to change. The server\nvalidates frequency, custom schedule rules, and profile name uniqueness. Schedule changes\ncan recalculate `nextScanDateUtc`; clients should use the returned value rather than\ncalculating it locally.\n\nUpdating `sp-default` can write through to the workspace's global\n`scanConfiguration` when the default profile is synthesized. Inactive profiles keep\ntheir product assignments but scheduled scans are paused.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.UpdateScanProfileDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.UpdateScanProfileDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.UpdateScanProfileDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "ScanProfiles"
        ],
        "summary": "Delete a non-default scan profile.",
        "description": "Deletes a custom scan profile from the active workspace. The Settings - Scan Profiles\nscreen uses `DELETE /api/scan-profiles/{id}` when a workspace administrator removes\na schedule group that is no longer needed.\n\nDeleting a profile does not delete products. Products assigned to the deleted profile are\nreassigned to the default profile where possible; if reassignment cannot be completed,\norphaned profile assignments fall back to the default profile on the next read.\n\nThe default profile cannot be deleted. Unknown IDs return `404`; successful deletes\nreturn `204 No Content`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/scans/{scanId}/stats": {
      "get": {
        "tags": [
          "Scans"
        ],
        "summary": "Get job counts and progress statistics for one scan.",
        "description": "Returns a `ScanStatisticsDto` for the supplied scan, including scan status, completion\npercentage, total jobs, completed jobs, successful jobs, errored jobs, start and finish\ntimestamps, average job duration, and a vendor breakdown.\n\nThe Nesika web app uses this endpoint when it needs detailed lifecycle telemetry for a\nscan, especially while a scan is still running. Callers can poll\n`GET /api/scans/{scanId}/stats` after creating or observing a scan and watch\n`progressPercent`, `completedJobs`, `successJobs`, and `errorJobs`.\nTerminal statuses include values such as `Completed`, `Cancelled`, and\n`Failed`; active scans return partial counts until all jobs finish.\n\nThe response is marked `Cache-Control: no-store` because it represents live scan\nstate. A missing or unknown scan returns `404`; unauthorized cross-workspace access\nreturns `403`.",
        "parameters": [
          {
            "name": "scanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Scans.ScanStatisticsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Scans.ScanStatisticsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Scans.ScanStatisticsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/companies/{workspaceId}/scan-history": {
      "get": {
        "tags": [
          "Scans"
        ],
        "summary": "Get recent scan-history points for one workspace.",
        "description": "Returns a time series of `ScanHistoryPointDto` records for the requested workspace.\nThe data is intended for overview and reporting screens that show scan volume, duration,\nprogress, and success or error trends over a recent time window.\n\nThe route is absolute: call `GET /api/companies/{workspaceId}/scan-history` with an\noptional `days` query parameter. `days` defaults to `14` and must be between\n`1` and `365`. The authenticated user's active workspace must match\n`workspaceId`; otherwise the endpoint returns `403`.\n\nThe response uses `Cache-Control: no-store` so charts do not reuse stale scan\nhistory immediately after a scheduled or manual scan completes.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "maximum": 365,
              "minimum": 1,
              "type": "integer",
              "format": "int32",
              "default": 14
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Scans.ScanHistoryPointDto"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Scans.ScanHistoryPointDto"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Scans.ScanHistoryPointDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/scans/{scanId}/discovery-status": {
      "get": {
        "tags": [
          "Scans"
        ],
        "summary": "Get crawl-discovery status for one scan.",
        "description": "Returns `DiscoveryStatusDTO` for the authenticated user's company, combining the\nscan status with OpenCrawl discovery fields such as `discoveryStatus`,\n`discoveryJobId`, request/start/completion timestamps, deadline, product count,\nlast error, and result blob URI.\n\nThe web app polls `GET /api/scans/{scanId}/discovery-status` during product\ndiscovery workflows to decide whether discovery is still pending, running, completed, or\nfailed before showing discovered product counts or errors. The caller only supplies the\n`scanId`; workspace scoping comes from the authenticated user's company context.\n\nThe endpoint returns `401` when no company can be resolved for the user and\n`404` when the scan is not found for that company.",
        "parameters": [
          {
            "name": "scanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DiscoveryStatusDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DiscoveryStatusDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DiscoveryStatusDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns a paged, filterable catalog of tracked products for the active workspace.",
        "description": "Product Catalog, Product Details fallback lookups, Product Mapping, fine-tuning, alerts, and settings screens call this endpoint to load the user's tracked product set.\n\nSearch with `query`, page with one-based `page` and `pageSize`, and filter by tracked state, owner, tags, human validation, department, category, brand, scan profile, scan status, scan issue type, or validation status. Custom field filters use query keys prefixed with `cf_`, for example `cf_region=North,South`. Multiple custom fields are AND-ed, while comma-separated values within a field use OR logic.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 500
            }
          },
          {
            "name": "tracked",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": null
            }
          },
          {
            "name": "owner",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "humanValidation",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "department",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "brand",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "scanProfileId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "scanStatus",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "lastScanStatus",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "scanIssueType",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "validationStatus",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductsListDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Creates a tracked product and queues it for validation when possible.",
        "description": "The Add Product screen calls this endpoint for manual product entry or URL-based product tracking. A request must provide either product name and SKU, or a product URL. Supplying both is accepted.\n\nBefore creation, the endpoint enforces the workspace SKU limit. After creation it attempts to send a validation queue message; if queueing fails, the product still remains created and can be revalidated later. Duplicate SKU or duplicate URL requests return 400.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.CreateTrackedProductDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.CreateTrackedProductDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.CreateTrackedProductDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfTrackedProductDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfTrackedProductDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfTrackedProductDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/status-summary": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns aggregate product validation and URL scan status counts.",
        "description": "Product catalog status badges and dashboard summary widgets call this endpoint to display how many products are pending, in progress, successful, or failed without loading the full catalog.\n\nThe result is scoped to the current user's workspace and contains a total plus counts by status. It is read-only and suitable for lightweight refresh polling after product imports or revalidation actions.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductStatusSummaryDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/autocomplete": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns tracked product suggestions for search autocompletion.",
        "description": "Product search inputs call this endpoint as the user types to show matching product name and SKU suggestions without loading a full product page.\n\n`pageSize` controls the maximum number of suggestions and must be positive. Optional `owner` and comma-separated `tags` filters keep suggestions aligned with the active product list.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 5
            }
          },
          {
            "name": "owner",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductsAutocompleteDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/{id}": {
      "put": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Updates editable metadata for a tracked product.",
        "description": "Product edit drawers, inline catalog edits, image edits, and product detail forms call this endpoint to update fields such as name, SKU, brand, category, owner, tags, tracking state, images, custom fields, and related metadata.\n\nThe route `id` must match the body `Id` to prevent accidental updates to the wrong document. Custom field keys are validated against the workspace configuration. Successful updates should invalidate product catalog and product details caches in clients.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.EditTrackedProductDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.EditTrackedProductDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.EditTrackedProductDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns one tracked product by document identifier.",
        "description": "Detail pages and edit workflows use this endpoint when they need the freshest server copy of a single tracked product rather than reusing list data.\n\nThe lookup is scoped to the active workspace. A product from another workspace returns 403, and a missing product returns 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Deletes a tracked product from the active workspace catalog.",
        "description": "Product catalog delete actions and bulk-edit flows call this endpoint when a user removes a single product from tracking.\n\nThe operation is destructive for the tracked product record and is scoped to the active workspace. Clients should clear product catalog, mapping, and detail caches after a successful 204 response.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content",
            "content": {
              "application/json": { }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/{id}/acquisition-method": {
      "patch": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Promotes or demotes a tracked product between static import and live scrape acquisition modes.",
        "description": "Static import management flows call this endpoint when a user promotes a static product to live scraping, or demotes a live-scrape or CSV-feed product to static import with a fixed base price.\n\nThis endpoint is hidden with a 404 when the static import feature flag is disabled. Supported transitions are `static_import` to `live_scrape`, and non-static products to `static_import`. Unsupported acquisition methods or transitions return 400.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.UpdateTrackedProductAcquisitionMethodDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.UpdateTrackedProductAcquisitionMethodDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.UpdateTrackedProductAcquisitionMethodDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/static-import": {
      "post": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Imports one or more static products that do not require live scraping.",
        "description": "Static import workflows call this endpoint for products whose base price is supplied by the customer instead of extracted from a URL. Each item is created or re-imported with `acquisitionMethod=static_import`, and an optional base price becomes the active price anchor.\n\nThe endpoint is hidden with a 404 when the static import feature flag is disabled. It enforces SKU limits before import and returns aggregate created, updated, conflict, and failed counts with per-item outcomes. The company primary vendor configuration is not changed.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StaticImport.StaticImportRequestDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StaticImport.StaticImportRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StaticImport.StaticImportRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfStaticImportResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfStaticImportResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/bulk-upload": {
      "post": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Bulk creates tracked products from a simple CSV upload.",
        "description": "Legacy CSV upload flows call this endpoint to import products from a file using the server's default CSV parser. Newer import wizards should prefer the analyze, preflight, and confirmed-upload endpoints for explicit column mappings.\n\nThe request is multipart form data with a `file` and optional `scanFrequency`. The endpoint validates file presence, size, and extension before importing. It returns success and error counts rather than failing the whole upload for row-level errors.",
        "parameters": [
          {
            "name": "scanFrequency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "WEEKLY"
            }
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvProductUploadResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/export": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Exports tracked products as PDF, Excel, or CSV with optional filters.",
        "description": "Product catalog export actions call this endpoint when a user downloads the visible product set or the full catalog.\n\n`format` must be `pdf`, `excel`, or `csv`. When filters are supplied, the export uses the same tracked, owner, tags, department, category, query, and human-validation filters as the catalog. The response includes an `X-Export-Filters-Applied` header so clients can distinguish filtered from full exports.",
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "pdf"
            }
          },
          {
            "name": "tracked",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": null
            }
          },
          {
            "name": "owner",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "department",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "humanValidation",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/usage": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns current tracked-product usage against the workspace SKU limit.",
        "description": "Add Product and catalog screens call this endpoint to show capacity and prevent users from adding products beyond their plan.\n\nThe response contains current SKU usage and plan limits for the active workspace. Use it before create, static import, or bulk import flows where capacity affects whether the user can proceed.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Usage.SkuUsageDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/{id}/revalidate": {
      "patch": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Queues a tracked product for validation again.",
        "description": "Product Details retry buttons, failed-product tables, and catalog actions call this endpoint when extraction or validation failed and the user wants to retry.\n\nThe service resets validation status to pending and sends a validation request to the queue. Queue processing is asynchronous, so clients should refresh or poll product status after the request succeeds. Already validated products return 400.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/analyze-csv-upload": {
      "post": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Analyzes a tracked-product CSV and suggests column mappings before import.",
        "description": "The CSV import wizard calls this endpoint after a user uploads a file so the UI can display detected columns, sample rows, and suggested mappings for confirmation.\n\nThe request is multipart form data containing `file`. The endpoint validates file presence, size, and extension, then returns detected columns and mapping confidence. It is read-only and does not create products.",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "$ref": "#/components/schemas/IFormFile"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductCsvAnalysisDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/bulk-upload-csv-confirmed": {
      "post": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Imports tracked products from CSV using confirmed column mappings.",
        "description": "The CSV import wizard calls this endpoint after the user confirms column mappings and import options. It creates or updates tracked products according to `importMode`, optional custom-field mappings, and `preserveExistingOnEmpty` behavior.\n\nThe `product_id` mapping is required. Duplicate products are reported in the response rather than treated as a transport failure. The primary vendor type from company configuration determines how product identity is interpreted.",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "File": {
                    "$ref": "#/components/schemas/IFormFile"
                  },
                  "ColumnMappings": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "CustomFieldMappings": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "ImportMode": {
                    "type": "string"
                  },
                  "PreserveExistingOnEmpty": {
                    "type": "boolean"
                  },
                  "AdditionalTags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductBulkUploadResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/csv-preflight": {
      "post": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Computes a read-only preflight plan for a tracked-product CSV import.",
        "description": "The redesigned product import wizard calls this endpoint before executing an import to get authoritative create, update, unchanged, skip, duplicate, and capacity counts.\n\nThe endpoint validates the file and column mappings, reads company primary vendor configuration, and returns whether the import can proceed without mutating the catalog. Supported import modes include `create_and_update`, `create_only`, and `update_only`.",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "File": {
                    "$ref": "#/components/schemas/IFormFile"
                  },
                  "ColumnMappings": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "CustomFieldMappings": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "ImportMode": {
                    "type": "string"
                  },
                  "PreserveExistingOnEmpty": {
                    "type": "boolean"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductCsvPreflightResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": { }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/bulk": {
      "patch": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Applies the same owner, tags, tracked state, scan profile, or competitor overrides to multiple products.",
        "description": "Product catalog bulk edit panels call this endpoint when a user selects multiple rows and changes shared metadata or scan behavior in one operation.\n\nThe request must contain at least one product ID and at least one enabled update field. The response reports success and failure counts so the UI can show partial outcomes when some products cannot be updated.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkUpdateProductsDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkUpdateProductsDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkUpdateProductsDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkUpdateResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Deletes multiple tracked products in one request.",
        "description": "Product catalog bulk delete actions call this endpoint after a user confirms removal of selected products.\n\nThe request must contain at least one product ID. The response reports success and failure counts so clients can show partial deletion results and refresh the catalog after completion.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkDeleteProductsDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkDeleteProductsDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkDeleteProductsDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.BulkDeleteResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/owners": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns distinct owner values for tracked-product filters and autocomplete.",
        "description": "Owner filter components call this endpoint to populate autocomplete options without loading the full catalog.\n\nPass `tracked` with the same value used by the catalog list so the dropdown matches the visible tracked-only, untracked-only, or all-products scope.",
        "parameters": [
          {
            "name": "tracked",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/tags": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns distinct tag values for tracked-product filters and autocomplete.",
        "description": "Tag filter components call this endpoint to populate tag suggestions without loading the full catalog.\n\nPass `tracked` with the same value used by the catalog list so the dropdown matches the visible tracked-only, untracked-only, or all-products scope.",
        "parameters": [
          {
            "name": "tracked",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/tracked-products/distinct-values": {
      "get": {
        "tags": [
          "TrackedProducts"
        ],
        "summary": "Returns distinct values for catalog filters, including custom fields.",
        "description": "Product catalog filters and edit drawers call this endpoint to populate category, brand, owner, tag, and custom-field dropdowns.\n\nWhen filters are supplied, the service uses an exclude-self cascading pattern: each field's options are computed from products matching all other active filters. Custom field filters use query keys prefixed with `cf_`. Pass `tracked` to keep options aligned with the current catalog scope.",
        "parameters": [
          {
            "name": "owner",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "tags",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "department",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "tracked",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.DistinctFieldValuesDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/invitations/my-pending": {
      "get": {
        "tags": [
          "UserInvitations"
        ],
        "summary": "Get pending invitations for the authenticated user's email.",
        "description": "Returns pending invitations addressed to the email in the authenticated token. The web app uses this during login when a user may not have a database user record yet, so it can detect invitations and guide the user into the acceptance flow.\n\nCall `GET /api/invitations/my-pending` with the normal bearer token. The endpoint reads email directly from JWT claims and can return an empty list without blocking authentication.\n\nThis endpoint is read-only and not workspace-route scoped. It returns `401` when the token does not contain a usable email.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/invitations": {
      "post": {
        "tags": [
          "UserInvitations"
        ],
        "summary": "Create a workspace invitation.",
        "description": "Creates an invitation for a user to join the specified workspace. The members and invitations settings screens use this when a workspace administrator invites a new user by email and role.\n\nCall `POST /api/workspaces/{workspaceId}/invitations` with a `CreateInvitationRequestDTO` body. The caller must pass workspace-admin validation for the route workspace.\n\nThis endpoint has side effects: it creates an invitation record and the service may send an invitation email. Duplicate existing users or invitations return `409`.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.CreateInvitationRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.CreateInvitationRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.CreateInvitationRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "get": {
        "tags": [
          "UserInvitations"
        ],
        "summary": "Get manageable invitations for a workspace.",
        "description": "Returns invitations that can be managed for the specified workspace, including pending and expired records exposed by the invitation service. The members settings screen uses this list to display outstanding invites and available actions.\n\nCall `GET /api/workspaces/{workspaceId}/invitations`. The caller must pass workspace-admin validation for the route workspace.\n\nThis endpoint is read-only. Use the cancel and resend endpoints to change invitation state.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/invitations/validate/{token}": {
      "get": {
        "tags": [
          "UserInvitations"
        ],
        "summary": "Validate an invitation token.",
        "description": "Validates an invitation token before the user signs in or accepts it. The public invitation acceptance page uses this to show the target workspace and whether the token is still usable.\n\nCall `GET /api/invitations/validate/{token}`. This endpoint allows anonymous access because it runs before the user is necessarily authenticated.\n\nThe endpoint returns `200` with validation details even when `IsValid` is false, which lets the web app show a friendly invalid or expired invitation state.",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.ValidateInvitationResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.ValidateInvitationResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.ValidateInvitationResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/accept/{token}": {
      "post": {
        "tags": [
          "UserInvitations"
        ],
        "summary": "Accept an invitation and join the workspace.",
        "description": "Accepts an invitation for the authenticated user. The invitation completion screen calls this after the user signs in so the backend can create or link the user to the invited workspace.\n\nCall `POST /api/invitations/accept/{token}` with the normal bearer token. For social sign-ins where the access token contains a synthetic directory identifier, the web app may include an `idToken` in `AcceptInvitationRequestDTO` so the backend can verify the real invited email.\n\nThis endpoint has side effects: it accepts the invitation and creates membership/user state as needed. Email mismatches, invalid tokens, existing users, or expired invitations return the documented error responses.",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.AcceptInvitationRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.AcceptInvitationRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.AcceptInvitationRequestDTO"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/invitations/{token}": {
      "delete": {
        "tags": [
          "UserInvitations"
        ],
        "summary": "Cancel a workspace invitation.",
        "description": "Cancels an invitation for the specified workspace. The members and invitations settings screens use this when an administrator revokes an outstanding invitation.\n\nCall `DELETE /api/workspaces/{workspaceId}/invitations/{token}`. The caller must pass workspace-admin validation for the route workspace, and the token must belong to that workspace.\n\nThis endpoint has a side effect: it changes invitation state so the token can no longer be used. Missing or non-cancellable invitations return `404`.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/invitations/{token}/resend": {
      "post": {
        "tags": [
          "UserInvitations"
        ],
        "summary": "Resend a workspace invitation email.",
        "description": "Resends the invitation email for an existing invitation. The members and invitations settings screens use this when an administrator wants to remind an invited user.\n\nCall `POST /api/workspaces/{workspaceId}/invitations/{token}/resend`. The caller must pass workspace-admin validation for the route workspace, and the invitation must belong to that workspace.\n\nThis endpoint has a side effect outside the database: it asks the invitation service to send another email. It returns `404` when the invitation is missing, expired, already used, or not in the workspace.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-roles/me": {
      "get": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Get the authenticated user's user-role details.",
        "description": "Returns the current user's role, permissions, and active workspace identifier. The Nesika web app combines this with auth data during app bootstrap to determine navigation, feature access, and whether workspace-scoped screens can load.\n\nCall `GET /api/user-roles/me` with the normal bearer token. The endpoint reads the user from the token/current-user service and returns `401` when the token cannot be mapped to a user.\n\nThis endpoint is read-only. It reports the active workspace but does not switch it.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.CurrentUserResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.CurrentUserResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.CurrentUserResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-roles/roles": {
      "get": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Get roles available for user management.",
        "description": "Returns the role names that an administrator can assign in the user-management UI. The web app caches this list for role selectors on members and user administration screens.\n\nCall `GET /api/user-roles/roles`. The caller must have an active workspace and pass workspace-admin validation. Results are scoped to roles the user-management service exposes for the workspace workflow.\n\nThis endpoint is read-only and does not assign roles.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "text/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-roles/users": {
      "get": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Get users in the active workspace.",
        "description": "Returns users and roles for the caller's active workspace. The user-management screen uses this list to show members, role labels, and available row actions.\n\nCall `GET /api/user-roles/users`. The caller must have an active workspace and pass workspace-admin validation. Non-system administrators are limited to their active workspace.\n\nThis endpoint is read-only. It is not the hidden system-admin cross-workspace user listing.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserDTO[]"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserDTO[]"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserDTO[]"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Add a user to the active workspace.",
        "description": "Adds a user with the requested role to the caller's active workspace. The user-management screen uses this for direct user creation or access grants when not using the invitation flow.\n\nCall `POST /api/user-roles/users` with an `AddUserRequestDTO` body. The caller must have an active workspace and pass workspace-admin validation. The endpoint also validates the workspace user limit before adding the user.\n\nThis endpoint has a side effect: it creates or links user access. Duplicate users return `409`; invalid email format returns `422`; usage or authorization failures return an error response.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AddUserRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AddUserRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AddUserRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AddUserResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AddUserResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AddUserResponseDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-roles/users/{email}": {
      "patch": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Update a user's role by email.",
        "description": "Changes a user's role in the active workspace. The user-management screen uses this when an administrator edits the role selector for an existing user.\n\nCall `PATCH /api/user-roles/users/{email}` with an `UpdateUserRoleRequestDTO` body. The caller must have an active workspace and pass workspace-admin validation. Non-system administrators can only update users in their own active workspace.\n\nThis endpoint has a side effect: it updates role membership. It protects the last-admin rule and returns `409` if the requested change would remove the final administrator.",
        "parameters": [
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UpdateUserRoleRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UpdateUserRoleRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UpdateUserRoleRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Remove a user from the active workspace by email.",
        "description": "Removes a user's access from the active workspace. The user-management screen uses this when an administrator deletes or removes a user from the workspace.\n\nCall `DELETE /api/user-roles/users/{email}`. The caller must have an active workspace and pass workspace-admin validation. Non-system administrators can only remove users from their own active workspace.\n\nThis endpoint has a side effect: it removes workspace access. It protects the last-admin rule and returns `409` when removing the user would leave the workspace without an administrator.",
        "parameters": [
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-roles/users/{email}/profile": {
      "get": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Get a user's profile and role by email.",
        "description": "Returns a user profile plus role information for administrator editing. The user-management screen uses this when opening a user's profile details from the users table.\n\nCall `GET /api/user-roles/users/{email}/profile`. System administrators can use this endpoint directly; other callers must have an active workspace and pass workspace-admin validation.\n\nThis endpoint is read-only. It returns `404` when the user cannot be found or the caller is not allowed to view that profile.",
        "parameters": [
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserProfileWithRoleDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserProfileWithRoleDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserProfileWithRoleDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Update a user's profile and role by email.",
        "description": "Updates profile fields and role information for a user from the administrator UI. The web app uses this when an administrator edits a user details form rather than only changing the role selector.\n\nCall `PUT /api/user-roles/users/{email}/profile` with an `AdminUpdateUserProfileRequestDTO` body. System administrators can use this endpoint directly; other callers must have an active workspace and pass workspace-admin validation.\n\nThis endpoint has side effects: it updates user profile fields and may update role membership. Username conflicts and last-admin violations return `409`; invalid input returns `400`.",
        "parameters": [
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AdminUpdateUserProfileRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AdminUpdateUserProfileRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AdminUpdateUserProfileRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserProfileWithRoleDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserProfileWithRoleDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserProfileWithRoleDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-roles/dismiss-first-signin": {
      "put": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Dismiss first sign-in onboarding for the current user.",
        "description": "Clears the current user's first-sign-in flag after the web app has shown or skipped onboarding guidance. The frontend calls this after onboarding dismissal so the user is not prompted again.\n\nCall `PUT /api/user-roles/dismiss-first-signin` with the normal bearer token. The endpoint uses the authenticated user from the current-user service.\n\nThis endpoint has a side effect: it updates the current user's onboarding state. It returns `400` if the flag could not be updated.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-roles/usage": {
      "get": {
        "tags": [
          "UserManagement"
        ],
        "summary": "Get current user usage and limit information.",
        "description": "Returns user-count usage and limit information for the current workspace. The web app uses this to display plan limits and prevent administrators from exceeding the number of users allowed by the workspace plan.\n\nCall `GET /api/user-roles/usage` with the normal bearer token. The usage plan service derives the workspace and usage data from the authenticated context.\n\nThis endpoint is read-only. A user without a valid company/workspace association receives a forbidden response.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Usage.UserUsageDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Usage.UserUsageDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Usage.UserUsageDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-profile/me": {
      "get": {
        "tags": [
          "UserProfile"
        ],
        "summary": "Get the current user's profile.",
        "description": "Returns personal profile fields for the authenticated user. The profile settings screen uses this to populate the user's name, username, contact details, and related account fields.\n\nCall `GET /api/user-profile/me` with the normal bearer token. The endpoint requires an authenticated email but does not require an active workspace; profile data is resolved by the user's email across duplicate workspace-specific user records.\n\nThis endpoint is read-only. It returns `404` when no matching profile can be found.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UserProfileDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UserProfileDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UserProfileDTO"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "UserProfile"
        ],
        "summary": "Update the current user's profile.",
        "description": "Updates personal profile fields for the authenticated user. The profile settings screen uses this when the user saves changes to their own account details.\n\nCall `PUT /api/user-profile/me` with an `UpdateUserProfileRequestDTO` body. The endpoint requires an authenticated email but does not require an active workspace; updates are synchronized across matching user records for the same email.\n\nThis endpoint has a side effect: it persists profile changes. Username conflicts return `409` with `USERNAME_CONFLICT`; invalid usernames return `400` with `USERNAME_INVALID`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UpdateUserProfileRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UpdateUserProfileRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UpdateUserProfileRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UserProfileDTO"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UserProfileDTO"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UserProfileDTO"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/user-profile/me/preferences": {
      "get": {
        "tags": [
          "UserProfile"
        ],
        "summary": "Get the current user's notification preferences.",
        "description": "Returns notification preferences for the authenticated user. The profile or notification settings screen uses this to show which emails and alerts the user has enabled.\n\nCall `GET /api/user-profile/me/preferences` with the normal bearer token. The endpoint requires an authenticated email but does not require an active workspace; preferences are resolved by the user's email across duplicate workspace-specific user records.\n\nThis endpoint is read-only. It returns `404` when no matching user record can be found.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO2"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO2"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO2"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "UserProfile"
        ],
        "summary": "Update the current user's notification preferences.",
        "description": "Partially updates notification preferences for the authenticated user. The notification settings screen uses this when a user toggles email or alert settings.\n\nCall `PUT /api/user-profile/me/preferences` with an `UpdateNotificationPreferencesRequestDTO` body. Null fields are treated as no change by the service, so clients can send only the preferences being changed.\n\nThis endpoint has a side effect: it persists preference changes and synchronizes them across matching user records for the same email. It does not require an active workspace.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UpdateNotificationPreferencesRequestDTO"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UpdateNotificationPreferencesRequestDTO"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.UpdateNotificationPreferencesRequestDTO"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO2"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO2"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO2"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/telemetry/web-vitals": {
      "post": {
        "tags": [
          "WebVitalsTelemetry"
        ],
        "summary": "Accepts a single Web Vitals beacon or a JSON array of beacons and forwards\neach valid metric to Application Insights. Always returns 202 Accepted on\nsuccess; returns 400 only for a malformed single payload or a batch that\nviolates the batch-level limits.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonElement"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/JsonElement"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Accepted"
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        }
      }
    },
    "/api/workspaces/current": {
      "get": {
        "tags": [
          "WorkspaceMemberships"
        ],
        "summary": "Get the current user's active workspace.",
        "description": "Returns the active workspace summary for the authenticated user. The Nesika web app uses this for workspace-aware layout, settings pages, and navigation when it needs the currently selected workspace.\n\nCall `GET /api/workspaces/current` with the normal bearer token. The response is wrapped in `ApiResponse<UserWorkspaceDto>`. A missing authenticated user returns `401`; a user without an active workspace returns `404`.\n\nThis endpoint is read-only. Use `POST /api/me/active-context` to switch the active workspace.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfUserWorkspaceDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfUserWorkspaceDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfUserWorkspaceDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces": {
      "get": {
        "tags": [
          "WorkspaceMemberships"
        ],
        "summary": "Get workspaces available to the current user.",
        "description": "Returns workspace summaries the authenticated user can access. The workspace switcher and settings screens use this lightweight list to populate workspace choices and scoped navigation.\n\nCall `GET /api/workspaces`. Optional query parameters `organizationId`, `skip`, and `take` filter by organization and support offset pagination. Results are scoped to the current user and do not expose workspaces the user cannot access.\n\nThis endpoint is read-only and does not change the active workspace.",
        "parameters": [
          {
            "name": "organizationId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "skip",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": null
            }
          },
          {
            "name": "take",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfUserWorkspaceDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfUserWorkspaceDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfUserWorkspaceDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/members": {
      "get": {
        "tags": [
          "WorkspaceMemberships"
        ],
        "summary": "Get members of a workspace.",
        "description": "Returns users who are members of the specified workspace. The workspace members settings screen uses this to show who can access the workspace and what role each person has.\n\nCall `GET /api/workspaces/{workspaceId}/members`. The current user must have access to the workspace according to the membership service. Results are scoped to the route workspace.\n\nThis endpoint is read-only. Use the corresponding `POST`, `PATCH`, or `DELETE` member endpoints for changes.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfMemberDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfMemberDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfMemberDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "WorkspaceMemberships"
        ],
        "summary": "Add a member to a workspace.",
        "description": "Adds an existing or specified user as a workspace member. The workspace members settings screen uses this when an administrator grants someone access to the selected workspace.\n\nCall `POST /api/workspaces/{workspaceId}/members` with an `AddMemberDto` body. The current user must have permission to administer members in the workspace.\n\nThis endpoint has a side effect: it creates membership access for the target user. Business-rule failures, such as invalid role or duplicate membership, return `400`; insufficient permissions return `403`.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.AddMemberDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.AddMemberDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.AddMemberDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfMemberDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfMemberDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfMemberDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/members/{targetUserId}": {
      "patch": {
        "tags": [
          "WorkspaceMemberships"
        ],
        "summary": "Update a workspace member's role.",
        "description": "Changes the role for an existing workspace member. The workspace members settings screen uses this when an administrator promotes or demotes a member inside a workspace.\n\nCall `PATCH /api/workspaces/{workspaceId}/members/{targetUserId}` with an `UpdateMemberDto` body. The caller must have member-administration access for the workspace.\n\nThis endpoint has a side effect: it updates the member role. Service validation protects workspace boundaries and business rules such as invalid roles.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "targetUserId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UpdateMemberDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UpdateMemberDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UpdateMemberDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfMemberDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfMemberDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfMemberDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "WorkspaceMemberships"
        ],
        "summary": "Remove a member from a workspace.",
        "description": "Removes a user's membership from the specified workspace. The workspace members settings screen uses this when an administrator revokes access.\n\nCall `DELETE /api/workspaces/{workspaceId}/members/{targetUserId}`. The caller must have member-administration access for the workspace.\n\nThis endpoint has a side effect: it removes workspace access for the target user. If the membership is not found, it returns `404`.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "targetUserId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfString"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/workspaces/{workspaceId}/settings": {
      "patch": {
        "tags": [
          "WorkspaceMemberships"
        ],
        "summary": "Update workspace locale and regional settings.",
        "description": "Updates workspace-level settings such as currency, timezone, and regional values used by the web app when displaying prices, dates, and workspace metadata.\n\nCall `PATCH /api/workspaces/{workspaceId}/settings` with an `UpdateWorkspaceSettingsDto` body. The caller must have permission to administer the workspace.\n\nThis endpoint has a side effect: it persists workspace settings for future requests in that workspace. Validation failures return `400`; unauthorized workspace access returns `403`.",
        "parameters": [
          {
            "name": "workspaceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UpdateWorkspaceSettingsDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UpdateWorkspaceSettingsDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UpdateWorkspaceSettingsDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.Common.ApiResponseOfWorkspaceSummaryDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{productId}/cheapest": {
      "get": {
        "tags": [
          "Price Monitoring"
        ],
        "summary": "Get the cheapest current option.",
        "description": "Use this endpoint when your workflow needs one actionable recommendation for the\ncheapest current way to buy a product, such as repricing alerts, shopping-agent\ndecisions, or basket optimization pre-checks.\n\nPrefer `GET /api/v1/products/{productId}/prices` when you need the full current\ncompetitor price table. Prefer the history endpoints when you need to explain how prices\nchanged over time. This endpoint returns the best option now, not a trend or time series.\n\n`include_shipping` can change the winning option when delivery estimates are\navailable. `include_coupons` asks the API to include eligible coupon adjustments\nwhere supported by the source data.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include_shipping",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": true
            }
          },
          {
            "name": "include_coupons",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                },
                "examples": {
                  "success": {
                    "summary": "Cheapest purchase option",
                    "value": {
                      "data": {
                        "productId": "prod_ABC123",
                        "productName": "UltraClean Laundry Liquid 2L",
                        "cheapestVendor": "Big W",
                        "cheapestPrice": 11.95,
                        "currency": "AUD",
                        "allOptions": [
                          {
                            "vendorName": "Big W",
                            "vendorId": "bigw",
                            "price": 11.95,
                            "currency": "AUD",
                            "url": "https://example.com/bigw/prod-abc123",
                            "lastUpdated": "2026-07-14T00:00:00Z"
                          },
                          {
                            "vendorName": "Chemist Warehouse",
                            "vendorId": "chemistwarehouse",
                            "price": 12.5,
                            "currency": "AUD",
                            "url": "https://example.com/chemistwarehouse/prod-abc123",
                            "lastUpdated": "2026-07-14T00:10:00Z"
                          }
                        ]
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/competitors": {
      "get": {
        "tags": [
          "Competitor Intelligence"
        ],
        "summary": "List competitor vendors.",
        "description": "Use this endpoint to discover which competitor vendors are available for public\nmonitoring before you request product prices or apply a vendor filter. It is useful for\nsetup screens, agent planning, and validating whether a category has enough competitor\ncoverage for analysis.\n\nThis is a catalog and coverage endpoint, not a price endpoint. Use product search to\nfind product identifiers, then use price monitoring endpoints for current prices or\ntrends.\n\nPagination uses `page` and `pageSize`; `pageSize` is capped at 100.\n`category` narrows the vendor list to competitors relevant for that category.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                },
                "examples": {
                  "success": {
                    "summary": "Tracked competitors",
                    "value": {
                      "data": {
                        "competitors": [
                          {
                            "vendorId": "bigw",
                            "vendorName": "Big W",
                            "productCount": 1280,
                            "averagePrice": 16.45,
                            "pricingTrend": "stable"
                          },
                          {
                            "vendorId": "chemistwarehouse",
                            "vendorName": "Chemist Warehouse",
                            "productCount": 940,
                            "averagePrice": 13.2,
                            "pricingTrend": "down"
                          }
                        ],
                        "message": "2 competitors returned."
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/analysis/cost": {
      "post": {
        "tags": [
          "Pricing Actions"
        ],
        "summary": "Analyze basket cost.",
        "description": "Use this endpoint when a workflow needs to evaluate a basket of public product\nidentifiers as a pricing action: total cost, vendor comparison, or basket optimization.\nIt is designed for checkout planning, savings estimates, and AI agents deciding which\nproducts or vendors to recommend.\n\nThis endpoint accepts up to 20 product identifiers per request. Use\n`GET /api/v1/products/search` first if you need to discover product identifiers from\nproduct names. Use `GET /api/v1/products/{productId}/cheapest` for a single-product\nrecommendation instead of basket-level analysis.\n\nCurrency and shipping behavior follow the currently available product observations.\nRecent scan data can be eventually consistent, so a just-completed scan may take a short\ntime to appear in calculations.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CostAnalysisRequestDto"
              },
              "examples": {
                "request": {
                  "summary": "Analyze a basket",
                  "value": {
                    "product_ids": [
                      "prod_ABC123",
                      "prod_DEF456"
                    ],
                    "analysis_type": "total_cost",
                    "include_shipping": true,
                    "optimize_for": "lowest_total"
                  }
                }
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CostAnalysisRequestDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CostAnalysisRequestDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                },
                "examples": {
                  "success": {
                    "summary": "Basket cost analysis",
                    "value": {
                      "data": {
                        "analysisType": "total_cost",
                        "optimizeFor": "lowest_total",
                        "includeShipping": true,
                        "currency": "AUD",
                        "foundProductCount": 2,
                        "missingProductIds": [ ],
                        "recommendedOptions": [
                          {
                            "productId": "prod_ABC123",
                            "productName": "UltraClean Laundry Liquid 2L",
                            "vendorId": "bigw",
                            "vendorName": "Big W",
                            "unitPrice": 11.95,
                            "shippingEstimate": 0,
                            "totalPrice": 11.95,
                            "url": "https://example.com/bigw/prod-abc123"
                          },
                          {
                            "productId": "prod_DEF456",
                            "productName": "FreshBrite Dishwasher Tablets 40 pack",
                            "vendorId": "bigw",
                            "vendorName": "Big W",
                            "unitPrice": 17.5,
                            "shippingEstimate": 0,
                            "totalPrice": 17.5,
                            "url": "https://example.com/bigw/prod-def456"
                          }
                        ],
                        "vendorComparison": [
                          {
                            "vendorId": "bigw",
                            "vendorName": "Big W",
                            "productCount": 2,
                            "subtotal": 29.45,
                            "shippingEstimate": 0,
                            "total": 29.45
                          }
                        ],
                        "subtotal": 29.45,
                        "shippingEstimate": 0,
                        "totalCost": 29.45,
                        "summary": "Lowest total found at Big W for the requested basket."
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/products": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "List my tracked products.",
        "description": "Use this endpoint when an integration or AI agent needs the authenticated caller's own\ntracked product list before requesting account-scoped positions, reports, or price\nchanges. Data is scoped to the caller's active workspace and is not the public market\ncatalog.\n\nPrefer `GET /api/v1/products/search` for public product discovery across the broader\ncatalog. Use this `/me` endpoint only when you need products already configured in\nthe caller's account.\n\nPagination uses `page` and `pageSize`; `pageSize` is capped at 100.\n`status` accepts `tracked`, `paused`, or `all`.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "tracked"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                },
                "examples": {
                  "success": {
                    "summary": "Account tracked products",
                    "value": {
                      "data": [
                        {
                          "productId": "prod_ABC123",
                          "name": "UltraClean Laundry Liquid 2L",
                          "sku": "UC-LL-2L",
                          "brand": "UltraClean",
                          "category": "Laundry",
                          "scanStatus": "completed",
                          "lastScanDate": "2026-07-14T00:00:00Z",
                          "competitorCount": 3,
                          "currentPrice": 12.5,
                          "productUrl": "https://example.com/account/products/prod-abc123"
                        }
                      ],
                      "meta": {
                        "page": 1,
                        "pageSize": 20,
                        "totalCount": 1,
                        "totalPages": 1,
                        "hasNextPage": false
                      },
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/products/position": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "Get my portfolio price position.",
        "description": "Use this endpoint when you need an account-scoped view of how the caller's whole tracked\nportfolio is positioned against competitors, such as \"are we generally above or below\nmarket?\" dashboards or agent summaries.\n\nThis endpoint is scoped to the authenticated caller's active workspace. Prefer\n`GET /api/v1/me/products/{productId}/position` for a single tracked product, or\npublic `/api/v1/products/{productId}/prices` when you need market prices that are not\ntied to the caller's account.\n\n`timeframe` accepts `7d`, `30d`, or `90d`. Recent scans can be\neventually consistent, so portfolio movement may lag immediately after a scan completes.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "timeframe",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "30d"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/products/{productId}/position": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "Get my product price position.",
        "description": "Use this endpoint when you need the authenticated caller's competitive position for one\ntracked product, for example to explain whether that product is overpriced, underpriced,\nor near market.\n\nThis endpoint only returns data for products in the caller's active workspace. Prefer\n`GET /api/v1/products/{productId}/prices` for a public current-price snapshot across\ncompetitors, or `GET /api/v1/me/products/position` for portfolio-level account\npositioning.\n\nRecent scans can be eventually consistent, so newly scanned observations may take a short\ntime to affect the returned position.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/scans": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "List my scans.",
        "description": "Use this endpoint when an integration needs the authenticated caller's recent scan runs,\nfor example to find the latest completed scan before requesting a report or to monitor\naccount-specific scan status.\n\nThis endpoint is scoped to the caller's active workspace and returns account scan\nrecords, not public market data. Use `GET /api/v1/me/scans/{scanId}/report` after\nselecting a scan when you need export-ready scan details.\n\nPagination uses `page` and `pageSize`; `pageSize` is capped at 50.\nRecent scan status can be eventually consistent while processing completes.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/scans/{scanId}/report": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "Get my scan report.",
        "description": "Use this endpoint when you need an export-ready report for one of the authenticated\ncaller's scans, such as feeding a business intelligence job, attaching a report to an\nagent response, or downloading the latest scan as CSV.\n\nThis endpoint is scoped to the caller's active workspace. The special `scanId`\nvalue `latest` resolves to that workspace's most recent scan. Use\n`GET /api/v1/me/scans` first when you need to list available scans or check status.\n\nThe default response wraps the generated CSV in JSON for API and MCP clients.\n`format=csv` returns the raw CSV file for direct download. The CSV is generated on\ndemand and recent scan results can be eventually consistent.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "scanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResult"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/price-changes": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "List my price changes.",
        "description": "Use this endpoint when you need recent account-scoped price movement for the\nauthenticated caller's tracked products, such as alert feeds, daily summaries, or agent\nexplanations of what changed since the last review.\n\nThis endpoint is scoped to the caller's active workspace. Prefer public product history\nendpoints when you need market-level movement for a product regardless of whether the\ncaller tracks it.\n\n`days` is capped at 90, `limit` is capped at 200, and\n`min_change_percent` filters out small movements. Recent scans can be eventually\nconsistent, so newly observed price changes may not appear immediately.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 7
            }
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          },
          {
            "name": "min_change_percent",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/insights/summary": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "List my insight summaries.",
        "description": "Use this endpoint when you need account-scoped insight cards for the authenticated\ncaller's active workspace, such as opportunity feeds, risk triage, or an AI agent's\nprioritized action list.\n\nThis endpoint returns the caller's own persisted insights. Prefer\n`GET /api/v1/insights/market` for public category-level market intelligence that is\nnot tied to the caller's account.\n\nPagination uses `page` and `pageSize`; `pageSize` is capped at 100.\nOptional filters narrow by severity, type, or status. Recent insight generation can be\neventually consistent after a scan.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "severity",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/me/competitors/overview": {
      "get": {
        "tags": [
          "Account & Usage Data"
        ],
        "summary": "Get my competitor overview.",
        "description": "Use this endpoint when you need an account-scoped competitor overview for the\nauthenticated caller's tracked products, such as which competitors most often create\npricing pressure or where an account should focus attention.\n\nThis endpoint is scoped to the caller's active workspace and is based on that account's\npersisted insights. Prefer `GET /api/v1/competitors` for the public competitor\ncatalog, or `GET /api/v1/products/{productId}/prices` for current competitor prices\nfor a single public product.\n\n`competitorUrls` accepts a comma-separated filter list. `limit` is capped at\n100. Unknown competitor filters are reported in the response so agents can explain why a\nrequested competitor was not matched.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "competitorUrls",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/insights/market": {
      "get": {
        "tags": [
          "Market Insights"
        ],
        "summary": "Get market insights.",
        "description": "Use this endpoint when you need aggregated category-level signals for pricing strategy,\nmarket monitoring, or AI-agent context before choosing a specific product action.\n\nThis returns market-level insight for a required `category`. It is not scoped to the\ncaller's own tracked products; use `GET /api/v1/me/insights/summary` for insight\ncards tied to the authenticated account's workspace.\n\n`region` must be a two-letter ISO code and defaults to `AU`. `timeframe`\naccepts `7d`, `30d`, `90d`, or `1y`. Recent scans can be eventually\nconsistent, so newly observed market changes may not appear immediately.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "region",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "AU"
            }
          },
          {
            "name": "timeframe",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                },
                "examples": {
                  "success": {
                    "summary": "Market insight summary",
                    "value": {
                      "data": {
                        "category": "Laundry",
                        "productCount": 245,
                        "averagePrice": 13.1,
                        "medianPrice": 12.75,
                        "priceRange": {
                          "min": 4.5,
                          "max": 32
                        },
                        "priceDistribution": [
                          {
                            "rangeStart": 0,
                            "rangeEnd": 10,
                            "count": 72
                          },
                          {
                            "rangeStart": 10.01,
                            "rangeEnd": 20,
                            "count": 128
                          },
                          {
                            "rangeStart": 20.01,
                            "rangeEnd": 40,
                            "count": 45
                          }
                        ],
                        "trendDirection": "stable",
                        "trendPercentage": 1.8
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{productId}/prices": {
      "get": {
        "tags": [
          "Price Monitoring"
        ],
        "summary": "Get current competitor prices.",
        "description": "Use this endpoint when you need the current live market snapshot for one product:\nall available competitor prices, optionally narrowed to selected vendors and optionally\nincluding shipping.\n\nPrefer `GET /api/v1/products/{productId}/cheapest` when you only need the single\nlowest available option now. Prefer `GET /api/v1/products/{productId}/history`,\n`price-history-series`, or `price-trends` when your scenario needs price\nmovement over time rather than a current comparison table.\n\nVendor filtering accepts a comma-separated `vendors` list. Currency is returned as\nstored for the product and vendor observations; this endpoint does not perform currency\nconversion.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include_shipping",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "vendors",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                },
                "examples": {
                  "success": {
                    "summary": "Current competitor prices",
                    "value": {
                      "data": {
                        "productId": "prod_ABC123",
                        "productName": "UltraClean Laundry Liquid 2L",
                        "competitors": [
                          {
                            "vendorName": "Big W",
                            "vendorId": "bigw",
                            "price": 11.95,
                            "currency": "AUD",
                            "url": "https://example.com/bigw/prod-abc123",
                            "lastUpdated": "2026-07-14T00:00:00Z",
                            "priceChange24h": -4
                          },
                          {
                            "vendorName": "Chemist Warehouse",
                            "vendorId": "chemistwarehouse",
                            "price": 12.5,
                            "currency": "AUD",
                            "url": "https://example.com/chemistwarehouse/prod-abc123",
                            "lastUpdated": "2026-07-14T00:10:00Z",
                            "priceChange24h": 0
                          }
                        ]
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{productId}/history": {
      "get": {
        "tags": [
          "Price Monitoring"
        ],
        "summary": "Get current-price history snapshots.",
        "description": "Use this endpoint when you need the legacy history shape: one current-price snapshot per\nvendor, optionally filtered by vendor and date range. It is useful for compatibility with\nclients that expect a vendor-by-vendor snapshot rather than chart-ready points.\n\nPrefer `GET /api/v1/products/{productId}/price-history-series` when you need a true\ntime series for charts, backtesting, or trend calculations. Prefer\n`GET /api/v1/products/{productId}/price-trends` when you need scan-scoped trend data\naligned with product detail results. Prefer `GET /api/v1/products/{productId}/prices`\nfor the current live competitor snapshot and `cheapest` for the single lowest option.\n\nDate filters use ISO 8601 timestamps. Recent scans can be eventually consistent, so a\njust-observed price may not appear immediately.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "vendorId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                },
                "examples": {
                  "success": {
                    "summary": "Historical price points",
                    "value": {
                      "data": {
                        "productId": "prod_ABC123",
                        "productName": "UltraClean Laundry Liquid 2L",
                        "vendorId": "bigw",
                        "dataPoints": [
                          {
                            "date": "2026-07-12T00:00:00Z",
                            "price": 12.95,
                            "currency": "AUD",
                            "vendorName": "Big W"
                          },
                          {
                            "date": "2026-07-13T00:00:00Z",
                            "price": 12.5,
                            "currency": "AUD",
                            "vendorName": "Big W"
                          },
                          {
                            "date": "2026-07-14T00:00:00Z",
                            "price": 11.95,
                            "currency": "AUD",
                            "vendorName": "Big W"
                          }
                        ]
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{productId}/price-history-series": {
      "get": {
        "tags": [
          "Price Monitoring"
        ],
        "summary": "Get competitor price history series.",
        "description": "Use this endpoint when you need chart-ready competitor price history over time, such as\npricing-trend dashboards, price-rule backtests, or agent reasoning about whether a\ncompetitor is rising or discounting.\n\nThis returns a true time series bucketed by `daily`, `weekly`, or `monthly`\ngranularity and split by competitor. Prefer it over\n`GET /api/v1/products/{productId}/history`, which returns a current-price snapshot\nper vendor. Prefer `GET /api/v1/products/{productId}/price-trends` when you need\nscan-scoped trend data aligned with product detail results. Use `prices` or\n`cheapest` for current prices instead of historical movement.\n\nThe date window defaults to the recent period and is capped by the caller's tier. The\nresponse indicates when a tier cap was applied. Filter `competitorIds` with a\ncomma-separated vendor list when an agent only needs specific competitors.\n\nCurrency conversion is not yet performed; currently stored prices are returned and the\nrequested `currency` value is echoed for forward compatibility.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time",
              "default": null
            }
          },
          {
            "name": "granularity",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "daily"
            }
          },
          {
            "name": "competitorIds",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                },
                "examples": {
                  "success": {
                    "summary": "Bucketed price history series",
                    "value": {
                      "data": {
                        "productId": "prod_ABC123",
                        "productName": "UltraClean Laundry Liquid 2L",
                        "granularity": "daily",
                        "from": "2026-07-12T00:00:00Z",
                        "to": "2026-07-14T00:00:00Z",
                        "currency": "AUD",
                        "byCompetitor": {
                          "bigw": [
                            {
                              "timestamp": "2026-07-12T00:00:00Z",
                              "averagePrice": 12.95,
                              "minPrice": 12.95,
                              "maxPrice": 12.95,
                              "observationCount": 1
                            },
                            {
                              "timestamp": "2026-07-14T00:00:00Z",
                              "averagePrice": 11.95,
                              "minPrice": 11.95,
                              "maxPrice": 11.95,
                              "observationCount": 1
                            }
                          ],
                          "chemistwarehouse": [
                            {
                              "timestamp": "2026-07-14T00:00:00Z",
                              "averagePrice": 12.5,
                              "minPrice": 12.5,
                              "maxPrice": 12.5,
                              "observationCount": 1
                            }
                          ]
                        },
                        "tierCapApplied": false,
                        "effectiveTierCapDays": 365
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/products/{productId}/price-trends": {
      "get": {
        "tags": [
          "Price Monitoring"
        ],
        "summary": "Get scan-scoped price trends.",
        "description": "Use this endpoint when you need price movements derived from scan-scoped product detail\nresults, such as explaining a recent scan, showing product-detail trend panels, or\ncomparing similar products from a specific scan context.\n\nPrefer `GET /api/v1/products/{productId}/price-history-series` for a canonical\nhistorical time series across a date window. Prefer\n`GET /api/v1/products/{productId}/history` for the legacy current-price snapshot per\nvendor. Use `prices` for the current competitor table and `cheapest` for the\nsingle best option now.\n\n`scanId` narrows the trend context to a specific scan when supplied.\n`includeSimilar` can include similar product observations, `inStockOnly`\nfilters unavailable offers, and `limit` is capped at 1000. Recent scans can be\neventually consistent.\n\nCurrency conversion is not yet performed; currently stored prices are returned and the\nrequested `currency` value is echoed where supported.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scanId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "includeSimilar",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 10
            }
          },
          {
            "name": "inStockOnly",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                },
                "examples": {
                  "success": {
                    "summary": "Scan-scoped price trends",
                    "value": {
                      "data": {
                        "priceTrends": [
                          {
                            "competitorId": 1001,
                            "competitorName": "Big W",
                            "priceHistory": [
                              {
                                "scanId": "scan_20260712",
                                "date": "2026-07-12T00:00:00Z",
                                "price": 12.95,
                                "currency": "AUD",
                                "originalPrice": null,
                                "originalCurrency": null,
                                "isOutOfStock": false,
                                "priceIsStale": false,
                                "lastPriceFetchDate": null,
                                "mainVendorScanStatus": "fresh"
                              },
                              {
                                "scanId": "scan_20260714",
                                "date": "2026-07-14T00:00:00Z",
                                "price": 11.95,
                                "currency": "AUD",
                                "originalPrice": null,
                                "originalCurrency": null,
                                "isOutOfStock": false,
                                "priceIsStale": false,
                                "lastPriceFetchDate": null,
                                "mainVendorScanStatus": "fresh"
                              }
                            ]
                          }
                        ]
                      },
                      "meta": null,
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    },
    "/api/v1/products/search": {
      "get": {
        "tags": [
          "Product Matching"
        ],
        "summary": "Search for matching products.",
        "description": "Use this endpoint first when an integration or AI agent needs to turn a product name,\nbrand, category, or vendor-specific catalog hint into public product identifiers that\ncan be reused with price monitoring endpoints.\n\nResults are ranked product matches, not live competitor prices. After selecting a\nproduct, call `GET /api/v1/products/{productId}/prices` for the current market\nsnapshot, `GET /api/v1/products/{productId}/cheapest` for the single best option\nnow, or the history endpoints when you need movement over time.\n\nPagination uses `page` and `pageSize`; `pageSize` is capped at 100.\nSupplying `vendorId`, `category`, or price filters narrows the candidate set\nand is recommended for agent workflows that already know the shopping context.\n\nThis API is metered. Responses include quota and rate-limit headers, and calls may\nreturn `429 Too Many Requests` when the caller exceeds their plan quota.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "vendorId",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "brand",
            "in": "query",
            "schema": {
              "type": "string",
              "default": null
            }
          },
          {
            "name": "minPrice",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double",
              "default": null
            }
          },
          {
            "name": "maxPrice",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "double",
              "default": null
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                },
                "examples": {
                  "success": {
                    "summary": "Matched products",
                    "value": {
                      "data": [
                        {
                          "productId": "prod_ABC123",
                          "name": "UltraClean Laundry Liquid 2L",
                          "brand": "UltraClean",
                          "category": "Laundry",
                          "imageUrl": "https://example.com/images/prod-abc123.png",
                          "currentPrice": 12.5,
                          "currency": "AUD",
                          "priceLastUpdated": "2026-07-14T00:00:00Z",
                          "competitorCount": 3,
                          "lowestPrice": 11.95,
                          "highestPrice": 14.2,
                          "averagePrice": 12.88
                        },
                        {
                          "productId": "prod_DEF456",
                          "name": "FreshBrite Dishwasher Tablets 40 pack",
                          "brand": "FreshBrite",
                          "category": "Dishwashing",
                          "imageUrl": "https://example.com/images/prod-def456.png",
                          "currentPrice": 18,
                          "currency": "AUD",
                          "priceLastUpdated": "2026-07-13T23:30:00Z",
                          "competitorCount": 2,
                          "lowestPrice": 17.5,
                          "highestPrice": 19,
                          "averagePrice": 18.25
                        }
                      ],
                      "meta": {
                        "page": 1,
                        "pageSize": 20,
                        "totalCount": 2,
                        "totalPages": 1,
                        "hasNextPage": false
                      },
                      "error": null
                    }
                  }
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "text/plain": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              },
              "text/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": [ ]
          },
          {
            "Bearer": [ ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "EntityTagHeaderValue": {
        "type": "object",
        "properties": {
          "tag": {
            "$ref": "#/components/schemas/StringSegment"
          },
          "isWeak": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "FileResult": {
        "type": "object",
        "properties": {
          "contentType": {
            "type": "string",
            "nullable": true
          },
          "fileDownloadName": {
            "type": "string",
            "nullable": true
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "entityTag": {
            "$ref": "#/components/schemas/EntityTagHeaderValue"
          },
          "enableRangeProcessing": {
            "type": "boolean"
          }
        }
      },
      "FileStreamResult": {
        "type": "object",
        "properties": {
          "fileStream": {
            "$ref": "#/components/schemas/Stream"
          },
          "contentType": {
            "type": "string",
            "nullable": true
          },
          "fileDownloadName": {
            "type": "string",
            "nullable": true
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "entityTag": {
            "$ref": "#/components/schemas/EntityTagHeaderValue"
          },
          "enableRangeProcessing": {
            "type": "boolean"
          }
        }
      },
      "IFormFile": {
        "type": "string",
        "format": "binary"
      },
      "JsonElement": { },
      "NullableOfAcquisitionMethod": {
        "nullable": true
      },
      "NullableOfAgentType": {
        "enum": [
          "Default",
          "PricingExpert",
          "InventoryExpert",
          "BuyerExpert",
          "ProductExpert",
          null
        ],
        "nullable": true
      },
      "NullableOfProductValidationStatus": {
        "enum": [
          "PENDING",
          "IN_PROGRESS",
          "VALIDATED",
          "FAILED",
          "SKIPPED",
          "SUSPICIOUS",
          null
        ],
        "nullable": true
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Stream": {
        "type": "string",
        "format": "binary"
      },
      "StringSegment": {
        "type": "object",
        "properties": {
          "buffer": {
            "type": "string",
            "nullable": true
          },
          "offset": {
            "type": "integer",
            "format": "int32"
          },
          "length": {
            "type": "integer",
            "format": "int32"
          },
          "value": {
            "type": "string",
            "nullable": true
          },
          "hasValue": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.AgentContributionResponse": {
        "type": "object",
        "properties": {
          "agentType": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.Enums.AgentType"
          },
          "agentName": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "usage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.TokenUsageResponse"
          },
          "confidence": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.AgentDiscussionResponse": {
        "type": "object",
        "properties": {
          "contributions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.AgentContributionResponse"
            }
          },
          "summary": {
            "type": "string",
            "nullable": true
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "processingTimeMs": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.Chat.DTOs.AgentInfoResponse": {
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.Enums.AgentType"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "specialization": {
            "type": "string"
          },
          "isAvailable": {
            "type": "boolean"
          },
          "useCases": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "exampleQueries": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.AgentListResponse": {
        "type": "object",
        "properties": {
          "agents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.AgentInfoResponse"
            }
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ChatConfigurationResponse": {
        "type": "object",
        "properties": {
          "supportsMultiAgent": {
            "type": "boolean"
          },
          "availableAgents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.AgentInfoResponse"
            }
          },
          "maxMessagesPerConversation": {
            "type": "integer",
            "format": "int32"
          },
          "maxConversationsPerUserPerMonth": {
            "type": "integer",
            "format": "int32"
          },
          "conversationsUsedThisMonth": {
            "type": "integer",
            "format": "int32"
          },
          "conversationsRemainingThisMonth": {
            "type": "integer",
            "format": "int32"
          },
          "currentMonth": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ChatContentBlock": {
        "required": [
          "type"
        ],
        "type": "object",
        "anyOf": [
          {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatContentBlockWebAPIServer.Models.Chat.DTOs.MarkdownContentBlock"
          },
          {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatContentBlockWebAPIServer.Models.Chat.DTOs.ChartContentBlock"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "markdown": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatContentBlockWebAPIServer.Models.Chat.DTOs.MarkdownContentBlock",
            "chart": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatContentBlockWebAPIServer.Models.Chat.DTOs.ChartContentBlock"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ChatContentBlockWebAPIServer.Models.Chat.DTOs.ChartContentBlock": {
        "required": [
          "chart"
        ],
        "properties": {
          "type": {
            "enum": [
              "chart"
            ],
            "type": "string"
          },
          "chart": {
            "required": [
              "chartType",
              "xKey",
              "series",
              "data"
            ],
            "type": "object",
            "properties": {
              "chartType": {
                "type": "string"
              },
              "xKey": {
                "type": "string"
              },
              "series": {
                "type": "array",
                "items": {
                  "required": [
                    "key",
                    "label"
                  ],
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    },
                    "color": {
                      "type": "string",
                      "default": null,
                      "nullable": true
                    }
                  }
                }
              },
              "data": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              },
              "title": {
                "type": "string",
                "default": null,
                "nullable": true
              },
              "description": {
                "type": "string",
                "default": null,
                "nullable": true
              },
              "yFormat": {
                "type": "string",
                "default": null,
                "nullable": true
              },
              "options": {
                "type": "object",
                "default": null,
                "nullable": true
              }
            }
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ChatContentBlockWebAPIServer.Models.Chat.DTOs.MarkdownContentBlock": {
        "required": [
          "content"
        ],
        "properties": {
          "type": {
            "enum": [
              "markdown"
            ],
            "type": "string"
          },
          "content": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ChatMessageRequest": {
        "required": [
          "content"
        ],
        "type": "object",
        "properties": {
          "content": {
            "maxLength": 4000,
            "minLength": 1,
            "type": "string"
          },
          "conversationId": {
            "type": "string",
            "nullable": true
          },
          "agent": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.Enums.AgentType"
          },
          "agents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.Enums.AgentType"
            },
            "nullable": true
          },
          "enableHtml": {
            "type": "boolean"
          },
          "requestMultiAgent": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ChatMessageResponse": {
        "type": "object",
        "properties": {
          "conversationId": {
            "type": "string"
          },
          "conversationTitle": {
            "type": "string"
          },
          "isNewConversation": {
            "type": "boolean"
          },
          "userMessage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageResponse"
          },
          "assistantMessage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageResponse"
          },
          "processingTimeMs": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ContextReferenceResponse": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.ConversationResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastMessageAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "messageCount": {
            "type": "integer",
            "format": "int32"
          },
          "metadata": {
            "type": "object",
            "nullable": true
          },
          "serializedThreadState": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.MessageFeedbackRequest": {
        "required": [
          "rating"
        ],
        "type": "object",
        "properties": {
          "rating": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.Enums.MessageFeedbackRating"
          },
          "comment": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.MessageFeedbackResponse": {
        "type": "object",
        "properties": {
          "messageId": {
            "type": "string"
          },
          "conversationId": {
            "type": "string"
          },
          "rating": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.Enums.MessageFeedbackRating"
          },
          "recordedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.MessageListResponse": {
        "type": "object",
        "properties": {
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.MessageResponse"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.PaginationMetadata"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.MessageResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "conversationId": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "contentHtml": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "agent": {
            "$ref": "#/components/schemas/NullableOfAgentType"
          },
          "agents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.Enums.AgentType"
            },
            "nullable": true
          },
          "toolCalls": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ToolCallDto"
            },
            "nullable": true
          },
          "contextRefs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ContextReferenceResponse"
            },
            "nullable": true
          },
          "usage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.TokenUsageResponse"
          },
          "discussion": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.AgentDiscussionResponse"
          },
          "contentBlocks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.Chat.DTOs.ChatContentBlock"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.PaginationMetadata": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "hasNextPage": {
            "type": "boolean"
          },
          "hasPreviousPage": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.TokenUsageResponse": {
        "type": "object",
        "properties": {
          "promptTokens": {
            "type": "integer",
            "format": "int32"
          },
          "completionTokens": {
            "type": "integer",
            "format": "int32"
          },
          "totalTokens": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.Chat.DTOs.ToolCallDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "args": {
            "type": "object",
            "nullable": true
          },
          "result": { }
        }
      },
      "WebAPIServer.Models.Chat.DTOs.UpdateConversationRequest": {
        "type": "object",
        "properties": {
          "title": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          },
          "description": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Chat.Enums.AgentType": {
        "enum": [
          "Default",
          "PricingExpert",
          "InventoryExpert",
          "BuyerExpert",
          "ProductExpert"
        ]
      },
      "WebAPIServer.Models.Chat.Enums.MessageFeedbackRating": {
        "type": "integer"
      },
      "WebAPIServer.Models.Common.ApiResponseOfApiKeyDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.ApiKeyDto2"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfApiKeyGenerationResultDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.ApiKeyGenerationResultDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfBasketAnalysisDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.BasketAnalysisDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfBillingPortalDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.BillingPortalDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfBrandDetailsDiscoveryDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.BrandDetailsDiscoveryDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfCompanyDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Company.CompanyDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceMatrixDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.CompetitorPriceMatrixDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfCompetitorPriceTrendsDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.CompetitorPriceTrendsDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfContactRequestDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ContactRequest.ContactRequestDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfCreateScanResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CreateScanResponse"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfCurrentOrganizationAnalyticsDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.CurrentOrganizationAnalyticsDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfCustomFieldDefinitionDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.CustomFieldDefinitionDto2"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfEnqueueProductValidationResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.EnqueueProductValidationResponse"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfExportTemplateResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportTemplateResponse2"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfFeedbackDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.FeedbackDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfFilterLayoutResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterLayout.FilterLayoutResponseDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfMemberDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.MemberDto2"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfOnboardingCompleteDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Billing.OnboardingCompleteDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfOnboardingSessionDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.OnboardingSessionDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfOrganization": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Entities.Organization.Organization"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfOrganizationBillingDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.OrganizationBillingDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfOrganizationMembersDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.OrganizationMembersDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfOverviewStatisticsDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.OverviewStatisticsDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfPriceTableDataResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Dashboard.PriceTableDataResponse"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfPriceTrendsDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.PriceTrendsDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfProductDiscoveryResultsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.ProductDiscoveryResultsResponse"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfProductPriceTableDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.ProductPriceTableDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfProductValidationResultResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.ProductValidationResultResponse"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfProductValidationStatusResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.ProductValidationStatusResponse"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfScanStatusResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.ScanStatusResponse"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSetupIntentResponseDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Billing.SetupIntentResponseDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfStartDiscoveryResponseDTO": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StartDiscoveryResponseDTO"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfStaticImportResultDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StaticImport.StaticImportResultDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfString": {
        "type": "object",
        "properties": {
          "data": {
            "type": "string",
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfApiKeyDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ApiKeys.ApiKeyDto"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfExportTemplateResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportTemplateResponse"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfMemberDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.MemberDto"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfUserWorkspaceDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UserWorkspaceDto2"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSubscriptionDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceSubscriptionDto"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.IEnumerableOfWorkspaceSummaryDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceSummaryDto"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfAvailableCustomFieldDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterLayout.AvailableCustomFieldDto"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCompetitorDiscoveryDTO": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.CompetitorDiscoveryDTO"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfCustomFieldDefinitionDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.CustomFieldDefinitionDto"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfSystem.Collections.Generic.ListOfUsagePlanDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto"
            },
            "nullable": true
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfTrackedProductDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto2"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfUserContextDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UserContextDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfUserWorkspaceDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.UserWorkspaceDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfWorkspaceBillingDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceBillingDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfWorkspaceMembersDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceMembersDto"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.Common.ApiResponseOfWorkspaceSummaryDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceSummaryDto2"
          },
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.AIInsights.AIInsightsResponseDTO": {
        "type": "object",
        "properties": {
          "content": {
            "type": "string"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "filters": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.AIInsights.InsightsFiltersDTO"
          }
        }
      },
      "WebAPIServer.Models.DTOs.AIInsights.InsightsFiltersDTO": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string",
            "nullable": true
          },
          "competitors": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "includeSimilar": {
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Alerts.AlertConditionParamsDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string",
            "nullable": true
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "competitorId": {
            "type": "string",
            "nullable": true
          },
          "competitorName": {
            "type": "string",
            "nullable": true
          },
          "thresholdValue": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Alerts.CreateAlertRuleDto": {
        "required": [
          "name",
          "conditionType"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "conditionType": {
            "maxLength": 50,
            "minLength": 0,
            "type": "string"
          },
          "conditionParams": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.AlertConditionParamsDto"
          },
          "enabled": {
            "type": "boolean"
          },
          "deliveryChannels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Alerts.NotificationDataDto": {
        "type": "object",
        "properties": {
          "triggeredPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "thresholdPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "previousAvailability": {
            "type": "string",
            "nullable": true
          },
          "newAvailability": {
            "type": "string",
            "nullable": true
          },
          "conditionType": {
            "type": "string",
            "nullable": true
          },
          "productUrl": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Alerts.NotificationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "alertRuleId": {
            "type": "string"
          },
          "alertRuleName": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "severity": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "scanId": {
            "type": "string",
            "nullable": true
          },
          "productId": {
            "type": "string",
            "nullable": true
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "competitorId": {
            "type": "string",
            "nullable": true
          },
          "competitorName": {
            "type": "string",
            "nullable": true
          },
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.NotificationDataDto"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "readAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Alerts.ToggleAlertRuleDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Alerts.UpdateAlertRuleDto": {
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 200,
            "minLength": 1,
            "type": "string",
            "nullable": true
          },
          "conditionType": {
            "maxLength": 50,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "conditionParams": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Alerts.AlertConditionParamsDto"
          },
          "enabled": {
            "type": "boolean",
            "nullable": true
          },
          "deliveryChannels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ApiKeys.ApiKeyDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "keyPrefix": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "usageCount": {
            "type": "integer",
            "format": "int64"
          },
          "createdByEmail": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ApiKeys.ApiKeyDto2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "keyPrefix": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "usageCount": {
            "type": "integer",
            "format": "int64"
          },
          "createdByEmail": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.ApiKeys.ApiKeyGenerationResultDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "keyPrefix": {
            "type": "string"
          },
          "rawKey": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.ApiKeys.GenerateApiKeyRequestDto": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "minLength": 3,
            "type": "string"
          },
          "expirationDays": {
            "maximum": 365,
            "minimum": 1,
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ApiKeys.UpdateApiKeyRequestDto": {
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "minLength": 3,
            "type": "string",
            "nullable": true
          },
          "expirationDays": {
            "maximum": 365,
            "minimum": 1,
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Billing.ConfirmPaymentRequest": {
        "type": "object",
        "properties": {
          "setupIntentId": {
            "type": "string"
          },
          "usagePlanId": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Billing.OnboardingCompleteDto": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "subscriptionId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "trialEndsAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Billing.SetupIntentResponseDto": {
        "type": "object",
        "properties": {
          "setupIntentId": {
            "type": "string"
          },
          "clientSecret": {
            "type": "string"
          },
          "customerId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Company.CompanyDTO": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "userAdminId": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "logoUrl": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string",
            "nullable": true
          },
          "phoneNumber": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "website": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Company.InsightsConfigDto": {
        "type": "object",
        "properties": {
          "consensusThreshold": {
            "type": "number",
            "format": "double"
          },
          "minConfidenceThreshold": {
            "type": "number",
            "format": "double"
          },
          "priceSensitivityThreshold": {
            "type": "number",
            "format": "double"
          },
          "lowTicketDollarsThreshold": {
            "type": "number",
            "format": "double"
          },
          "highTicketPercentThreshold": {
            "type": "number",
            "format": "double"
          },
          "defenseGapLowTicket": {
            "type": "number",
            "format": "double"
          },
          "defenseGapHighTicket": {
            "type": "number",
            "format": "double"
          },
          "offenseGapLowTicket": {
            "type": "number",
            "format": "double"
          },
          "offenseGapHighTicket": {
            "type": "number",
            "format": "double"
          },
          "minMatchConfidence": {
            "type": "number",
            "format": "double"
          },
          "undercutThresholdPercent": {
            "type": "number",
            "format": "double"
          },
          "dedupeTtlHours": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Company.MarketplaceFilterDefaultDto": {
        "type": "object",
        "properties": {
          "exclude_marketplace_products_default": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Company.PrimaryVendorDto": {
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Enums.PrimaryVendorType"
          },
          "vendorId": {
            "type": "string",
            "nullable": true
          },
          "baseUrl": {
            "type": "string",
            "nullable": true
          },
          "csvPath": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Company.SetMarketplaceFilterDefaultDto": {
        "type": "object",
        "properties": {
          "exclude_marketplace_products_default": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Company.SetPrimaryVendorDto": {
        "required": [
          "type"
        ],
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Enums.PrimaryVendorType"
          },
          "vendorId": {
            "type": "string",
            "nullable": true
          },
          "baseUrl": {
            "type": "string",
            "nullable": true
          },
          "csvPath": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Company.UpdateInsightsConfigDto": {
        "required": [
          "consensusThreshold",
          "minConfidenceThreshold",
          "priceSensitivityThreshold",
          "lowTicketDollarsThreshold",
          "highTicketPercentThreshold",
          "defenseGapLowTicket",
          "defenseGapHighTicket",
          "offenseGapLowTicket",
          "offenseGapHighTicket",
          "minMatchConfidence",
          "undercutThresholdPercent",
          "dedupeTtlHours"
        ],
        "type": "object",
        "properties": {
          "consensusThreshold": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "minConfidenceThreshold": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "priceSensitivityThreshold": {
            "minimum": 0.01,
            "type": "number",
            "format": "double"
          },
          "lowTicketDollarsThreshold": {
            "minimum": 0.01,
            "type": "number",
            "format": "double"
          },
          "highTicketPercentThreshold": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "defenseGapLowTicket": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "defenseGapHighTicket": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "offenseGapLowTicket": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "offenseGapHighTicket": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "minMatchConfidence": {
            "maximum": 1,
            "minimum": 0,
            "type": "number",
            "format": "double"
          },
          "undercutThresholdPercent": {
            "minimum": 0.01,
            "type": "number",
            "format": "double"
          },
          "dedupeTtlHours": {
            "maximum": 2147483647,
            "minimum": 1,
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Company.VendorSystemOptionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "isAvailable": {
            "type": "boolean"
          },
          "category": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.CategoryExposureRow": {
        "type": "object",
        "properties": {
          "category_name": {
            "type": "string"
          },
          "total_matched_skus": {
            "type": "integer",
            "format": "int32"
          },
          "competitor_cheaper_percent": {
            "type": "number",
            "format": "double"
          },
          "avg_gap_absolute": {
            "type": "number",
            "format": "double"
          },
          "avg_gap_percent": {
            "type": "number",
            "format": "double"
          },
          "trend_direction": {
            "type": "string"
          },
          "exposure_level": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorDetailSummaryDto": {
        "type": "object",
        "properties": {
          "vendor_id": {
            "type": "string"
          },
          "competitor_name": {
            "type": "string"
          },
          "logo_url": {
            "type": "string",
            "nullable": true
          },
          "base_url": {
            "type": "string",
            "nullable": true
          },
          "custom_color": {
            "type": "string",
            "nullable": true
          },
          "last_scanned_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "total_perfect_matches": {
            "type": "integer",
            "format": "int32"
          },
          "total_similar_matches": {
            "type": "integer",
            "format": "int32"
          },
          "total_matches": {
            "type": "integer",
            "format": "int32"
          },
          "cheaper_than_us_percent": {
            "type": "number",
            "format": "double"
          },
          "cheaper_than_us_trend": {
            "type": "string"
          },
          "avg_undercut_depth_absolute": {
            "type": "number",
            "format": "double"
          },
          "avg_undercut_depth_percent": {
            "type": "number",
            "format": "double"
          },
          "oos_flags": {
            "type": "integer",
            "format": "int32"
          },
          "currency": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorMatchRowDto": {
        "type": "object",
        "properties": {
          "mappingId": {
            "type": "string"
          },
          "tracked_product_doc_id": {
            "type": "string",
            "nullable": true
          },
          "product_id": {
            "type": "string"
          },
          "product_name": {
            "type": "string"
          },
          "product_image_url": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string"
          },
          "subcategory": {
            "type": "string",
            "nullable": true
          },
          "our_price": {
            "type": "number",
            "format": "double"
          },
          "our_promo_active": {
            "type": "boolean"
          },
          "our_was_price": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "competitor_product_id": {
            "type": "string",
            "nullable": true
          },
          "competitor_product_name": {
            "type": "string",
            "nullable": true
          },
          "competitor_product_image_url": {
            "type": "string",
            "nullable": true
          },
          "competitor_price": {
            "type": "number",
            "format": "double"
          },
          "competitor_promo_active": {
            "type": "boolean"
          },
          "competitor_was_price": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "competitor_is_oos": {
            "type": "boolean"
          },
          "gap_absolute": {
            "type": "number",
            "format": "double"
          },
          "gap_percent": {
            "type": "number",
            "format": "double"
          },
          "matching_type": {
            "type": "string"
          },
          "match_confidence": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "key_difference": {
            "type": "string",
            "nullable": true
          },
          "why_this_match": {
            "type": "string",
            "nullable": true
          },
          "last_scanned_at": {
            "type": "string",
            "format": "date-time"
          },
          "is_stale": {
            "type": "boolean"
          },
          "currency": {
            "type": "string"
          },
          "is_marketplace": {
            "type": "boolean"
          },
          "is_third_party_seller": {
            "type": "boolean"
          },
          "seller_name": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorSensitivityDto": {
        "type": "object",
        "properties": {
          "category_heat_map": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CategoryExposureRow"
            }
          },
          "undercut_map": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.UndercutBarEntry"
            }
          },
          "price_position_over_time": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PricePositionTimeSeries"
          },
          "promo_aggression": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PromoAggressionSummary"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.OosEventDto": {
        "type": "object",
        "properties": {
          "start_date": {
            "type": "string",
            "format": "date-time"
          },
          "end_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfCompetitorMatchRowDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.CompetitorMatchRowDto"
            }
          },
          "total_count": {
            "type": "integer",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "page_size": {
            "type": "integer",
            "format": "int32"
          },
          "total_pages": {
            "type": "integer",
            "format": "int32"
          },
          "has_next_page": {
            "type": "boolean"
          },
          "has_previous_page": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PaginatedResultDtoOfObject": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array"
          },
          "total_count": {
            "type": "integer",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "page_size": {
            "type": "integer",
            "format": "int32"
          },
          "total_pages": {
            "type": "integer",
            "format": "int32"
          },
          "has_next_page": {
            "type": "boolean"
          },
          "has_previous_page": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PriceHistoryPointDto": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "is_on_promo": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PricePositionPoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "indexed_price": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PricePositionTimeSeries": {
        "type": "object",
        "properties": {
          "client_prices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PricePositionPoint"
            }
          },
          "competitor_prices": {
            "type": "array",
            "items": { }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.ProductDrawerDto": {
        "type": "object",
        "properties": {
          "tracked_product_doc_id": {
            "type": "string",
            "nullable": true
          },
          "product_id": {
            "type": "string"
          },
          "product_name": {
            "type": "string"
          },
          "product_image_url": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "matching_type": {
            "type": "string"
          },
          "match_confidence": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "why_this_match": {
            "type": "string",
            "nullable": true
          },
          "client_price_history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PriceHistoryPointDto"
            }
          },
          "competitor_price_history": {
            "type": "array",
            "items": { }
          },
          "promo_history": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PromoHistoryEntryDto"
            }
          },
          "oos_events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.OosEventDto"
            }
          },
          "current_client_price": {
            "type": "number",
            "format": "double"
          },
          "current_competitor_price": {
            "type": "number",
            "format": "double"
          },
          "competitor_is_oos": {
            "type": "boolean"
          },
          "currency": {
            "type": "string"
          },
          "product_url": {
            "type": "string",
            "nullable": true
          },
          "competitor_product_name": {
            "type": "string",
            "nullable": true
          },
          "competitor_product_image_url": {
            "type": "string",
            "nullable": true
          },
          "competitor_product_url": {
            "type": "string",
            "nullable": true
          },
          "is_marketplace": {
            "type": "boolean"
          },
          "is_third_party_seller": {
            "type": "boolean"
          },
          "seller_name": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PromoAggressionSummary": {
        "type": "object",
        "properties": {
          "total_promos_30d": {
            "type": "integer",
            "format": "int32"
          },
          "deepest_promo_discount": {
            "type": "number",
            "format": "double"
          },
          "most_promoted_category": {
            "type": "string"
          },
          "promo_timeline": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorDetail.PromoFrequencyPoint"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PromoFrequencyPoint": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "promo_count": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.PromoHistoryEntryDto": {
        "type": "object",
        "properties": {
          "start_date": {
            "type": "string",
            "format": "date-time"
          },
          "end_date": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "promo_type": {
            "type": "string",
            "nullable": true
          },
          "promo_text": {
            "type": "string",
            "nullable": true
          },
          "discount_percent": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorDetail.UndercutBarEntry": {
        "type": "object",
        "properties": {
          "category_name": {
            "type": "string"
          },
          "competitor_cheaper_percent": {
            "type": "number",
            "format": "double"
          },
          "we_are_cheaper_percent": {
            "type": "number",
            "format": "double"
          },
          "parity_percent": {
            "type": "number",
            "format": "double"
          },
          "sku_count": {
            "type": "integer",
            "format": "int32"
          },
          "avg_gap_absolute": {
            "type": "number",
            "format": "double"
          },
          "top_undercut_sku_name": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorPriceHistoryDto": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "integer",
            "format": "int32"
          },
          "competitorName": {
            "type": "string",
            "nullable": true
          },
          "priceHistory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PriceEntryDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorProductDto": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "integer",
            "format": "int32"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "productId": {
            "type": "integer",
            "format": "int32"
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "image": {
            "type": "string",
            "nullable": true
          },
          "price": {
            "type": "number",
            "format": "float"
          },
          "wasPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalWasPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "discountPercentage": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "promotionText": {
            "type": "string",
            "nullable": true
          },
          "matchPercentage": {
            "type": "integer",
            "format": "int32"
          },
          "mappingType": {
            "type": "string",
            "nullable": true
          },
          "tracked": {
            "type": "boolean"
          },
          "isOnDiscount": {
            "type": "boolean",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "quantity": {
            "type": "string",
            "nullable": true
          },
          "weight": {
            "type": "string",
            "nullable": true
          },
          "weightUnit": {
            "type": "string",
            "nullable": true
          },
          "variant": {
            "type": "string",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean",
            "nullable": true
          },
          "avgPrice13w": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "avgPrice52w": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "isMarketplace": {
            "type": "boolean"
          },
          "isThirdPartySeller": {
            "type": "boolean"
          },
          "sellerName": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorProductTableDto": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "totalProducts": {
            "type": "integer",
            "format": "int32"
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorProductDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Competitors.AddCompetitorRequestDto": {
        "required": [
          "vendor_id",
          "name",
          "base_url"
        ],
        "type": "object",
        "properties": {
          "vendor_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "base_url": {
            "type": "string",
            "format": "uri"
          },
          "onboarding_status": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "custom_color": {
            "pattern": "^(#[0-9a-fA-F]{6})?$",
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Competitors.CompetitorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "vendor_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "base_url": {
            "type": "string"
          },
          "onboarding_status": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "requested_date": {
            "type": "string",
            "format": "date-time"
          },
          "modified_at": {
            "type": "string",
            "format": "date-time"
          },
          "custom_color": {
            "type": "string",
            "nullable": true
          },
          "exclude_marketplace_products": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Competitors.CompetitorsListResponseDto": {
        "type": "object",
        "properties": {
          "competitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Competitors.CompetitorDto"
            }
          },
          "exclude_marketplace_products_default": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Competitors.UpdateCompetitorRequestDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "base_url": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "custom_color": {
            "pattern": "^(#[0-9a-fA-F]{6})?$",
            "type": "string",
            "nullable": true
          },
          "exclude_marketplace_products": {
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorSummaryDto": {
        "type": "object",
        "properties": {
          "shopPrice": {
            "type": "number",
            "format": "float"
          },
          "totalCompetitors": {
            "type": "integer",
            "format": "int32"
          },
          "totalCompanies": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "averageCompetitorPrice": {
            "type": "number",
            "format": "float"
          },
          "marketPosition": {
            "type": "integer",
            "format": "int32"
          },
          "currency": {
            "type": "string",
            "nullable": true
          },
          "originalShopPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalAverageCompetitorPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean",
            "nullable": true
          },
          "priceIsStale": {
            "type": "boolean"
          },
          "lastPriceFetchDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "mainVendorScanStatus": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorUnitOfMeasurePriceHistoryDto": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "integer",
            "format": "int32"
          },
          "competitorName": {
            "type": "string",
            "nullable": true
          },
          "unitOfMeasurePriceHistory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UnitOfMeasurePriceEntryDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.CompetitorUnitPriceHistoryDto": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "integer",
            "format": "int32"
          },
          "competitorName": {
            "type": "string",
            "nullable": true
          },
          "unitPriceHistory": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UnitPriceEntryDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ContactRequest.ContactRequestDTO": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "fullName": {
            "type": "string"
          },
          "workEmail": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "industry": {
            "type": "string",
            "nullable": true
          },
          "skuVolume": {
            "type": "string",
            "nullable": true
          },
          "mobile": {
            "type": "string",
            "nullable": true
          },
          "competitors": {
            "type": "string",
            "nullable": true
          },
          "monthlySkus": {
            "type": "string",
            "nullable": true
          },
          "sendNda": {
            "type": "boolean"
          },
          "source": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.ContactRequest.CreateContactRequestDTO": {
        "required": [
          "fullName",
          "workEmail",
          "company",
          "source"
        ],
        "type": "object",
        "properties": {
          "fullName": {
            "maxLength": 200,
            "minLength": 2,
            "type": "string"
          },
          "workEmail": {
            "maxLength": 254,
            "minLength": 0,
            "type": "string"
          },
          "company": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string"
          },
          "industry": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "skuVolume": {
            "maxLength": 50,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "mobile": {
            "maxLength": 30,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "competitors": {
            "maxLength": 1000,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "monthlySkus": {
            "maxLength": 50,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "sendNda": {
            "type": "boolean"
          },
          "source": {
            "pattern": "^(book-demo|contact)$",
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvAnalysisResultDto": {
        "type": "object",
        "properties": {
          "detectedColumns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "fieldSchema": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvFieldSchemaDto"
          },
          "suggestedStandardMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "suggestedCustomFieldMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "unmappedColumns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "mappingConfidence": {
            "type": "object",
            "additionalProperties": {
              "type": "number",
              "format": "double"
            }
          },
          "mappingReasoning": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "companyCustomFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sampleRows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "rowCount": {
            "type": "integer",
            "format": "int32"
          },
          "aiGenerated": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvColumnMappingDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "isEnabled": {
            "type": "boolean"
          },
          "columnMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "customFieldMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "requiredColumns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvFieldDefinitionDto": {
        "type": "object",
        "properties": {
          "fieldName": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "dataType": {
            "type": "string"
          },
          "exampleValues": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvFieldSchemaDto": {
        "type": "object",
        "properties": {
          "requiredFields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvFieldDefinitionDto"
            }
          },
          "optionalFields": {
            "type": "array",
            "items": { }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvPriceDataDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "productId": {
            "type": "string"
          },
          "rawProductId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "description": {
            "type": "string"
          },
          "productUrl": {
            "type": "string",
            "nullable": true
          },
          "vendorId": {
            "type": "string",
            "nullable": true
          },
          "wasPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "date": {
            "type": "string",
            "nullable": true
          },
          "imageUri": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "weight": {
            "type": "string",
            "nullable": true
          },
          "weightUnit": {
            "type": "string",
            "nullable": true
          },
          "volume": {
            "type": "string",
            "nullable": true
          },
          "volumeUnit": {
            "type": "string",
            "nullable": true
          },
          "quantity": {
            "type": "string",
            "nullable": true
          },
          "variant": {
            "type": "string",
            "nullable": true
          },
          "isOnDiscount": {
            "type": "boolean"
          },
          "discountPercentage": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "promotionText": {
            "type": "string",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "nullable": true
          },
          "availability": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean"
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "mpn": {
            "type": "string",
            "nullable": true
          },
          "gtin": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "nullable": true
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "size": {
            "type": "string",
            "nullable": true
          },
          "material": {
            "type": "string",
            "nullable": true
          },
          "style": {
            "type": "string",
            "nullable": true
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "descriptionHtml": {
            "type": "string",
            "nullable": true
          },
          "breadcrumbs": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "nullable": true
          },
          "additionalProperties": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "nullable": true
          },
          "aggregateRating": {
            "type": "object",
            "nullable": true
          },
          "canonicalUrl": {
            "type": "string",
            "nullable": true
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "nullable": true
          },
          "extractionProbability": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "extractionDate": {
            "type": "string",
            "nullable": true
          },
          "rawVendorData": {
            "type": "object",
            "nullable": true
          },
          "uploadDate": {
            "type": "string",
            "format": "date-time"
          },
          "uploadedBy": {
            "type": "string"
          },
          "uploadId": {
            "type": "string"
          },
          "effectiveDate": {
            "type": "string",
            "format": "date-time"
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvPriceUploadResultDto": {
        "type": "object",
        "properties": {
          "totalRows": {
            "type": "integer",
            "format": "int32"
          },
          "successCount": {
            "type": "integer",
            "format": "int32"
          },
          "errorCount": {
            "type": "integer",
            "format": "int32"
          },
          "priceRecordsStored": {
            "type": "integer",
            "format": "int32"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadErrorDto"
            }
          },
          "uploadId": {
            "type": "string"
          },
          "uploadDate": {
            "type": "string",
            "format": "date-time"
          },
          "effectiveDate": {
            "type": "string",
            "format": "date-time"
          },
          "productDetailsUpdated": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvProductUploadResultDto": {
        "type": "object",
        "properties": {
          "totalRows": {
            "type": "integer",
            "format": "int32"
          },
          "successfullyAdded": {
            "type": "integer",
            "format": "int32"
          },
          "alreadyTracked": {
            "type": "integer",
            "format": "int32"
          },
          "skipped": {
            "type": "integer",
            "format": "int32"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadErrorDto"
            }
          },
          "uploadId": {
            "type": "string"
          },
          "uploadDate": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvUploadDetailsDto": {
        "type": "object",
        "properties": {
          "uploadId": {
            "type": "string"
          },
          "uploadDate": {
            "type": "string",
            "format": "date-time"
          },
          "effectiveDate": {
            "type": "string",
            "format": "date-time"
          },
          "uploadedBy": {
            "type": "string"
          },
          "csvFileName": {
            "type": "string"
          },
          "totalProducts": {
            "type": "integer",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvPriceDataDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvUploadErrorDto": {
        "type": "object",
        "properties": {
          "row": {
            "type": "integer",
            "format": "int32"
          },
          "productId": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvUploadHistoryDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Csv.CsvUploadHistoryItemDto"
            }
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "totalRecords": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.CsvUploadHistoryItemDto": {
        "type": "object",
        "properties": {
          "uploadId": {
            "type": "string"
          },
          "uploadDate": {
            "type": "string",
            "format": "date-time"
          },
          "effectiveDate": {
            "type": "string",
            "format": "date-time"
          },
          "uploadedBy": {
            "type": "string"
          },
          "recordCount": {
            "type": "integer",
            "format": "int32"
          },
          "csvFileName": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Csv.SaveCsvMappingDto": {
        "type": "object",
        "properties": {
          "columnMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "customFieldMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "isEnabled": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CustomFields.CreateCustomFieldDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "maxLength": 50,
            "pattern": "^[a-z0-9_]+$",
            "type": "string"
          },
          "name": {
            "maxLength": 100,
            "type": "string"
          },
          "isFilterable": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CustomFields.CustomFieldDefinitionDto": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "isFilterable": {
            "type": "boolean"
          },
          "displayOrder": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CustomFields.CustomFieldDefinitionDto2": {
        "required": [
          "id",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "isFilterable": {
            "type": "boolean"
          },
          "displayOrder": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.CustomFields.CustomFieldFilterDto": {
        "required": [
          "displayName",
          "id",
          "values"
        ],
        "type": "object",
        "properties": {
          "displayName": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "values": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "displayOrder": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.CustomFields.UpdateCustomFieldDto": {
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "isFilterable": {
            "type": "boolean",
            "nullable": true
          },
          "displayOrder": {
            "maximum": 1000,
            "minimum": 0,
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Dashboard.CompetitorData": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Dashboard.PriceTableDataResponse": {
        "type": "object",
        "properties": {
          "headers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Dashboard.TableHeader"
            }
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Dashboard.PriceTableSingleRowData"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Dashboard.PriceTableSingleRowData": {
        "type": "object",
        "properties": {
          "productData": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Dashboard.ProductData"
          },
          "competitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Dashboard.CompetitorData"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Dashboard.ProductData": {
        "type": "object",
        "properties": {
          "productImage": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "categoryIcon": {
            "type": "string"
          },
          "categoryName": {
            "type": "string"
          },
          "sku": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Dashboard.TableHeader": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "string"
          },
          "companyName": {
            "type": "string"
          },
          "logoUrl": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DataPointsBilling.DataPointProjectionDto": {
        "type": "object",
        "properties": {
          "projectedTotal": {
            "type": "integer",
            "format": "int64"
          },
          "projectedRemaining": {
            "type": "integer",
            "format": "int64"
          },
          "consumedToDate": {
            "type": "integer",
            "format": "int64"
          },
          "quota": {
            "type": "integer",
            "format": "int64"
          },
          "dailyAverage": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DataPointsBilling.DataPointTraceEntryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "competitorId": {
            "type": "string"
          },
          "competitorName": {
            "type": "string"
          },
          "scanProfileId": {
            "type": "string"
          },
          "scannedUrl": {
            "type": "string"
          },
          "billingCycleId": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DataPointsBilling.DataPointTracePageDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DataPointsBilling.DataPointTraceEntryDto"
            }
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "hasMore": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DataPointsBilling.DataPointUsageDto": {
        "type": "object",
        "properties": {
          "consumed": {
            "type": "integer",
            "format": "int64"
          },
          "quota": {
            "type": "integer",
            "format": "int64"
          },
          "percentUsed": {
            "type": "number",
            "format": "double"
          },
          "cycleStart": {
            "type": "string",
            "format": "date-time"
          },
          "cycleEnd": {
            "type": "string",
            "format": "date-time"
          },
          "daysRemaining": {
            "type": "integer",
            "format": "int32"
          },
          "billingCycleStartDay": {
            "type": "integer",
            "format": "int32"
          },
          "nextCycleStart": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DataPointsBilling.ScanProfileEstimationDto": {
        "type": "object",
        "properties": {
          "scanProfileId": {
            "type": "string"
          },
          "frequency": {
            "type": "string"
          },
          "productCount": {
            "type": "integer",
            "format": "int32"
          },
          "estimatedMonthlyDataPoints": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DiscoveryStatusDTO": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "scanStatus": {
            "type": "string"
          },
          "discoveryStatus": {
            "type": "string",
            "nullable": true
          },
          "discoveryJobId": {
            "type": "string",
            "nullable": true
          },
          "discoveryAttempts": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "discoveryRequestedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "discoveryStartedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "discoveryCompletedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "discoveryDeadline": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "discoveryProductCount": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "discoveryLastError": {
            "type": "string",
            "nullable": true
          },
          "discoveryResultBlobUri": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.DomainConfig.AvailabilityOverrideDto": {
        "type": "object",
        "properties": {
          "condition": {
            "type": "string"
          },
          "overrides": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DomainConfig.FieldMappingDto": {
        "type": "object",
        "properties": {
          "source_path": {
            "type": "string"
          },
          "target_field": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.DomainConfig.FieldOverridesDto": {
        "type": "object",
        "properties": {
          "field_mappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.FieldMappingDto"
            },
            "nullable": true
          },
          "field_inclusions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "field_exclusions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "value_transforms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.ValueTransformDto"
            },
            "nullable": true
          },
          "availability_overrides": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.DomainConfig.AvailabilityOverrideDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.DomainConfig.ValueTransformDto": {
        "type": "object",
        "properties": {
          "target_field": {
            "type": "string"
          },
          "operation": {
            "type": "string"
          },
          "parameters": {
            "type": "object",
            "nullable": true
          },
          "enabled": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExchangeRateResponseDto": {
        "type": "object",
        "properties": {
          "base": {
            "type": "string"
          },
          "rates": {
            "type": "object",
            "additionalProperties": {
              "type": "number",
              "format": "double"
            }
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "isStale": {
            "type": "boolean"
          },
          "provider": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExplorationFilterOptionsDto": {
        "type": "object",
        "properties": {
          "vendors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "brands": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "priceRange": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationPriceRangeDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExplorationPriceRangeDto": {
        "type": "object",
        "properties": {
          "min": {
            "type": "number",
            "format": "double"
          },
          "max": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExplorationProductDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "productId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string",
            "nullable": true
          },
          "price": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "wasPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "imageUri": {
            "type": "string",
            "nullable": true
          },
          "productUrl": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "source": {
            "type": "string"
          },
          "isTracked": {
            "type": "boolean"
          },
          "hasMapping": {
            "type": "boolean"
          },
          "trackedProductId": {
            "type": "string",
            "nullable": true
          },
          "lastSeen": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "matchingType": {
            "type": "string",
            "nullable": true
          },
          "confidence": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "sourceProductId": {
            "type": "string",
            "nullable": true
          },
          "sourceProductName": {
            "type": "string",
            "nullable": true
          },
          "sourceMappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationSourceMappingDto"
            },
            "nullable": true
          },
          "totalSourceMappingsCount": {
            "type": "integer",
            "format": "int32"
          },
          "promoText": {
            "type": "string",
            "nullable": true
          },
          "isMarketplace": {
            "type": "boolean"
          },
          "isThirdPartySeller": {
            "type": "boolean"
          },
          "sellerName": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExplorationSearchResultDto": {
        "type": "object",
        "properties": {
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationProductDto"
            }
          },
          "statistics": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationStatisticsDto"
          },
          "vendorBreakdown": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ExplorationVendorBreakdownDto"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PaginationDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExplorationSourceMappingDto": {
        "type": "object",
        "properties": {
          "sourceProductId": {
            "type": "string"
          },
          "sourceProductName": {
            "type": "string",
            "nullable": true
          },
          "originalSourceProductId": {
            "type": "string",
            "nullable": true
          },
          "targetProductId": {
            "type": "string",
            "nullable": true
          },
          "competitorVendorId": {
            "type": "string",
            "nullable": true
          },
          "matchingType": {
            "type": "string",
            "nullable": true
          },
          "confidence": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "relationshipType": {
            "type": "string"
          },
          "isResolved": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExplorationStatisticsDto": {
        "type": "object",
        "properties": {
          "totalProducts": {
            "type": "integer",
            "format": "int32"
          },
          "totalVendors": {
            "type": "integer",
            "format": "int32"
          },
          "averagePrice": {
            "type": "number",
            "format": "double"
          },
          "totalCategories": {
            "type": "integer",
            "format": "int32"
          },
          "trackedCount": {
            "type": "integer",
            "format": "int32"
          },
          "untrackedCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ExplorationVendorBreakdownDto": {
        "type": "object",
        "properties": {
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string",
            "nullable": true
          },
          "productCount": {
            "type": "integer",
            "format": "int32"
          },
          "confirmedCount": {
            "type": "integer",
            "format": "int32"
          },
          "suggestedCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Export.ColumnGroupConfigDto": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Export.CreateExportTemplateRequest": {
        "required": [
          "name",
          "config"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "minLength": 0,
            "pattern": "^[a-zA-Z0-9\\s\\-_]+$",
            "type": "string"
          },
          "pageType": {
            "type": "string",
            "nullable": true
          },
          "config": { }
        }
      },
      "WebAPIServer.Models.DTOs.Export.ExportColumnConfigDto": {
        "type": "object",
        "properties": {
          "groups": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ColumnGroupConfigDto"
            },
            "nullable": true
          },
          "groupOrder": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Export.ExportDataScope": {
        "enum": [
          "current-view",
          "entire-catalog",
          "specific-categories"
        ]
      },
      "WebAPIServer.Models.DTOs.Export.ExportFiltersDto": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string",
            "nullable": true
          },
          "productId": {
            "type": "string",
            "nullable": true
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "competitors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "owner": {
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "customFieldFilters": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "nullable": true
          },
          "includeSimilar": {
            "type": "boolean"
          },
          "insightType": {
            "type": "string",
            "nullable": true
          },
          "insightSeverity": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Export.ExportFormat": {
        "enum": [
          "csv",
          "excel",
          "pdf"
        ]
      },
      "WebAPIServer.Models.DTOs.Export.ExportPageType": {
        "enum": [
          "overview",
          "tracked-products",
          "insights",
          "competitor",
          "product-detail"
        ]
      },
      "WebAPIServer.Models.DTOs.Export.ExportTemplateResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "pageType": {
            "type": "string",
            "nullable": true
          },
          "config": { },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Export.ExportTemplateResponse2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "pageType": {
            "type": "string",
            "nullable": true
          },
          "config": { },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Export.ExportTimePeriod": {
        "enum": [
          "latest-scan",
          "historical"
        ]
      },
      "WebAPIServer.Models.DTOs.Export.GenerateExportRequest": {
        "required": [
          "pageType",
          "format"
        ],
        "type": "object",
        "properties": {
          "pageType": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportPageType"
          },
          "format": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportFormat"
          },
          "dataScope": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportDataScope"
          },
          "timePeriod": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportTimePeriod"
          },
          "historicalRange": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.HistoricalRangeDto"
          },
          "filters": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportFiltersDto"
          },
          "columns": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Export.ExportColumnConfigDto"
          },
          "templateId": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Export.HistoricalRangeDto": {
        "type": "object",
        "properties": {
          "start": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "end": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Export.RenameExportTemplateRequest": {
        "required": [
          "name"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "minLength": 0,
            "pattern": "^[a-zA-Z0-9\\s\\-_]+$",
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Feedback.CreateFeedbackRequestDTO": {
        "required": [
          "issueType"
        ],
        "type": "object",
        "properties": {
          "issueType": {
            "type": "string"
          },
          "subject": {
            "maxLength": 200,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "message": {
            "maxLength": 2000,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "pageLocation": {
            "type": "string",
            "nullable": true
          },
          "productSku": {
            "type": "string",
            "nullable": true
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "competitorVendorId": {
            "type": "string",
            "nullable": true
          },
          "searchQuery": {
            "type": "string",
            "nullable": true
          },
          "sourceProductId": {
            "type": "string",
            "nullable": true
          },
          "targetProductId": {
            "type": "string",
            "nullable": true
          },
          "scanContext": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.ScanContextDto"
          },
          "rowDataSnapshot": {
            "type": "object",
            "nullable": true
          },
          "tableContext": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.TableContextDto"
          },
          "dataTimestamp": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Feedback.FeedbackDTO": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "userId": {
            "type": "string"
          },
          "userName": {
            "type": "string",
            "nullable": true
          },
          "userEmail": {
            "type": "string",
            "nullable": true
          },
          "issueType": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "message": {
            "type": "string",
            "nullable": true
          },
          "pageLocation": {
            "type": "string",
            "nullable": true
          },
          "productSku": {
            "type": "string",
            "nullable": true
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "competitorVendorId": {
            "type": "string",
            "nullable": true
          },
          "searchQuery": {
            "type": "string",
            "nullable": true
          },
          "sourceProductId": {
            "type": "string",
            "nullable": true
          },
          "targetProductId": {
            "type": "string",
            "nullable": true
          },
          "userAgent": {
            "type": "string",
            "nullable": true
          },
          "assignedToUserId": {
            "type": "string",
            "nullable": true
          },
          "assignedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "resolvedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resolutionNotes": {
            "type": "string",
            "nullable": true
          },
          "scanContext": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.ScanContextDto"
          },
          "rowDataSnapshot": {
            "type": "object",
            "nullable": true
          },
          "tableContext": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.TableContextDto"
          },
          "dataTimestamp": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Feedback.PaginationInfoDto": {
        "type": "object",
        "properties": {
          "currentPage": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalItems": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Feedback.ScanContextDto": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "scanDate": {
            "type": "string",
            "format": "date-time"
          },
          "includeSimilar": {
            "type": "boolean",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Feedback.TableContextDto": {
        "type": "object",
        "properties": {
          "tableType": {
            "type": "string"
          },
          "filters": {
            "type": "object",
            "nullable": true
          },
          "pagination": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Feedback.PaginationInfoDto"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.FilterLayout.AvailableCustomFieldDto": {
        "required": [
          "fieldKey",
          "displayName"
        ],
        "type": "object",
        "properties": {
          "fieldKey": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "alreadyInLayout": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.FilterLayout.FilterLayoutItemDto": {
        "required": [
          "filterId",
          "filterType",
          "displayName"
        ],
        "type": "object",
        "properties": {
          "filterId": {
            "type": "string"
          },
          "filterType": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          },
          "displayOrder": {
            "type": "integer",
            "format": "int32"
          },
          "visible": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.FilterLayout.FilterLayoutResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterLayout.FilterLayoutItemDto"
            }
          },
          "lastModifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastModifiedBy": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.FilterLayout.UpdateFilterLayoutItemDto": {
        "required": [
          "filterId"
        ],
        "type": "object",
        "properties": {
          "filterId": {
            "type": "string"
          },
          "displayOrder": {
            "maximum": 1000,
            "minimum": 0,
            "type": "integer",
            "format": "int32"
          },
          "visible": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.FilterLayout.UpdateFilterLayoutRequestDto": {
        "required": [
          "lastModifiedAt",
          "items"
        ],
        "type": "object",
        "properties": {
          "lastModifiedAt": {
            "type": "string",
            "format": "date-time"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.FilterLayout.UpdateFilterLayoutItemDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.FilterOptionsDto": {
        "type": "object",
        "properties": {
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductFilterDto"
            },
            "nullable": true
          },
          "scanDates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.ScanDateInfo"
            },
            "nullable": true
          },
          "mappingTypes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Insights.ActionRequest": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string"
          },
          "notes": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Insights.DismissRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Insights.SnoozeRequest": {
        "type": "object",
        "properties": {
          "hours": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Invitations.AcceptInvitationRequestDTO": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "nullable": true
          },
          "idToken": {
            "type": "string",
            "nullable": true
          }
        },
        "default": null,
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Invitations.CreateInvitationRequestDTO": {
        "required": [
          "email",
          "role"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Invitations.InvitationDetailsDTO": {
        "required": [
          "email",
          "companyName",
          "role",
          "invitedBy"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "companyName": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "invitedBy": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Invitations.InvitationResponseDTO": {
        "required": [
          "token",
          "email",
          "role",
          "invitedBy",
          "status",
          "companyId"
        ],
        "type": "object",
        "properties": {
          "token": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "invitedBy": {
            "type": "string"
          },
          "invitedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "companyName": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Invitations.ValidateInvitationResponseDTO": {
        "type": "object",
        "properties": {
          "isValid": {
            "type": "boolean"
          },
          "message": {
            "type": "string",
            "nullable": true
          },
          "invitation": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Invitations.InvitationDetailsDTO"
          }
        }
      },
      "WebAPIServer.Models.DTOs.MarketBenchmarksDto": {
        "type": "object",
        "properties": {
          "currentMarketAverage": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "competitorRetailerCount": {
            "type": "integer",
            "format": "int32"
          },
          "averageScansPerRetailer": {
            "type": "integer",
            "format": "int32"
          },
          "rolling13wAverage": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "rolling52wAverage": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "change13wVsCurrent": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "change52wVsCurrent": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "weeksObserved13": {
            "type": "integer",
            "format": "int32"
          },
          "weeksObserved52": {
            "type": "integer",
            "format": "int32"
          },
          "userPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "userVsCurrentDelta": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "userVs13wDelta": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "userVs52wDelta": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "anchorIsoWeek": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "timeSeries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.MarketBenchmarkTimeSeriesPointDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.MarketBenchmarkTimeSeriesPointDto": {
        "type": "object",
        "properties": {
          "isoWeek": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "currentAverage": {
            "type": "number",
            "format": "float"
          },
          "rolling13wAverage": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "rolling52wAverage": {
            "type": "number",
            "format": "float",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.MetadataTupleDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "nullable": true
          },
          "value": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.BrandDetailsDiscoveryDTO": {
        "type": "object",
        "properties": {
          "description": {
            "maxLength": 1000,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.CompetitorDiscoveryDTO": {
        "required": [
          "name",
          "website"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string"
          },
          "website": {
            "maxLength": 255,
            "minLength": 0,
            "type": "string",
            "format": "uri"
          },
          "description": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "confidenceScore": {
            "maximum": 100,
            "minimum": 0,
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "matchReason": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.CompetitorDiscoveryRequest": {
        "required": [
          "companyName"
        ],
        "type": "object",
        "properties": {
          "companyName": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string"
          },
          "website": {
            "maxLength": 2048,
            "minLength": 0,
            "type": "string",
            "format": "uri",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.CreateProductDiscoveryRequest": {
        "type": "object",
        "properties": {
          "crawlStrategy": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.CreateScanResponse": {
        "required": [
          "jobId",
          "status",
          "statusUrl",
          "resultsUrl"
        ],
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "statusUrl": {
            "type": "string"
          },
          "resultsUrl": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.EnqueueProductValidationRequest": {
        "required": [
          "productUrl"
        ],
        "type": "object",
        "properties": {
          "productUrl": {
            "maxLength": 2048,
            "minLength": 0,
            "type": "string",
            "format": "uri"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.EnqueueProductValidationResponse": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.OnboardingProductDto": {
        "required": [
          "id",
          "source",
          "name",
          "product_id",
          "vendor_id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "source": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Entities.ProductSource"
          },
          "name": {
            "type": "string"
          },
          "price": {
            "type": "string"
          },
          "product_id": {
            "type": "string"
          },
          "product_url": {
            "type": "string"
          },
          "vendor_id": {
            "type": "string"
          },
          "was_price": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "image_uri": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "weight": {
            "type": "string"
          },
          "weight_unit": {
            "type": "string"
          },
          "volume": {
            "type": "string"
          },
          "volume_unit": {
            "type": "string"
          },
          "quantity": {
            "type": "string"
          },
          "variant": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "availability": {
            "type": "string",
            "nullable": true
          },
          "is_on_discount": {
            "type": "boolean",
            "nullable": true
          },
          "discount_percentage": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "promotion_text": {
            "type": "string"
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "mpn": {
            "type": "string",
            "nullable": true
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "size": {
            "type": "string",
            "nullable": true
          },
          "material": {
            "type": "string",
            "nullable": true
          },
          "style": {
            "type": "string",
            "nullable": true
          },
          "description_html": {
            "type": "string",
            "nullable": true
          },
          "canonical_url": {
            "type": "string",
            "nullable": true
          },
          "extraction_probability": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "extraction_date": {
            "type": "string",
            "nullable": true
          },
          "gtin_json": {
            "type": "string",
            "nullable": true
          },
          "features_json": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "breadcrumbs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.ZyteBreadcrumbDto"
            },
            "nullable": true
          },
          "additional_properties_json": { },
          "aggregate_rating_json": { },
          "variants_json": { },
          "raw_vendor_data_json": { },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.OnboardingProductDto2": {
        "required": [
          "id",
          "source",
          "name",
          "product_id",
          "vendor_id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "source": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Entities.ProductSource"
          },
          "name": {
            "type": "string"
          },
          "price": {
            "type": "string"
          },
          "product_id": {
            "type": "string"
          },
          "product_url": {
            "type": "string"
          },
          "vendor_id": {
            "type": "string"
          },
          "was_price": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "image_uri": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "weight": {
            "type": "string"
          },
          "weight_unit": {
            "type": "string"
          },
          "volume": {
            "type": "string"
          },
          "volume_unit": {
            "type": "string"
          },
          "quantity": {
            "type": "string"
          },
          "variant": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "availability": {
            "type": "string",
            "nullable": true
          },
          "is_on_discount": {
            "type": "boolean",
            "nullable": true
          },
          "discount_percentage": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "promotion_text": {
            "type": "string"
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "mpn": {
            "type": "string",
            "nullable": true
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "size": {
            "type": "string",
            "nullable": true
          },
          "material": {
            "type": "string",
            "nullable": true
          },
          "style": {
            "type": "string",
            "nullable": true
          },
          "description_html": {
            "type": "string",
            "nullable": true
          },
          "canonical_url": {
            "type": "string",
            "nullable": true
          },
          "extraction_probability": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "extraction_date": {
            "type": "string",
            "nullable": true
          },
          "gtin_json": {
            "type": "string",
            "nullable": true
          },
          "features_json": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "breadcrumbs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.ZyteBreadcrumbDto"
            },
            "nullable": true
          },
          "additional_properties_json": { },
          "aggregate_rating_json": { },
          "variants_json": { },
          "raw_vendor_data_json": { },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.OnboardingSessionDTO": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "userEmail": {
            "type": "string"
          },
          "stageData": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.OnboardingStageDataDTO"
          },
          "currentStage": {
            "type": "integer",
            "format": "int32"
          },
          "isCompleted": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.OnboardingStageDataDTO": {
        "type": "object",
        "properties": {
          "stage1": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage1CompanyInfoDTO"
          },
          "stage2": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage2BrandDetailsDTO"
          },
          "stage3": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage3ProductsResponseDTO"
          },
          "stage4": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO"
          },
          "stage5": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage5PlanSelectionDTO"
          },
          "stripePayment": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.StripePaymentStatusDTO"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.ProductDiscoveryResultsResponse": {
        "required": [
          "products"
        ],
        "type": "object",
        "properties": {
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.OnboardingProductDto"
            }
          },
          "count": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.ProductValidationResultResponse": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "validatedProduct": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.OnboardingProductDto2"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.ProductValidationStatusResponse": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string"
          },
          "productUrl": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.ScanStatusResponse": {
        "required": [
          "jobId",
          "status"
        ],
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "itemsScraped": {
            "type": "integer",
            "format": "int32"
          },
          "errorsCount": {
            "type": "integer",
            "format": "int32"
          },
          "startedTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updatedTime": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "baseUrl": {
            "type": "string"
          },
          "crawlStrategy": {
            "type": "string"
          },
          "isConsumed": {
            "type": "boolean"
          },
          "productsIngested": {
            "type": "integer",
            "format": "int32"
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          },
          "finishedTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage1CompanyInfoDTO": {
        "required": [
          "brandName",
          "websiteUrl"
        ],
        "type": "object",
        "properties": {
          "brandName": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string"
          },
          "websiteUrl": {
            "maxLength": 255,
            "minLength": 0,
            "type": "string",
            "format": "uri"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage1CompanyInfoDTO2": {
        "required": [
          "brandName",
          "websiteUrl"
        ],
        "type": "object",
        "properties": {
          "brandName": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string"
          },
          "websiteUrl": {
            "maxLength": 255,
            "minLength": 0,
            "type": "string",
            "format": "uri"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage2BrandDetailsDTO": {
        "type": "object",
        "properties": {
          "logoUrl": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "brandDescription": {
            "maxLength": 1000,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage2BrandDetailsDTO2": {
        "type": "object",
        "properties": {
          "logoUrl": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "brandDescription": {
            "maxLength": 1000,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage3ProductsResponseDTO": {
        "type": "object",
        "properties": {
          "selectedProductIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "discoveredProducts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.OnboardingProductDto"
            }
          },
          "validationJobs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.ValidationJobSummary"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage3ProductsUpdateDTO": {
        "type": "object",
        "properties": {
          "selectedProductIds": {
            "maxItems": 100,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO": {
        "type": "object",
        "properties": {
          "selectedCompetitors": {
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO.CompetitorSelectionDTO"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO.CompetitorSelectionDTO": {
        "required": [
          "name",
          "website"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string"
          },
          "website": {
            "maxLength": 255,
            "minLength": 0,
            "type": "string",
            "format": "uri"
          },
          "description": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "confidenceScore": {
            "maximum": 100,
            "minimum": 0,
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "matchReason": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO2": {
        "type": "object",
        "properties": {
          "selectedCompetitors": {
            "maxItems": 10,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Onboarding.Stage4CompetitorsDTO.CompetitorSelectionDTO"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage5PlanSelectionDTO": {
        "required": [
          "selectedPlanId"
        ],
        "type": "object",
        "properties": {
          "selectedPlanId": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.Stage5PlanSelectionDTO2": {
        "required": [
          "selectedPlanId"
        ],
        "type": "object",
        "properties": {
          "selectedPlanId": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.StripePaymentStatusDTO": {
        "type": "object",
        "properties": {
          "paymentValidated": {
            "type": "boolean"
          },
          "paymentValidatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "subscriptionCreated": {
            "type": "boolean"
          },
          "subscriptionCreatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Onboarding.UpdateTutorialProgressRequest": {
        "type": "object",
        "properties": {
          "tutorialStep": {
            "maximum": 10,
            "minimum": 0,
            "type": "integer",
            "format": "int32"
          },
          "tutorialCompleted": {
            "type": "boolean"
          },
          "skipped": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.ValidationJobSummary": {
        "required": [
          "jobId",
          "productUrl",
          "status"
        ],
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string"
          },
          "productUrl": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "finishedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Onboarding.ZyteBreadcrumbDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.AddMemberDto": {
        "required": [
          "userId"
        ],
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "role": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.BillingPortalDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.CreateWorkspaceDto": {
        "required": [
          "name",
          "usagePlanId",
          "website"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "usagePlanId": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "logoUrl": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string",
            "nullable": true
          },
          "phoneNumber": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.CurrentOrganizationAnalyticsDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "organizationName": {
            "type": "string"
          },
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceAnalyticsDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.MemberDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "role": {
            "type": "string"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.MemberDto2": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "role": {
            "type": "string"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.MembershipAnalyticsDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "role": {
            "type": "string"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.OrganizationBillingDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "organizationName": {
            "type": "string"
          },
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceBillingItemDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.OrganizationMembersDto": {
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "organizationName": {
            "type": "string"
          },
          "workspaces": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceMembersItemDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.PendingInvitationDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "invitedAt": {
            "type": "string",
            "format": "date-time"
          },
          "invitedBy": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.SwitchContextRequestDto": {
        "required": [
          "organizationId",
          "workspaceId"
        ],
        "type": "object",
        "properties": {
          "organizationId": {
            "type": "string"
          },
          "workspaceId": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.UpdateMemberDto": {
        "required": [
          "role"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.UpdateWorkspaceSettingsDto": {
        "type": "object",
        "properties": {
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.UserContextDto": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "organizationId": {
            "type": "string",
            "nullable": true
          },
          "organizationName": {
            "type": "string",
            "nullable": true
          },
          "workspaceId": {
            "type": "string",
            "nullable": true
          },
          "workspaceName": {
            "type": "string",
            "nullable": true
          },
          "lastSwitched": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.UserWorkspaceDto": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "workspaceWebsite": {
            "type": "string",
            "nullable": true
          },
          "organizationId": {
            "type": "string",
            "nullable": true
          },
          "organizationName": {
            "type": "string",
            "nullable": true
          },
          "userRole": {
            "type": "string"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "planName": {
            "type": "string",
            "nullable": true
          },
          "basePrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.UserWorkspaceDto2": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "workspaceWebsite": {
            "type": "string",
            "nullable": true
          },
          "organizationId": {
            "type": "string",
            "nullable": true
          },
          "organizationName": {
            "type": "string",
            "nullable": true
          },
          "userRole": {
            "type": "string"
          },
          "joinedAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "planName": {
            "type": "string",
            "nullable": true
          },
          "basePrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceAnalyticsDto": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "logoUrl": {
            "type": "string",
            "nullable": true
          },
          "website": {
            "type": "string",
            "nullable": true
          },
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          },
          "subscriptionId": {
            "type": "string",
            "nullable": true
          },
          "usagePlan": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto2"
          },
          "status": {
            "type": "string"
          },
          "trialEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "currentPeriodEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "usageStatus": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.WorkspaceUsageStatusDto"
          },
          "memberCount": {
            "type": "integer",
            "format": "int32"
          },
          "skuCount": {
            "type": "integer",
            "format": "int32"
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.MembershipAnalyticsDto"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceBillingDto": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "usagePlanName": {
            "type": "string"
          },
          "basePrice": {
            "type": "number",
            "format": "double"
          },
          "currentSkuUsage": {
            "type": "integer",
            "format": "int32"
          },
          "maxSkuQuota": {
            "type": "integer",
            "format": "int32"
          },
          "currentUserUsage": {
            "type": "integer",
            "format": "int32"
          },
          "maxUserQuota": {
            "type": "integer",
            "format": "int32"
          },
          "currentCompetitorUsage": {
            "type": "integer",
            "format": "int32"
          },
          "maxCompetitorQuota": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "type": "string"
          },
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "currentPeriodEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "trialEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "billingModel": {
            "type": "string"
          },
          "maxDataPointsQuota": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "enforceDataPointQuota": {
            "type": "boolean"
          },
          "currentDataPointUsage": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "dataPointCycleStart": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "dataPointCycleEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceBillingItemDto": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "usagePlanName": {
            "type": "string"
          },
          "basePrice": {
            "type": "number",
            "format": "double"
          },
          "currentSkuUsage": {
            "type": "integer",
            "format": "int32"
          },
          "maxSkuQuota": {
            "type": "integer",
            "format": "int32"
          },
          "currentUserUsage": {
            "type": "integer",
            "format": "int32"
          },
          "maxUserQuota": {
            "type": "integer",
            "format": "int32"
          },
          "currentCompetitorUsage": {
            "type": "integer",
            "format": "int32"
          },
          "maxCompetitorQuota": {
            "type": "integer",
            "format": "int32"
          },
          "status": {
            "type": "string"
          },
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "currentPeriodEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "trialEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "billingModel": {
            "type": "string"
          },
          "maxDataPointsQuota": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "enforceDataPointQuota": {
            "type": "boolean"
          },
          "currentDataPointUsage": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          },
          "dataPointCycleStart": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "dataPointCycleEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceMembersDto": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.MemberDto"
            }
          },
          "pendingInvitations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.PendingInvitationDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceMembersItemDto": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.MemberDto"
            }
          },
          "pendingInvitations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Organization.PendingInvitationDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceSubscriptionDto": {
        "type": "object",
        "properties": {
          "workspaceId": {
            "type": "string"
          },
          "workspaceName": {
            "type": "string"
          },
          "subscriptionId": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "nullable": true
          },
          "usagePlanId": {
            "type": "string",
            "nullable": true
          },
          "usagePlanName": {
            "type": "string",
            "nullable": true
          },
          "trialEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "cancelAtPeriodEnd": {
            "type": "boolean"
          },
          "currentPeriodEnd": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "billingModel": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceSummaryDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "organizationId": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceSummaryDto2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "organizationId": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "currencyCode": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "countryCode": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Organization.WorkspaceUsageStatusDto": {
        "type": "object",
        "properties": {
          "planName": {
            "type": "string"
          },
          "skuUsage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsageLimitCheckResult"
          },
          "competitorUsage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsageLimitCheckResult"
          },
          "userUsage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsageLimitCheckResult"
          },
          "hasAnyLimitExceeded": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Overview.BasketAnalysisDTO": {
        "type": "object",
        "properties": {
          "customerStore": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.StoreDTO"
          },
          "rows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.BasketAnalysisRowDTO"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Overview.BasketAnalysisRowDTO": {
        "type": "object",
        "properties": {
          "retailer": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.StoreDTO"
          },
          "matches": {
            "type": "integer",
            "format": "int32"
          },
          "competitorBasket": {
            "type": "number",
            "format": "double"
          },
          "customerBasket": {
            "type": "number",
            "format": "double"
          },
          "variation": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.CompetitorPriceComparisonDTO": {
        "type": "object",
        "properties": {
          "competitorName": {
            "type": "string"
          },
          "competitorLogoUrl": {
            "type": "string"
          },
          "priceComparison": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.PriceComparisonDTO"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.CompetitorPriceComparisonTrendDTO": {
        "type": "object",
        "properties": {
          "competitor": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.StoreDTO"
          },
          "priceCounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.PriceCountDTO"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.CompetitorPriceInfoDTO": {
        "type": "object",
        "properties": {
          "competitorName": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "priceDifferencePercentage": {
            "type": "number",
            "format": "double"
          },
          "matchType": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "currency": {
            "type": "string"
          },
          "originalPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean"
          },
          "regularPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "promoPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "isOnPromotion": {
            "type": "boolean"
          },
          "is_marketplace": {
            "type": "boolean"
          },
          "is_third_party_seller": {
            "type": "boolean"
          },
          "seller_name": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.CompetitorPriceMatrixDTO": {
        "type": "object",
        "properties": {
          "competitorList": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.CompetitorPriceComparisonDTO"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Overview.CompetitorPriceTrendDTO": {
        "type": "object",
        "properties": {
          "competitor": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.StoreDTO"
          },
          "priceVariations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.PriceVariationDTO"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.CompetitorPriceTrendsDTO": {
        "type": "object",
        "properties": {
          "customerStore": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.StoreDTO"
          },
          "priceComparisonTrends": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.CompetitorPriceComparisonTrendDTO"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Overview.OverviewFiltersDTO": {
        "type": "object",
        "properties": {
          "scanDates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.ScanDateInfo"
            }
          },
          "competitors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "matchTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "customFields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CustomFields.CustomFieldFilterDto"
            }
          },
          "categoriesByDepartment": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "nullable": true
          },
          "subCategoriesByCategory": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "nullable": true
          },
          "owners": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "vendorDisplayNames": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.OverviewStatisticsDTO": {
        "type": "object",
        "properties": {
          "productsTracked": {
            "type": "integer",
            "format": "int32"
          },
          "competitors": {
            "type": "integer",
            "format": "int32"
          },
          "priceAlerts": {
            "type": "integer",
            "format": "int32"
          },
          "basketSavings": {
            "type": "number",
            "format": "double"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Overview.PriceComparisonDTO": {
        "type": "object",
        "properties": {
          "higherPriceCount": {
            "type": "integer",
            "format": "int32"
          },
          "lowerPriceCount": {
            "type": "integer",
            "format": "int32"
          },
          "equalPriceCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.PriceCountDTO": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string"
          },
          "higherPriceCount": {
            "type": "integer",
            "format": "int32"
          },
          "lowerPriceCount": {
            "type": "integer",
            "format": "int32"
          },
          "equalPriceCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.PriceTrendsDTO": {
        "type": "object",
        "properties": {
          "customerStore": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.StoreDTO"
          },
          "priceTrendsList": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.CompetitorPriceTrendDTO"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Overview.PriceVariationDTO": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string"
          },
          "variation": {
            "type": "number",
            "format": "double"
          },
          "basketPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "currency": {
            "type": "string"
          },
          "originalVariation": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.ProductPriceInfoDTO": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true
          },
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "category": {
            "type": "string"
          },
          "brand": {
            "type": "string"
          },
          "sku": {
            "type": "string"
          },
          "imageUrl": {
            "type": "string"
          },
          "customerPrice": {
            "type": "number",
            "format": "double"
          },
          "priceIsStale": {
            "type": "boolean"
          },
          "lastPriceFetchDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "currency": {
            "type": "string"
          },
          "originalCustomerPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "owner": {
            "type": "string",
            "nullable": true
          },
          "productUrl": {
            "type": "string",
            "nullable": true
          },
          "department": {
            "type": "string",
            "nullable": true
          },
          "competitorPrices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.CompetitorPriceInfoDTO"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.ProductPriceTableDTO": {
        "type": "object",
        "properties": {
          "totalProducts": {
            "type": "integer",
            "format": "int32"
          },
          "currentPage": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.Overview.ProductPriceInfoDTO"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.Overview.ScanDateInfo": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "scanDate": {
            "type": "string",
            "format": "date-time"
          },
          "startTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "status": {
            "type": "string"
          },
          "totalJobs": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "completedJobs": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "completionPercentage": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "mainVendorScanStatus": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Overview.StoreDTO": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PaginationDto": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "totalItems": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PriceEntryDto": {
        "required": [
          "scanId"
        ],
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "price": {
            "type": "number",
            "format": "float"
          },
          "currency": {
            "type": "string"
          },
          "originalPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean"
          },
          "priceIsStale": {
            "type": "boolean"
          },
          "lastPriceFetchDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "mainVendorScanStatus": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PriceTrendsDto": {
        "type": "object",
        "properties": {
          "priceTrends": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorPriceHistoryDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PriceTrendsDto2": {
        "type": "object",
        "properties": {
          "priceTrends": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorPriceHistoryDto"
            },
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.ProductDetailsDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductVariantDto"
            },
            "nullable": true
          },
          "metadata": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.MetadataTupleDto"
            },
            "nullable": true
          },
          "trackedStatus": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductFilterDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "weight": {
            "type": "string",
            "nullable": true
          },
          "weightUnit": {
            "type": "string",
            "nullable": true
          },
          "quantity": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "variant": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductMappings.AddTrackingRequestDto": {
        "required": [
          "sourceProductId",
          "targetProductId",
          "competitorVendorId"
        ],
        "type": "object",
        "properties": {
          "sourceProductId": {
            "type": "string"
          },
          "targetProductId": {
            "type": "string"
          },
          "competitorVendorId": {
            "type": "string"
          },
          "matchingType": {
            "type": "string",
            "nullable": true
          },
          "reason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductMappings.ScanJobStatusDto": {
        "type": "object",
        "properties": {
          "jobId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "scannedProductId": {
            "type": "string",
            "nullable": true
          },
          "createdMappingId": {
            "type": "string",
            "nullable": true
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          },
          "durationSeconds": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductMappings.ScanUrlForMappingRequestDto": {
        "required": [
          "sourceProductId",
          "competitorVendorId",
          "competitorProductUrl"
        ],
        "type": "object",
        "properties": {
          "sourceProductId": {
            "type": "string"
          },
          "competitorVendorId": {
            "type": "string"
          },
          "competitorProductUrl": {
            "type": "string",
            "format": "uri"
          },
          "matchingType": {
            "type": "string",
            "nullable": true
          },
          "reason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductMappings.SetPrimaryRequestDto": {
        "required": [
          "sourceProductId",
          "targetProductId",
          "competitorVendorId"
        ],
        "type": "object",
        "properties": {
          "sourceProductId": {
            "type": "string"
          },
          "targetProductId": {
            "type": "string"
          },
          "competitorVendorId": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductMappings.UpdateMappingRequest": {
        "required": [
          "sourceProductId",
          "targetProductId",
          "competitorVendorId"
        ],
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string",
            "nullable": true
          },
          "sourceProductId": {
            "type": "string"
          },
          "targetProductId": {
            "type": "string"
          },
          "competitorVendorId": {
            "type": "string"
          },
          "matchingType": {
            "type": "string",
            "nullable": true
          },
          "isSelected": {
            "type": "boolean",
            "nullable": true
          },
          "setUserExcluded": {
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductMappings.UpdateProductMappingRequest": {
        "required": [
          "sourceVendorId",
          "sourceProductId",
          "matchingType",
          "customerId"
        ],
        "type": "object",
        "properties": {
          "sourceVendorId": {
            "type": "string"
          },
          "sourceProductId": {
            "type": "string"
          },
          "targetVendorId": {
            "type": "string",
            "nullable": true
          },
          "targetProductId": {
            "type": "string",
            "nullable": true
          },
          "matchingType": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Entities.MatchingType"
          },
          "customerId": {
            "type": "string"
          },
          "productUrl": {
            "type": "string",
            "format": "uri",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductSearch.ProductSearchResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ProductSearch.ProductSearchResultDto"
            }
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductSearch.ProductSearchResultDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string"
          },
          "price": {
            "type": "string"
          },
          "imageUri": {
            "type": "string",
            "nullable": true
          },
          "productUrl": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "isAlreadyMapped": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ProductVariantDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PromoEventDetailDto": {
        "type": "object",
        "properties": {
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time"
          },
          "scanCount": {
            "type": "integer",
            "format": "int32"
          },
          "avgDiscountPct": {
            "type": "number",
            "format": "float"
          },
          "avgPrice": {
            "type": "number",
            "format": "float"
          },
          "promotionText": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PromotionBreakdownDto": {
        "type": "object",
        "properties": {
          "retailers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.RetailerPromotionBreakdownDto"
            }
          },
          "period": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PromotionFrequencyDto": {
        "type": "object",
        "properties": {
          "marketDiscountedScansPct": {
            "type": "number",
            "format": "float"
          },
          "discountingNowCount": {
            "type": "integer",
            "format": "int32"
          },
          "totalCompetitorCount": {
            "type": "integer",
            "format": "int32"
          },
          "belowYourPriceNowCount": {
            "type": "integer",
            "format": "int32"
          },
          "retailerPromotions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.RetailerPromotionDto"
            }
          },
          "period": {
            "type": "string"
          },
          "totalScansInPeriod": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.CheapestOptionDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "cheapestVendor": {
            "type": "string"
          },
          "cheapestPrice": {
            "type": "number",
            "format": "double"
          },
          "currency": {
            "type": "string"
          },
          "allOptions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PurchaseOptionDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.CompetitorCatalogDto": {
        "type": "object",
        "properties": {
          "competitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CompetitorDto"
            }
          },
          "message": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.CompetitorDto": {
        "type": "object",
        "properties": {
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string"
          },
          "productCount": {
            "type": "integer",
            "format": "int32"
          },
          "averagePrice": {
            "type": "number",
            "format": "double"
          },
          "pricingTrend": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.CompetitorOverviewDto": {
        "type": "object",
        "properties": {
          "totalTrackedProducts": {
            "type": "integer",
            "format": "int32"
          },
          "totalCompetitors": {
            "type": "integer",
            "format": "int32"
          },
          "productsBeingUndercut": {
            "type": "integer",
            "format": "int32"
          },
          "productsBelowMarket": {
            "type": "integer",
            "format": "int32"
          },
          "topCompetitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CompetitorSummaryDto"
            }
          },
          "unknownCompetitorUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.CompetitorPriceDto": {
        "type": "object",
        "properties": {
          "vendorName": {
            "type": "string"
          },
          "vendorId": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "currency": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "priceChange24h": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.CompetitorSummaryDto": {
        "type": "object",
        "properties": {
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string"
          },
          "overlappingProducts": {
            "type": "integer",
            "format": "int32"
          },
          "cheaperCount": {
            "type": "integer",
            "format": "int32"
          },
          "moreExpensiveCount": {
            "type": "integer",
            "format": "int32"
          },
          "averagePriceGapPercent": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.CostAnalysisDto": {
        "type": "object",
        "properties": {
          "analysisType": {
            "type": "string"
          },
          "optimizeFor": {
            "type": "string"
          },
          "includeShipping": {
            "type": "boolean"
          },
          "currency": {
            "type": "string"
          },
          "foundProductCount": {
            "type": "integer",
            "format": "int32"
          },
          "missingProductIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "recommendedOptions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CostAnalysisOptionDto"
            }
          },
          "vendorComparison": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.VendorCostSummaryDto"
            }
          },
          "subtotal": {
            "type": "number",
            "format": "double"
          },
          "shippingEstimate": {
            "type": "number",
            "format": "double"
          },
          "totalCost": {
            "type": "number",
            "format": "double"
          },
          "summary": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.CostAnalysisOptionDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string"
          },
          "unitPrice": {
            "type": "number",
            "format": "double"
          },
          "shippingEstimate": {
            "type": "number",
            "format": "double"
          },
          "totalPrice": {
            "type": "number",
            "format": "double"
          },
          "url": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.CostAnalysisRequestDto": {
        "type": "object",
        "properties": {
          "product_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "analysis_type": {
            "type": "string"
          },
          "include_shipping": {
            "type": "boolean"
          },
          "optimize_for": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.CustomerPortfolioPositionDto": {
        "type": "object",
        "properties": {
          "category": {
            "type": "string",
            "nullable": true
          },
          "timeframe": {
            "type": "string"
          },
          "totalTrackedProducts": {
            "type": "integer",
            "format": "int32"
          },
          "productsAnalyzed": {
            "type": "integer",
            "format": "int32"
          },
          "averagePercentileRank": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "averageGapToCheapest": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CustomerPositionDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.CustomerPositionDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "customerPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "marketAverage": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "percentileRank": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "gapToCheapest": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "gapToMostExpensive": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.CustomerPositionDto2": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "customerPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "marketAverage": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "percentileRank": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "gapToCheapest": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "gapToMostExpensive": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.CustomerProductDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "scanStatus": {
            "type": "string",
            "nullable": true
          },
          "lastScanDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "competitorCount": {
            "type": "integer",
            "format": "int32"
          },
          "currentPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "productUrl": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.InsightSummaryDto": {
        "type": "object",
        "properties": {
          "insightId": {
            "type": "string"
          },
          "insightType": {
            "type": "string"
          },
          "severity": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "productSku": {
            "type": "string",
            "nullable": true
          },
          "whatChanged": {
            "type": "string"
          },
          "whyItMatters": {
            "type": "string"
          },
          "recommendation": {
            "type": "string",
            "nullable": true
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.MarketInsightsDto": {
        "type": "object",
        "properties": {
          "category": {
            "type": "string"
          },
          "productCount": {
            "type": "integer",
            "format": "int32"
          },
          "averagePrice": {
            "type": "number",
            "format": "double"
          },
          "medianPrice": {
            "type": "number",
            "format": "double"
          },
          "priceRange": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceRangeDto"
          },
          "priceDistribution": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceDistributionBucketDto"
            }
          },
          "trendDirection": {
            "type": "string"
          },
          "trendPercentage": {
            "type": "number",
            "format": "double"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.PaginationMeta": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalCount": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "hasNextPage": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceChangeDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string"
          },
          "previousPrice": {
            "type": "number",
            "format": "double"
          },
          "currentPrice": {
            "type": "number",
            "format": "double"
          },
          "changeAmount": {
            "type": "number",
            "format": "double"
          },
          "changePercent": {
            "type": "number",
            "format": "double"
          },
          "direction": {
            "type": "string"
          },
          "detectedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceComparisonDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "competitors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CompetitorPriceDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceDataPointDto": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "currency": {
            "type": "string"
          },
          "vendorName": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceDistributionBucketDto": {
        "type": "object",
        "properties": {
          "rangeStart": {
            "type": "number",
            "format": "double"
          },
          "rangeEnd": {
            "type": "number",
            "format": "double"
          },
          "count": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceHistoryDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "vendorId": {
            "type": "string",
            "nullable": true
          },
          "dataPoints": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceDataPointDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceHistorySeriesDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "productName": {
            "type": "string"
          },
          "granularity": {
            "type": "string"
          },
          "from": {
            "type": "string",
            "format": "date-time"
          },
          "to": {
            "type": "string",
            "format": "date-time"
          },
          "currency": {
            "type": "string"
          },
          "byCompetitor": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceSeriesPointDto"
              }
            }
          },
          "tierCapApplied": {
            "type": "boolean"
          },
          "effectiveTierCapDays": {
            "type": "integer",
            "format": "int32"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceRangeDto": {
        "type": "object",
        "properties": {
          "min": {
            "type": "number",
            "format": "double"
          },
          "max": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PriceSeriesPointDto": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "averagePrice": {
            "type": "number",
            "format": "double"
          },
          "minPrice": {
            "type": "number",
            "format": "double"
          },
          "maxPrice": {
            "type": "number",
            "format": "double"
          },
          "observationCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.ProductSearchResultDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "currentPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "currency": {
            "type": "string"
          },
          "priceLastUpdated": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "competitorCount": {
            "type": "integer",
            "format": "int32"
          },
          "lowestPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "highestPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "averagePrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiError": {
        "type": "object",
        "properties": {
          "errorCode": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "details": {
            "type": "string",
            "nullable": true
          },
          "requestId": {
            "type": "string"
          },
          "documentationUrl": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCheapestOptionDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CheapestOptionDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorCatalogDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CompetitorCatalogDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCompetitorOverviewDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CompetitorOverviewDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCostAnalysisDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CostAnalysisDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPortfolioPositionDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CustomerPortfolioPositionDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfCustomerPositionDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CustomerPositionDto2"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfMarketInsightsDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.MarketInsightsDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceComparisonDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceComparisonDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistoryDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceHistoryDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceHistorySeriesDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceHistorySeriesDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfPriceTrendsDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PriceTrendsDto2"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfScanReportCsvDto": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.ScanReportCsvDto"
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfCustomerProductDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.CustomerProductDto"
            },
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfInsightSummaryDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.InsightSummaryDto"
            },
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfPriceChangeDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PriceChangeDto"
            },
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfProductSearchResultDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.ProductSearchResultDto"
            },
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PublicApiResponseOfSystem.Collections.Generic.ListOfScanResultDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.ScanResultDto"
            },
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PaginationMeta"
          },
          "error": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PublicApi.PublicApiError"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.PurchaseOptionDto": {
        "type": "object",
        "properties": {
          "vendorName": {
            "type": "string"
          },
          "vendorId": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "format": "double"
          },
          "currency": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.ScanReportCsvDto": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "contentType": {
            "type": "string"
          },
          "productCount": {
            "type": "integer",
            "format": "int32"
          },
          "competitorCount": {
            "type": "integer",
            "format": "int32"
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "csv": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.PublicApi.ScanResultDto": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "scanType": {
            "type": "string"
          },
          "totalJobs": {
            "type": "integer",
            "format": "int32"
          },
          "completedJobs": {
            "type": "integer",
            "format": "int32"
          },
          "successJobs": {
            "type": "integer",
            "format": "int32"
          },
          "failedJobs": {
            "type": "integer",
            "format": "int32"
          },
          "productCount": {
            "type": "integer",
            "format": "int32"
          },
          "startTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "endTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.PublicApi.VendorCostSummaryDto": {
        "type": "object",
        "properties": {
          "vendorId": {
            "type": "string"
          },
          "vendorName": {
            "type": "string"
          },
          "productCount": {
            "type": "integer",
            "format": "int32"
          },
          "subtotal": {
            "type": "number",
            "format": "double"
          },
          "shippingEstimate": {
            "type": "number",
            "format": "double"
          },
          "total": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WebAPIServer.Models.DTOs.RetailerPromotionBreakdownDto": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "integer",
            "format": "int32"
          },
          "retailerName": {
            "type": "string"
          },
          "averageDiscountDepthPct": {
            "type": "number",
            "format": "float"
          },
          "longestConsecutivePromoScans": {
            "type": "integer",
            "format": "int32"
          },
          "averagePromoDurationScans": {
            "type": "number",
            "format": "float"
          },
          "lowestPromoPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "averagePromoPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "promoEvents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.PromoEventDetailDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.RetailerPromotionDto": {
        "type": "object",
        "properties": {
          "competitorId": {
            "type": "integer",
            "format": "int32"
          },
          "retailerName": {
            "type": "string"
          },
          "isCurrentlyOnPromotion": {
            "type": "boolean"
          },
          "isCurrentlyBelowYourPrice": {
            "type": "boolean"
          },
          "discountedScansPct": {
            "type": "number",
            "format": "float"
          },
          "promoEventCount": {
            "type": "integer",
            "format": "int32"
          },
          "belowYourPriceEventCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ScanConfiguration.ActiveScanProgressDto": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "totalJobs": {
            "type": "integer",
            "format": "int32"
          },
          "completedJobs": {
            "type": "integer",
            "format": "int32"
          },
          "successJobs": {
            "type": "integer",
            "format": "int32"
          },
          "errorJobs": {
            "type": "integer",
            "format": "int32"
          },
          "completionPercentage": {
            "type": "number",
            "format": "double"
          },
          "startTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.ScanConfiguration.CustomScheduleDto": {
        "type": "object",
        "properties": {
          "activeDays": {
            "type": "array",
            "items": {
              "type": "integer",
              "format": "int32"
            },
            "nullable": true
          },
          "scanTimes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationErrorResponseDto": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationResponseDto": {
        "type": "object",
        "properties": {
          "isActive": {
            "type": "boolean"
          },
          "lastScanDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "nextScanDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "scanScheduleFrequency": {
            "type": "string"
          },
          "startDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "timeZone": {
            "type": "string"
          },
          "customSchedule": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.CustomScheduleDto"
          },
          "activeScanProgress": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ActiveScanProgressDto"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationSuccessResponseDto": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationResponseDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ScanConfiguration.ScanConfigurationUpdateRequestDto": {
        "type": "object",
        "properties": {
          "isActive": {
            "type": "boolean",
            "nullable": true
          },
          "scanScheduleFrequency": {
            "maxLength": 50,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "startDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "nextScanDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "timeZone": {
            "maxLength": 100,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "customSchedule": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.CustomScheduleDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ScanProfiles.CreateScanProfileDto": {
        "required": [
          "name",
          "frequency"
        ],
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "type": "string"
          },
          "frequency": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "startDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "isActive": {
            "type": "boolean"
          },
          "customSchedule": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.CustomScheduleDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ScanProfiles.ScanProfileDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "isActive": {
            "type": "boolean"
          },
          "isDefault": {
            "type": "boolean"
          },
          "frequency": {
            "type": "string"
          },
          "timezone": {
            "type": "string"
          },
          "nextScanDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastScanDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "startDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "linkedProductCount": {
            "type": "integer",
            "format": "int32"
          },
          "customSchedule": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.CustomScheduleDto"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.ScanProfiles.UpdateScanProfileDto": {
        "type": "object",
        "properties": {
          "name": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "frequency": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "startDateUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "isActive": {
            "type": "boolean",
            "nullable": true
          },
          "customSchedule": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.ScanConfiguration.CustomScheduleDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Scans.ScanHistoryPointDto": {
        "type": "object",
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "totalJobs": {
            "type": "integer",
            "format": "int32"
          },
          "durationSec": {
            "type": "number",
            "format": "double"
          },
          "successRate": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Scans.ScanStatisticsDto": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "progressPercent": {
            "type": "number",
            "format": "double"
          },
          "totalJobs": {
            "type": "integer",
            "format": "int32"
          },
          "completedJobs": {
            "type": "integer",
            "format": "int32"
          },
          "successJobs": {
            "type": "integer",
            "format": "int32"
          },
          "errorJobs": {
            "type": "integer",
            "format": "int32"
          },
          "startedAtUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "finishedAtUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "averageJobDurationSec": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "vendorBreakdown": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.StartDiscoveryRequestDTO": {
        "required": [
          "companyId"
        ],
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "maxProducts": {
            "maximum": 10000,
            "minimum": 1,
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "maxDepth": {
            "maximum": 20,
            "minimum": 1,
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.StartDiscoveryResponseDTO": {
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "crawlJobId": {
            "type": "string"
          },
          "discoveryStatus": {
            "type": "string"
          },
          "deadline": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.StaticImport.StaticImportItemResultDto": {
        "type": "object",
        "properties": {
          "sku": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "trackedProductId": {
            "type": "string",
            "nullable": true
          },
          "dataAsOf": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "priceChanged": {
            "type": "boolean"
          },
          "message": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.StaticImport.StaticImportProductDto": {
        "required": [
          "title",
          "sku"
        ],
        "type": "object",
        "properties": {
          "title": {
            "maxLength": 500,
            "minLength": 1,
            "type": "string"
          },
          "sku": {
            "maxLength": 200,
            "minLength": 1,
            "type": "string"
          },
          "basePrice": {
            "maximum": 100000000,
            "minimum": 0,
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "currency": {
            "maxLength": 3,
            "minLength": 3,
            "type": "string",
            "nullable": true
          },
          "imagePath": {
            "maxLength": 2048,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "description": {
            "maxLength": 4000,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "brand": {
            "maxLength": 256,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "category": {
            "maxLength": 256,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.StaticImport.StaticImportRequestDto": {
        "required": [
          "products"
        ],
        "type": "object",
        "properties": {
          "products": {
            "minItems": 1,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StaticImport.StaticImportProductDto"
            }
          },
          "overwriteExisting": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.StaticImport.StaticImportResultDto": {
        "type": "object",
        "properties": {
          "created": {
            "type": "integer",
            "format": "int32"
          },
          "updated": {
            "type": "integer",
            "format": "int32"
          },
          "failed": {
            "type": "integer",
            "format": "int32"
          },
          "conflicts": {
            "type": "integer",
            "format": "int32"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.StaticImport.StaticImportItemResultDto"
            }
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto": {
        "required": [
          "id",
          "sourceProductId",
          "targetProductId",
          "companyId",
          "matchingType",
          "confidence",
          "isSelected",
          "selectedByClient",
          "date",
          "isAnnotated",
          "classificationFlags"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "sourceProductId": {
            "type": "string"
          },
          "targetProductId": {
            "type": "string"
          },
          "targetProductName": {
            "type": "string",
            "nullable": true
          },
          "targetProductDescription": {
            "type": "string",
            "nullable": true
          },
          "targetProductPrice": {
            "type": "string",
            "nullable": true
          },
          "targetProductImageUri": {
            "type": "string",
            "nullable": true
          },
          "targetProductUrl": {
            "type": "string",
            "nullable": true
          },
          "targetProductBrand": {
            "type": "string",
            "nullable": true
          },
          "targetProductWeight": {
            "type": "string",
            "nullable": true
          },
          "targetProductWeightUnit": {
            "type": "string",
            "nullable": true
          },
          "targetProductQuantity": {
            "type": "string",
            "nullable": true
          },
          "targetProductVariant": {
            "type": "string",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "nullable": true
          },
          "originalPrice": {
            "type": "string",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean",
            "nullable": true
          },
          "companyId": {
            "type": "string"
          },
          "matchingType": {
            "type": "string"
          },
          "confidence": {
            "maximum": 100,
            "minimum": 0,
            "type": "integer",
            "format": "int32"
          },
          "isSelected": {
            "type": "boolean"
          },
          "selectedByClient": {
            "type": "boolean"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "selectedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "deselectedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "isAutoGenerated": {
            "type": "boolean",
            "nullable": true
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "isAnnotated": {
            "type": "boolean"
          },
          "classificationFlags": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Entities.Mapping.MappingClassificationFlags"
          },
          "isCompetitorActive": {
            "type": "boolean"
          },
          "userExcluded": {
            "type": "boolean"
          },
          "humanValidationStatus": {
            "type": "string",
            "nullable": true
          },
          "humanValidatedBy": {
            "type": "string",
            "nullable": true
          },
          "humanValidatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "redirectSourceUrl": {
            "type": "string",
            "nullable": true
          },
          "redirectResolvedUrl": {
            "type": "string",
            "nullable": true
          },
          "origin": {
            "type": "string",
            "nullable": true
          },
          "isPrimaryForStats": {
            "type": "boolean"
          },
          "isAdditionalTracking": {
            "type": "boolean"
          },
          "sourceProductPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "sourceProductCurrency": {
            "type": "string",
            "nullable": true
          },
          "sourceProductOriginalPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "sourceProductIsOutOfStock": {
            "type": "boolean",
            "nullable": true
          },
          "targetIsMarketplace": {
            "type": "boolean"
          },
          "targetIsThirdPartySeller": {
            "type": "boolean"
          },
          "targetSellerName": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingsListDto": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "totalMappings": {
            "type": "integer",
            "format": "int32"
          },
          "mappings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.SuggestedProductMappings.SuggestedProductMappingDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.SuggestedProductMappings.ValidateHumanMappingRequest": {
        "required": [
          "validated"
        ],
        "type": "object",
        "properties": {
          "validated": {
            "type": "boolean"
          },
          "companyId": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.BulkDeleteProductsDto": {
        "required": [
          "productIds"
        ],
        "type": "object",
        "properties": {
          "productIds": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.BulkDeleteResultDto": {
        "type": "object",
        "properties": {
          "successCount": {
            "type": "integer",
            "format": "int32"
          },
          "failureCount": {
            "type": "integer",
            "format": "int32"
          },
          "deletedProductIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "failedProductIds": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.BulkUpdateProductsDto": {
        "required": [
          "productIds"
        ],
        "type": "object",
        "properties": {
          "productIds": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "owner": {
            "maxLength": 256,
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "tracked": {
            "type": "boolean",
            "nullable": true
          },
          "updateOwner": {
            "type": "boolean"
          },
          "updateTags": {
            "type": "boolean"
          },
          "updateTracked": {
            "type": "boolean"
          },
          "scanProfileId": {
            "type": "string",
            "nullable": true
          },
          "updateScanProfile": {
            "type": "boolean"
          },
          "competitorOverrides": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "updateCompetitorOverrides": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.BulkUpdateResultDto": {
        "type": "object",
        "properties": {
          "successCount": {
            "type": "integer",
            "format": "int32"
          },
          "failureCount": {
            "type": "integer",
            "format": "int32"
          },
          "updatedProductIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "failedProductIds": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.CreateTrackedProductDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "originalSku": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "productUrl": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "price": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "metadata": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductMetadataDto"
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "tracked": {
            "type": "boolean"
          },
          "owner": {
            "maxLength": 256,
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "validationStatus": {
            "$ref": "#/components/schemas/NullableOfProductValidationStatus"
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.CsvUploadErrorDto": {
        "required": [
          "error"
        ],
        "type": "object",
        "properties": {
          "row": {
            "type": "integer",
            "format": "int32"
          },
          "productId": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.DistinctFieldValuesDto": {
        "type": "object",
        "properties": {
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "brands": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "owners": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "adHocFieldKeys": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.DuplicateProductInfoDto": {
        "required": [
          "productId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "csvRowNumber": {
            "type": "integer",
            "format": "int32"
          },
          "existingProductCreatedDate": {
            "type": "string",
            "format": "date-time"
          },
          "existingProductName": {
            "type": "string",
            "nullable": true
          },
          "existingProductBrand": {
            "type": "string",
            "nullable": true
          },
          "existingProductPrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.EditTrackedProductDto": {
        "required": [
          "id"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "productLink": {
            "type": "string",
            "nullable": true
          },
          "sourceUrl": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "tracked": {
            "type": "boolean",
            "nullable": true
          },
          "metadata": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductMetadataDto"
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "owner": {
            "maxLength": 256,
            "type": "string",
            "nullable": true
          },
          "originalSku": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "description": {
            "maxLength": 5000,
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "maxLength": 2048,
            "type": "string",
            "nullable": true
          },
          "scanProfileId": {
            "type": "string",
            "nullable": true
          },
          "updateScanProfile": {
            "type": "boolean"
          },
          "competitorOverrides": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "updateCompetitorOverrides": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.FieldConflictDto": {
        "required": [
          "fieldName"
        ],
        "type": "object",
        "properties": {
          "fieldName": {
            "type": "string"
          },
          "existingValue": {
            "type": "string",
            "nullable": true
          },
          "csvValue": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.MetricValueDto": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.PreflightBlockingIssueDto": {
        "required": [
          "code",
          "message"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "action": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.PreflightCapacityDto": {
        "type": "object",
        "properties": {
          "current": {
            "type": "integer",
            "format": "int32"
          },
          "afterImport": {
            "type": "integer",
            "format": "int32"
          },
          "limit": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "remaining": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.PreflightCountsDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "ready": {
            "type": "integer",
            "format": "int32"
          },
          "create": {
            "type": "integer",
            "format": "int32"
          },
          "update": {
            "type": "integer",
            "format": "int32"
          },
          "unchanged": {
            "type": "integer",
            "format": "int32"
          },
          "skip": {
            "type": "integer",
            "format": "int32"
          },
          "duplicate": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.ProductConflictInfoDto": {
        "required": [
          "productId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "csvRowNumber": {
            "type": "integer",
            "format": "int32"
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "conflicts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.FieldConflictDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.ProductEnrichmentInfoDto": {
        "required": [
          "productId"
        ],
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "csvRowNumber": {
            "type": "integer",
            "format": "int32"
          },
          "productName": {
            "type": "string",
            "nullable": true
          },
          "enrichedFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "trackedStatusUpdated": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.ProductMetadataDto": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": "integer",
            "format": "int32"
          },
          "weight": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.MetricValueDto"
          },
          "volume": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.MetricValueDto"
          },
          "length": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.MetricValueDto"
          },
          "units": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.UnitsInfoDto"
          },
          "variant": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.ProductStatusSummaryDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "integer",
            "format": "int32"
          },
          "counts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer",
              "format": "int32"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.ProductSuggestionDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "weight": {
            "type": "string",
            "nullable": true
          },
          "weightUnit": {
            "type": "string",
            "nullable": true
          },
          "quantity": {
            "type": "string",
            "nullable": true
          },
          "variant": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductBulkUploadResultDto": {
        "type": "object",
        "properties": {
          "totalRows": {
            "type": "integer",
            "format": "int32"
          },
          "successfullyCreated": {
            "type": "integer",
            "format": "int32"
          },
          "duplicates": {
            "type": "integer",
            "format": "int32"
          },
          "skipped": {
            "type": "integer",
            "format": "int32"
          },
          "errors": {
            "type": "integer",
            "format": "int32"
          },
          "duplicateProducts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.DuplicateProductInfoDto"
            }
          },
          "errorDetails": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.CsvUploadErrorDto"
            }
          },
          "uploadDate": {
            "type": "string",
            "format": "date-time"
          },
          "queuedForValidation": {
            "type": "integer",
            "format": "int32"
          },
          "queueSubmissionFailures": {
            "type": "integer",
            "format": "int32"
          },
          "productsRequiringManualValidation": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enrichedCount": {
            "type": "integer",
            "format": "int32"
          },
          "enrichedProducts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductEnrichmentInfoDto"
            }
          },
          "conflictCount": {
            "type": "integer",
            "format": "int32"
          },
          "conflictProducts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductConflictInfoDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductCsvAnalysisDto": {
        "type": "object",
        "properties": {
          "detectedColumns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "suggestedStandardMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "suggestedCustomFieldMappings": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "unmappedColumns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sampleRows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "totalRows": {
            "type": "integer",
            "format": "int32"
          },
          "mappingConfidence": {
            "type": "number",
            "format": "double"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "primaryVendorType": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Enums.PrimaryVendorType"
          },
          "requiredFields": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "requirementsMessage": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductCsvPreflightResultDto": {
        "type": "object",
        "properties": {
          "canImport": {
            "type": "boolean"
          },
          "blockingIssues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.PreflightBlockingIssueDto"
            }
          },
          "counts": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.PreflightCountsDto"
          },
          "capacity": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.PreflightCapacityDto"
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto": {
        "required": [
          "id",
          "companyId",
          "productId",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "productId": {
            "type": "string"
          },
          "originalSku": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "productLink": {
            "type": "string",
            "nullable": true
          },
          "sourceUrl": {
            "type": "string",
            "nullable": true
          },
          "resolvedUrl": {
            "type": "string",
            "nullable": true
          },
          "urlSourceType": {
            "type": "string",
            "nullable": true
          },
          "acquisitionMethod": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Enums.AcquisitionMethod"
          },
          "dataAsOf": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "tracked": {
            "type": "boolean"
          },
          "metadata": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductMetadataDto"
          },
          "timeAdded": {
            "type": "string",
            "format": "date-time"
          },
          "timeLastModified": {
            "type": "string",
            "format": "date-time"
          },
          "validationStatus": {
            "$ref": "#/components/schemas/NullableOfProductValidationStatus"
          },
          "validationDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "validationMessage": {
            "type": "string",
            "nullable": true
          },
          "urlStatus": {
            "type": "string",
            "nullable": true
          },
          "humanValidationStatus": {
            "type": "string",
            "nullable": true
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "imageOverrideUrl": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "vendorProductId": {
            "type": "string",
            "nullable": true
          },
          "owner": {
            "maxLength": 256,
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "scanProfileId": {
            "type": "string",
            "nullable": true
          },
          "competitorOverrides": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "productDetailsId": {
            "type": "string",
            "nullable": true
          },
          "lastScanStatus": {
            "type": "string",
            "nullable": true
          },
          "lastScanWarning": {
            "type": "string",
            "nullable": true
          },
          "lastScanIssueType": {
            "type": "string",
            "nullable": true
          },
          "lastScanDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "competitorDataAvailable": {
            "type": "boolean",
            "nullable": true
          },
          "priceIsStale": {
            "type": "boolean"
          },
          "lastPriceFetchDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto2": {
        "required": [
          "id",
          "companyId",
          "productId",
          "name"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "productId": {
            "type": "string"
          },
          "originalSku": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "productLink": {
            "type": "string",
            "nullable": true
          },
          "sourceUrl": {
            "type": "string",
            "nullable": true
          },
          "resolvedUrl": {
            "type": "string",
            "nullable": true
          },
          "urlSourceType": {
            "type": "string",
            "nullable": true
          },
          "acquisitionMethod": {
            "$ref": "#/components/schemas/WebAPIServer.Models.Enums.AcquisitionMethod"
          },
          "dataAsOf": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "tracked": {
            "type": "boolean"
          },
          "metadata": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductMetadataDto"
          },
          "timeAdded": {
            "type": "string",
            "format": "date-time"
          },
          "timeLastModified": {
            "type": "string",
            "format": "date-time"
          },
          "validationStatus": {
            "$ref": "#/components/schemas/NullableOfProductValidationStatus"
          },
          "validationDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "validationMessage": {
            "type": "string",
            "nullable": true
          },
          "urlStatus": {
            "type": "string",
            "nullable": true
          },
          "humanValidationStatus": {
            "type": "string",
            "nullable": true
          },
          "customFields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "imageOverrideUrl": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "vendorProductId": {
            "type": "string",
            "nullable": true
          },
          "owner": {
            "maxLength": 256,
            "type": "string",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "scanProfileId": {
            "type": "string",
            "nullable": true
          },
          "competitorOverrides": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "productDetailsId": {
            "type": "string",
            "nullable": true
          },
          "lastScanStatus": {
            "type": "string",
            "nullable": true
          },
          "lastScanWarning": {
            "type": "string",
            "nullable": true
          },
          "lastScanIssueType": {
            "type": "string",
            "nullable": true
          },
          "lastScanDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "competitorDataAvailable": {
            "type": "boolean",
            "nullable": true
          },
          "priceIsStale": {
            "type": "boolean"
          },
          "lastPriceFetchDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductsAutocompleteDto": {
        "type": "object",
        "properties": {
          "suggestions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.ProductSuggestionDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductsListDto": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32"
          },
          "totalProducts": {
            "type": "integer",
            "format": "int32"
          },
          "totalItems": {
            "type": "integer",
            "format": "int32"
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.TrackedProducts.TrackedProductDto"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.UnitsInfoDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "count": {
            "type": "string",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.TrackedProducts.UpdateTrackedProductAcquisitionMethodDto": {
        "type": "object",
        "properties": {
          "acquisitionMethod": {
            "$ref": "#/components/schemas/NullableOfAcquisitionMethod"
          },
          "productLink": {
            "maxLength": 2048,
            "type": "string",
            "nullable": true
          },
          "basePrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.TrackFromExplorationDto": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "vendorId": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UnitOfMeasurePriceEntryDto": {
        "required": [
          "scanId"
        ],
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "unitPrice": {
            "type": "number",
            "format": "float"
          },
          "currency": {
            "type": "string"
          },
          "originalUnitPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UnitOfMeasurePriceTrendsDto": {
        "type": "object",
        "properties": {
          "unitOfMeasure": {
            "type": "string",
            "nullable": true
          },
          "currencyType": {
            "type": "string",
            "nullable": true
          },
          "unitPriceTrends": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorUnitOfMeasurePriceHistoryDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UnitPriceEntryDto": {
        "required": [
          "scanId"
        ],
        "type": "object",
        "properties": {
          "scanId": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "unitPrice": {
            "type": "number",
            "format": "float"
          },
          "currency": {
            "type": "string"
          },
          "originalUnitPrice": {
            "type": "number",
            "format": "float",
            "nullable": true
          },
          "originalCurrency": {
            "type": "string",
            "nullable": true
          },
          "isOutOfStock": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UnitPriceTrendsDto": {
        "type": "object",
        "properties": {
          "unitPriceTrends": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.CompetitorUnitPriceHistoryDto"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.Usage.CompetitorUsageDto": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "usageType": {
            "type": "string",
            "nullable": true
          },
          "used": {
            "type": "integer",
            "format": "int32"
          },
          "max": {
            "type": "integer",
            "format": "int32"
          },
          "percentage": {
            "type": "number",
            "format": "double"
          },
          "exceedsLimit": {
            "type": "boolean"
          },
          "remaining": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Usage.SkuUsageDto": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "usageType": {
            "type": "string",
            "nullable": true
          },
          "used": {
            "type": "integer",
            "format": "int32"
          },
          "max": {
            "type": "integer",
            "format": "int32"
          },
          "percentage": {
            "type": "number",
            "format": "double"
          },
          "exceedsLimit": {
            "type": "boolean"
          },
          "remaining": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.Usage.UserUsageDto": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "usageType": {
            "type": "string",
            "nullable": true
          },
          "used": {
            "type": "integer",
            "format": "int32"
          },
          "max": {
            "type": "integer",
            "format": "int32"
          },
          "percentage": {
            "type": "number",
            "format": "double"
          },
          "exceedsLimit": {
            "type": "boolean"
          },
          "remaining": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.ChangeCompanyPlanRequestDto": {
        "required": [
          "usagePlanId"
        ],
        "type": "object",
        "properties": {
          "usagePlanId": {
            "type": "string"
          },
          "effectiveDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "preserveAddons": {
            "type": "boolean"
          },
          "notes": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.CompanyPlanUsageDto": {
        "type": "object",
        "properties": {
          "plan": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto2"
          },
          "skuUsage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsageStatsDto"
          },
          "competitorUsage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsageStatsDto"
          },
          "userUsage": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsageStatsDto"
          },
          "hasDailyRefreshAddon": {
            "type": "boolean"
          },
          "extraUsersCount": {
            "type": "integer",
            "format": "int32"
          },
          "lastUpdated": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.CompanySubscriptionDetailDto": {
        "type": "object",
        "properties": {
          "companyId": {
            "type": "string"
          },
          "companyName": {
            "type": "string"
          },
          "currentPlan": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto2"
          },
          "subscriptionStartDate": {
            "type": "string",
            "format": "date-time"
          },
          "hasDailyRefreshAddon": {
            "type": "boolean"
          },
          "dailyRefreshAddonStartDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "extraUsersCount": {
            "type": "integer",
            "format": "int32"
          },
          "extraCompetitorsCount": {
            "type": "integer",
            "format": "int32"
          },
          "extraSkusCount": {
            "type": "integer",
            "format": "int32"
          },
          "extraDataPointsCount": {
            "type": "integer",
            "format": "int32"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time"
          },
          "enableAdvancedFieldOverrides": {
            "type": "boolean"
          },
          "enforceDataPointQuota": {
            "type": "boolean"
          },
          "billingCycleStartDay": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.CreateCompanySubscriptionRequestDto": {
        "required": [
          "usagePlanId"
        ],
        "type": "object",
        "properties": {
          "usagePlanId": {
            "type": "string"
          },
          "subscriptionStartDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "hasDailyRefreshAddon": {
            "type": "boolean"
          },
          "extraUsersCount": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer",
            "format": "int32"
          },
          "extraCompetitorsCount": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer",
            "format": "int32"
          },
          "extraSkusCount": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer",
            "format": "int32"
          },
          "notes": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.PlanChangeValidationDto": {
        "type": "object",
        "properties": {
          "isValid": {
            "type": "boolean"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "hasUsageConflicts": {
            "type": "boolean"
          },
          "usageConflictDetails": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.PlanManagementResponseDto": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.UpdateCompanySubscriptionRequestDto": {
        "type": "object",
        "properties": {
          "hasDailyRefreshAddon": {
            "type": "boolean",
            "nullable": true
          },
          "extraUsersCount": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "extraCompetitorsCount": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "extraSkusCount": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "extraDataPointsCount": {
            "maximum": 2147483647,
            "minimum": 0,
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "effectiveDate": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "notes": {
            "maxLength": 500,
            "minLength": 0,
            "type": "string",
            "nullable": true
          },
          "enableAdvancedFieldOverrides": {
            "type": "boolean",
            "nullable": true
          },
          "enforceDataPointQuota": {
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.UsageLimitCheckResult": {
        "type": "object",
        "properties": {
          "isAllowed": {
            "type": "boolean"
          },
          "errorMessage": {
            "type": "string",
            "nullable": true
          },
          "currentUsage": {
            "type": "integer",
            "format": "int32"
          },
          "maxAllowed": {
            "type": "integer",
            "format": "int32"
          },
          "remainingCount": {
            "type": "integer",
            "format": "int32"
          },
          "upgradeMessage": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "planName": {
            "type": "string"
          },
          "maxSkus": {
            "type": "integer",
            "format": "int32"
          },
          "maxCompetitors": {
            "type": "integer",
            "format": "int32"
          },
          "maxUsers": {
            "type": "integer",
            "format": "int32"
          },
          "allowsAutomaticMatching": {
            "type": "boolean"
          },
          "allowsAIAnalyst": {
            "type": "boolean"
          },
          "allowsApiAccess": {
            "type": "boolean"
          },
          "allowsWeeklyRefresh": {
            "type": "boolean"
          },
          "dailyRefreshAddonPrice": {
            "type": "number",
            "format": "double"
          },
          "extraUserPrice": {
            "type": "number",
            "format": "double"
          },
          "extraCompetitorPrice": {
            "type": "number",
            "format": "double"
          },
          "extraSkuPrice": {
            "type": "number",
            "format": "double"
          },
          "basePrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "allowsMultiAgentChat": {
            "type": "boolean",
            "nullable": true
          },
          "maxMessagesPerConversation": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "maxChatConversationsPerUserPerMonth": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "maxDataPoints": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UsagePlans.UsagePlanDto2": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "planName": {
            "type": "string"
          },
          "maxSkus": {
            "type": "integer",
            "format": "int32"
          },
          "maxCompetitors": {
            "type": "integer",
            "format": "int32"
          },
          "maxUsers": {
            "type": "integer",
            "format": "int32"
          },
          "allowsAutomaticMatching": {
            "type": "boolean"
          },
          "allowsAIAnalyst": {
            "type": "boolean"
          },
          "allowsApiAccess": {
            "type": "boolean"
          },
          "allowsWeeklyRefresh": {
            "type": "boolean"
          },
          "dailyRefreshAddonPrice": {
            "type": "number",
            "format": "double"
          },
          "extraUserPrice": {
            "type": "number",
            "format": "double"
          },
          "extraCompetitorPrice": {
            "type": "number",
            "format": "double"
          },
          "extraSkuPrice": {
            "type": "number",
            "format": "double"
          },
          "basePrice": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "allowsMultiAgentChat": {
            "type": "boolean",
            "nullable": true
          },
          "maxMessagesPerConversation": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "maxChatConversationsPerUserPerMonth": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "maxDataPoints": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.UsagePlans.UsageStatsDto": {
        "type": "object",
        "properties": {
          "current": {
            "type": "integer",
            "format": "int32"
          },
          "max": {
            "type": "integer",
            "format": "int32"
          },
          "percentageUsed": {
            "type": "number",
            "format": "double"
          },
          "isNearLimit": {
            "type": "boolean"
          },
          "isOverLimit": {
            "type": "boolean"
          },
          "remaining": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.AddedUserDTO": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.UserManagement.AddUserRequestDTO": {
        "required": [
          "email",
          "role"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.AddUserResponseDTO": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "user": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.AddedUserDTO"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.AdminUpdateUserProfileRequestDTO": {
        "required": [
          "role"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          },
          "firstName": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "lastName": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "displayName": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          },
          "jobTitle": {
            "maxLength": 150,
            "type": "string",
            "nullable": true
          },
          "department": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "phoneNumber": {
            "maxLength": 30,
            "pattern": "^[+]?[\\d\\s\\-\\(\\)]{0,30}$",
            "type": "string",
            "nullable": true
          },
          "bio": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "username": {
            "maxLength": 50,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.CurrentUserDetailsDTO": {
        "type": "object",
        "properties": {
          "isFirstSignIn": {
            "type": "boolean"
          },
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "permissions": {
            "type": "string"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.UserManagement.CurrentUserResponseDTO": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "user": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.CurrentUserDetailsDTO"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.ErrorResponseDTO": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.SuccessResponseDTO": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.UpdateUserRoleRequestDTO": {
        "required": [
          "role"
        ],
        "type": "object",
        "properties": {
          "role": {
            "type": "string"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.UserDTO": {
        "type": "object",
        "properties": {
          "isFirstSignIn": {
            "type": "boolean"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "companyId": {
            "type": "string"
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.UserDTO[]": {
        "type": "array",
        "items": {
          "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserManagement.UserDTO"
        }
      },
      "WebAPIServer.Models.DTOs.UserManagement.UserProfileWithRoleDTO": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "firstName": {
            "type": "string",
            "nullable": true
          },
          "lastName": {
            "type": "string",
            "nullable": true
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "jobTitle": {
            "type": "string",
            "nullable": true
          },
          "department": {
            "type": "string",
            "nullable": true
          },
          "phoneNumber": {
            "type": "string",
            "nullable": true
          },
          "bio": {
            "type": "string",
            "nullable": true
          },
          "username": {
            "type": "string",
            "nullable": true
          },
          "lastModified": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO": {
        "type": "object",
        "properties": {
          "pricingInsights": {
            "type": "boolean"
          },
          "scanNotifications": {
            "type": "boolean"
          },
          "platformAlerts": {
            "type": "boolean"
          },
          "productUpdates": {
            "type": "boolean"
          },
          "tipsBestPractices": {
            "type": "boolean"
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO2": {
        "type": "object",
        "properties": {
          "pricingInsights": {
            "type": "boolean"
          },
          "scanNotifications": {
            "type": "boolean"
          },
          "platformAlerts": {
            "type": "boolean"
          },
          "productUpdates": {
            "type": "boolean"
          },
          "tipsBestPractices": {
            "type": "boolean"
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserProfile.UpdateNotificationPreferencesRequestDTO": {
        "type": "object",
        "properties": {
          "pricingInsights": {
            "type": "boolean",
            "nullable": true
          },
          "scanNotifications": {
            "type": "boolean",
            "nullable": true
          },
          "platformAlerts": {
            "type": "boolean",
            "nullable": true
          },
          "productUpdates": {
            "type": "boolean",
            "nullable": true
          },
          "tipsBestPractices": {
            "type": "boolean",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserProfile.UpdateUserProfileRequestDTO": {
        "type": "object",
        "properties": {
          "firstName": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "lastName": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "displayName": {
            "maxLength": 200,
            "type": "string",
            "nullable": true
          },
          "jobTitle": {
            "maxLength": 150,
            "type": "string",
            "nullable": true
          },
          "department": {
            "maxLength": 100,
            "type": "string",
            "nullable": true
          },
          "phoneNumber": {
            "maxLength": 30,
            "pattern": "^[+]?[\\d\\s\\-\\(\\)]{0,30}$",
            "type": "string",
            "nullable": true
          },
          "avatarUrl": {
            "maxLength": 500,
            "pattern": "^https?://.*$",
            "type": "string",
            "nullable": true
          },
          "bio": {
            "maxLength": 500,
            "type": "string",
            "nullable": true
          },
          "username": {
            "maxLength": 50,
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.DTOs.UserProfile.UserProfileDTO": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "firstName": {
            "type": "string",
            "nullable": true
          },
          "lastName": {
            "type": "string",
            "nullable": true
          },
          "displayName": {
            "type": "string",
            "nullable": true
          },
          "jobTitle": {
            "type": "string",
            "nullable": true
          },
          "department": {
            "type": "string",
            "nullable": true
          },
          "phoneNumber": {
            "type": "string",
            "nullable": true
          },
          "avatarUrl": {
            "type": "string",
            "nullable": true
          },
          "bio": {
            "type": "string",
            "nullable": true
          },
          "username": {
            "type": "string",
            "nullable": true
          },
          "profileUpdatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "linkedIdentityProviders": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "notificationPreferences": {
            "$ref": "#/components/schemas/WebAPIServer.Models.DTOs.UserProfile.NotificationPreferencesDTO"
          }
        }
      },
      "WebAPIServer.Models.Entities.Mapping.MappingClassificationFlags": {
        "required": [
          "perfect_match",
          "different_weight_or_volume",
          "different_quantity",
          "different_variant",
          "different_brand",
          "wrong_product"
        ],
        "type": "object",
        "properties": {
          "perfect_match": {
            "type": "boolean",
            "description": "Indicates perfect match"
          },
          "different_weight_or_volume": {
            "type": "boolean",
            "description": "Indicates different weight"
          },
          "different_quantity": {
            "type": "boolean",
            "description": "Indicates different quantity"
          },
          "different_variant": {
            "type": "boolean",
            "description": "Indicates different variant"
          },
          "different_brand": {
            "type": "boolean",
            "description": "Indicates different brand"
          },
          "wrong_product": {
            "type": "boolean",
            "description": "Indicates wrong product"
          }
        }
      },
      "WebAPIServer.Models.Entities.MatchingType": {
        "type": "integer"
      },
      "WebAPIServer.Models.Entities.Organization.Organization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "org_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "stripe_customer_id": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "_rid": {
            "type": "string",
            "nullable": true
          },
          "_self": {
            "type": "string",
            "nullable": true
          },
          "_etag": {
            "type": "string",
            "nullable": true
          },
          "_attachments": {
            "type": "string",
            "nullable": true
          },
          "_ts": {
            "type": "integer",
            "format": "int64",
            "nullable": true
          }
        },
        "nullable": true
      },
      "WebAPIServer.Models.Entities.ProductMapping": {
        "required": [
          "target_product_id",
          "customer_id",
          "matching_type",
          "date"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "source_product_id": {
            "type": "string"
          },
          "tracked_product_doc_id": {
            "type": "string",
            "nullable": true
          },
          "target_product_id": {
            "type": "string"
          },
          "source_vendor": {
            "type": "string"
          },
          "target_vendor": {
            "type": "string"
          },
          "customer_id": {
            "type": "string"
          },
          "matching_type": {
            "type": "string"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "candidates_fingerprint": {
            "type": "string",
            "nullable": true
          },
          "fingerprint_date": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WebAPIServer.Models.Entities.ProductSource": {
        "enum": [
          "ZyteScan",
          "UrlValidation",
          "OpenCrawl"
        ]
      },
      "WebAPIServer.Models.Enums.AcquisitionMethod": { },
      "WebAPIServer.Models.Enums.PrimaryVendorType": {
        "enum": [
          "VendorId",
          "Url",
          "Csv",
          "None"
        ]
      }
    },
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "description": "API key issued from the Nesika account dashboard. Send it in the X-API-Key request header.",
        "name": "X-API-Key",
        "in": "header"
      },
      "Bearer": {
        "type": "http",
        "description": "Azure AD (Entra) access token used by the Nesika web application. Send it as 'Authorization: Bearer <token>'.",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "tags": [
    {
      "name": "Product Matching",
      "description": "Search the catalog and resolve products so you can look up pricing by product. Start here when you have a name/identifier but not a Nesika product id."
    },
    {
      "name": "Price Monitoring",
      "description": "Read current and historical competitor prices. Use price-history/series/trends for time-series charting and backtesting; use the current-prices endpoint for a live snapshot."
    },
    {
      "name": "Pricing Actions",
      "description": "Run pricing computations such as landed-cost analysis to support pricing decisions."
    },
    {
      "name": "Competitor Intelligence",
      "description": "Browse the competitor/vendor catalog you are tracking."
    },
    {
      "name": "Market Insights",
      "description": "Aggregate market-level pricing signals across competitors."
    },
    {
      "name": "Account & Usage Data",
      "description": "Access data scoped to your own account: your tracked products, scans, price changes, and insight summaries."
    },
    {
      "name": "AIInsights",
      "description": "Generates AI-written weekly pricing insight reports for the authenticated workspace."
    },
    {
      "name": "AlertRules",
      "description": "Manages workspace alert rules that generate in-app and optional email notifications after scans."
    },
    {
      "name": "ApiKeys",
      "description": "Controller for managing API keys. Requires Azure AD (JWT) authentication only — API key auth is not allowed.\nUsers can generate, list, revoke, rotate, and update their own API keys within their active workspace."
    },
    {
      "name": "Chat",
      "description": "Provides authenticated AI chat, conversation management, agent discovery, configuration, streaming, and message-feedback endpoints."
    },
    {
      "name": "CompanyConfiguration",
      "description": "Manages company configuration for the authenticated user's active workspace."
    },
    {
      "name": "Company",
      "description": "Provides company data for the authenticated user's active workspace."
    },
    {
      "name": "CompetitorDetail",
      "description": "Provides the competitor detail workflow for retailer-level KPIs, matches, sensitivity analysis, insight cards, and product drawers."
    },
    {
      "name": "Competitors",
      "description": "Manages the authenticated workspace's competitor catalog and competitor usage limits."
    },
    {
      "name": "ContactRequest",
      "description": "Accepts public contact and demo requests from marketing forms."
    },
    {
      "name": "CsvConfiguration",
      "description": "Configures CSV column mappings for workspace-managed product and price uploads."
    },
    {
      "name": "CsvPrices",
      "description": "Uploads, lists, downloads, and deletes CSV-based price data for a workspace."
    },
    {
      "name": "CustomFields",
      "description": "Manages workspace-defined custom fields used to tag, filter, import, and display tracked products."
    },
    {
      "name": "Dashboard",
      "description": "Provides legacy dashboard summary, trend, and price-table data endpoints."
    },
    {
      "name": "DataPointsBilling",
      "description": "Provides customer-facing data-point billing usage, projection, trace, and scan-profile estimation endpoints."
    },
    {
      "name": "ExchangeRate",
      "description": "Provides authenticated access to cached foreign exchange rates used by pricing workflows."
    },
    {
      "name": "Exploration",
      "description": "Provides workspace-scoped product exploration across own products, competitor matches, and competitor catalog rows."
    },
    {
      "name": "Export",
      "description": "Generates authenticated workspace data exports for the Nesika web app export modal."
    },
    {
      "name": "ExportTemplate",
      "description": "Manages saved export modal templates for the authenticated user and active workspace."
    },
    {
      "name": "Feedback",
      "description": "Accepts authenticated product, data-quality, feature, and bug feedback from the Nesika web app."
    },
    {
      "name": "FilterLayout",
      "description": "Persists workspace filter order, visibility, and custom field filter layout for the web app."
    },
    {
      "name": "Insights",
      "description": "Manages Insight Card listing, detail, and user lifecycle actions for pricing recommendations."
    },
    {
      "name": "Notifications",
      "description": "Provides authenticated notification list, unread-count, read-state, and dismissal endpoints for the web app."
    },
    {
      "name": "Onboarding",
      "description": "Provides authenticated onboarding session, stage, discovery, validation, payment, tutorial, and crawl-discovery endpoints."
    },
    {
      "name": "Organizations",
      "description": "Manages organization, workspace, context-switching, billing, and member-report workflows for authenticated users."
    },
    {
      "name": "Overview",
      "description": "Provides market overview analytics, filter options, price matrices, trend charts, tables, and exports for the authenticated workspace."
    },
    {
      "name": "PlanManagement",
      "description": "Provides billing plan and workspace subscription endpoints for authenticated billing workflows."
    },
    {
      "name": "ProductDetails",
      "description": "Provides product detail, competitor pricing, trend, benchmark, promotion, and export data for product-analysis screens."
    },
    {
      "name": "ProductMapping",
      "description": "Manages source-to-competitor product mappings, manual match corrections, URL scan jobs, and validation workflows."
    },
    {
      "name": "ProductSearch",
      "description": "Searches competitor product catalogs for manual match selection and additional tracking workflows."
    },
    {
      "name": "ScanConfiguration",
      "description": "Manages the active workspace's global scan schedule and exposes active scan progress."
    },
    {
      "name": "ScanProfiles",
      "description": "Manages workspace scan profiles, which group tracked products onto independent scan schedules."
    },
    {
      "name": "Scans",
      "description": "Provides workspace-scoped scan analytics, history, and crawl-discovery status for the Nesika web app."
    },
    {
      "name": "TrackedProducts",
      "description": "Manages the workspace product catalog, including listing, filters, CRUD, validation, CSV import, static import, exports, and bulk operations."
    },
    {
      "name": "UserInvitations",
      "description": "Manages workspace invitations and invitation acceptance workflows."
    },
    {
      "name": "UserManagement",
      "description": "Manages current-user bootstrap data, workspace users, roles, profile administration, onboarding dismissal, and usage limits."
    },
    {
      "name": "UserProfile",
      "description": "Manages the authenticated user's personal profile and notification preferences."
    },
    {
      "name": "WebVitalsTelemetry",
      "description": "Ingestion endpoint for frontend Real User Monitoring (RUM) Web Vitals\nbeacons (Phase 0, measure-first; SDD\ndocs/design/2026-06-19-website-performance-remediation.md).\n\nThe frontend telemetry transport (apps/frontend/lib/telemetry) posts scrubbed\nmetrics here via navigator.sendBeacon (with a fetch keepalive fallback). The\nfrontend derives the URL from its API base (which already ends in \"/api\") plus\n\"/telemetry/web-vitals\", so the full path is POST /api/telemetry/web-vitals.\n\nResponsibilities are intentionally narrow: validate strictly, forward each\nvalid metric to Application Insights, and persist nothing. The endpoint is\nfire-and-forget; it returns 202 Accepted immediately and never fails the\ncaller because of a telemetry problem.\n\nSecurity: because navigator.sendBeacon cannot send an Authorization header,\nthe endpoint is `AllowAnonymousAttribute`. To compensate it is\nhardened with strict bounds (allowlisted metric names, bounded string lengths,\na bounded numeric range, a small maximum batch size, and a small request body\nsize limit) and accepts only the privacy whitelist. CORS is governed by the\napplication default policy (POST and Content-Type are allowed for the\nconfigured dev/test/prod origins), so this route is already covered."
    },
    {
      "name": "WorkspaceMemberships",
      "description": "Manages the authenticated user's workspace list, active workspace, workspace members, and workspace settings."
    }
  ]
}