{
  "openapi": "3.0.0",
  "info": {
    "title": "Selwise Public API",
    "version": "1.0",
    "description": "The merchant-facing API of Selwise: the bootstrap config, campaigns, recommendations, search, event ingest, orders, identity, consent and enrichment. `x-selwise-tier` separates the stable integration contract (`integration`) from widget and app-SDK traffic that evolves with the client protocol (`widget`). Human-readable documentation: https://selwise.com/docs/api-reference/public-api"
  },
  "servers": [
    {
      "url": "https://api.selwise.com/api/v1"
    }
  ],
  "paths": {
    "/public/sites/{siteKey}/campaigns": {
      "get": {
        "operationId": "PublicCampaignsController_getCampaigns",
        "summary": "Get active campaigns for a site",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language (`tr`, `en`…), matched to the account's languages; the default language otherwise.",
            "schema": {}
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignsResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/widgets": {
      "get": {
        "operationId": "PublicWidgetsController_getWidgets",
        "summary": "Deprecated: widgets merged into campaigns. Always returns an empty list.",
        "deprecated": true,
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WidgetsResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/scripts": {
      "get": {
        "operationId": "PublicScriptsController_getScripts",
        "summary": "Get active scripts for a site path",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "path",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScriptsResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/search": {
      "get": {
        "operationId": "PublicSearchController_search",
        "summary": "Search products for a site",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "q",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "minPrice",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxPrice",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inStock",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "device",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/search-config": {
      "get": {
        "operationId": "PublicSearchController_getSearchConfig",
        "summary": "Get search configuration for a site",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language (`tr`, `en`…), matched to the account's languages; the default language otherwise.",
            "schema": {}
          }
        ],
        "responses": {
          "200": {
            "description": "Widget rendering settings; the fields an integration reads are listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchConfigResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/search/suggestions": {
      "get": {
        "operationId": "PublicSearchController_getSearchSuggestions",
        "summary": "Get search suggestions for a site",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "device",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchSuggestionsResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/search/log": {
      "post": {
        "operationId": "PublicSearchController_logSearch",
        "summary": "Log a search query for analytics",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchLogBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/search/click": {
      "post": {
        "operationId": "PublicSearchController_trackSearchClick",
        "summary": "Track product click from search",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchClickBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/search/zero-results": {
      "post": {
        "operationId": "PublicSearchController_logZeroResultsSearch",
        "summary": "Log a zero-results search query for analytics",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchZeroResultsBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/recommendations": {
      "get": {
        "operationId": "PublicRecommendationsController_getRecommendationWidgets",
        "summary": "Get active recommendation widgets for a site",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "pageUrl",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language (`tr`, `en`…), matched to the account's languages; the default language otherwise.",
            "schema": {}
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicRecommendationsResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/recommendations/{widgetId}/products": {
      "post": {
        "operationId": "PublicRecommendationsController_getRecommendationProducts",
        "summary": "Get products for a recommendation widget",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "widgetId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecommendationProductsBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecommendationProductsResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-read-only": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/recommendations/track/event": {
      "post": {
        "operationId": "PublicRecommendationsController_trackRecommendationEvent",
        "summary": "Track recommendation event",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecommendationTrackEventBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "verified",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/recommendations/track/behavior": {
      "post": {
        "operationId": "PublicRecommendationsController_trackUserBehavior",
        "summary": "Track user behavior",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecommendationTrackBehaviorBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "verified",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/tracking-config": {
      "get": {
        "operationId": "PublicTrackingController_getTrackingConfig",
        "summary": "Get tracking configuration for a site",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrackingSettings"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/events/batch": {
      "post": {
        "operationId": "PublicTrackingController_trackEventsBatch",
        "summary": "Track events (batch) for a site",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrackPublicEventsBatchDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrackingBatchResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "verified",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/orders": {
      "post": {
        "operationId": "PublicOrdersController_ingestOrder",
        "summary": "Ingest an order/purchase for a site",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "x-selwise-client-platform",
            "required": false,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-client-version",
            "required": false,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicOrderIngestBody"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicOrderIngestResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/users/identify": {
      "post": {
        "operationId": "PublicUsersController_identifyUser",
        "summary": "Identify user and merge identity",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IdentifyPublicDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentifyResult"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/users/traits": {
      "post": {
        "operationId": "PublicUsersController_setUserTraits",
        "summary": "Set user traits/attributes",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetTraitsDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TraitsResult"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/consent": {
      "post": {
        "operationId": "PublicConsentController_saveConsent",
        "summary": "Save cookie consent state for a user",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveConsentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentSaveResult"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      },
      "delete": {
        "operationId": "PublicConsentController_withdrawConsent",
        "summary": "Withdraw cookie consent for a user (GDPR compliance)",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WithdrawConsentDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentWithdrawResult"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/integrations": {
      "get": {
        "operationId": "PublicIntegrationsController_getIntegrations",
        "summary": "Get the data layer settings for a site",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationsResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/product-metrics/view-count": {
      "get": {
        "operationId": "PublicProductMetricsController_getViewCount",
        "summary": "Get product view count for widget display",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "product",
            "required": true,
            "in": "query",
            "description": "Product SKU/item code",
            "schema": {
              "example": "SKU-12345",
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language, as on every public read. Nothing here is text, so it is accepted and unused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period",
            "required": false,
            "in": "query",
            "description": "Time period for counting views",
            "schema": {
              "enum": [
                "1h",
                "24h",
                "7d",
                "30d"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductMetricCount"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/product-metrics/cart-count": {
      "get": {
        "operationId": "PublicProductMetricsController_getCartCount",
        "summary": "Get cart count for widget display",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "product",
            "required": true,
            "in": "query",
            "description": "Product SKU/item code",
            "schema": {
              "example": "SKU-12345",
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language, as on every public read. Nothing here is text, so it is accepted and unused.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "metric",
            "required": false,
            "in": "query",
            "description": "Type of cart metric to return",
            "schema": {
              "enum": [
                "active_carts"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductMetricCount"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/product-metrics/batch": {
      "post": {
        "operationId": "PublicProductMetricsController_getBatchMetrics",
        "summary": "Get multiple product metrics in one request",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchMetricsDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Keyed by the `widgetId` each entry was asked under; `{}` when nothing was asked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/ProductMetricBatchEntry"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-read-only": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/config": {
      "get": {
        "operationId": "PublicConfigController_getSiteConfig",
        "summary": "Get complete site configuration in a single request",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "p",
            "required": false,
            "in": "query",
            "description": "The client protocol (`5` current). A campaign or page experiment this protocol cannot evaluate as written is withheld.",
            "schema": {}
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language (`tr`, `en`…), matched to the account's languages; the default language otherwise.",
            "schema": {}
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConfigResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/enrichments": {
      "get": {
        "operationId": "PublicEnrichmentController_getEnrichments",
        "summary": "Get enrichment content for one product code",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "code",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "test",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "capabilities",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrichmentResponseSchema"
                }
              }
            }
          },
          "402": {
            "description": "The account's plan does not include product enrichment (`MODULE_NOT_ENTITLED`). A client reads `enrichment.enabled` / `enrichment.keys` from `/config` first and does not call this when there is nothing to ask."
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/product-facts": {
      "get": {
        "operationId": "PublicEnrichmentController_getProductFacts",
        "summary": "Catalogue facts for one product code, for campaign placeholders",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "code",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductFactsSchema"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/app/enrichments": {
      "get": {
        "operationId": "PublicEnrichmentController_getAppEnrichments",
        "summary": "Rendered enrichment content for an app channel, by placement key",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "code",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slots",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "test",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "capabilities",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AppEnrichmentResponseSchema"
                }
              }
            }
          },
          "402": {
            "description": "The account's plan does not include product enrichment (`MODULE_NOT_ENTITLED`). A client reads `enrichment.enabled` / `enrichment.keys` from `/config` first and does not call this when there is nothing to ask."
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/ssr/recommendations/{widgetId}": {
      "get": {
        "operationId": "PublicSsrController_recommendations",
        "summary": "One recommendation strip as JSON for server-side rendering (server-to-server)",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "widgetId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SsrRecommendationResponseSchema"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 401 no key sent · 402 module not in the contract · 403 key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "ssr",
        "x-selwise-scope": "ssr_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/ssr/enrichments": {
      "get": {
        "operationId": "PublicSsrController_renderEnrichments",
        "summary": "Render enrichment slots for one product code as HTML (server-to-server)",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "code",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slots",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SsrEnrichmentResponseSchema"
                }
              }
            }
          },
          "304": {
            "description": "`If-None-Match` matched the digest (`v`)."
          },
          "402": {
            "description": "The account's plan does not include product enrichment (`MODULE_NOT_ENTITLED`). Answer the page without the slot: every shipped caller already treats a non-200 as empty."
          },
          "4XX": {
            "description": "400 invalid input · 401 no key sent · 402 module not in the contract · 403 key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "ssr",
        "x-selwise-scope": "ssr_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/reports/summary": {
      "get": {
        "operationId": "PublicReportsController_summary",
        "summary": "The channel's headline figures for a back office (server-to-server)",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "days",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportsSummaryResponseSchema"
                }
              }
            }
          },
          "4XX": {
            "description": "401 no key sent · 402 module not in the contract · 403 key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "reports",
        "x-selwise-scope": "reports_read",
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/newsletter": {
      "post": {
        "operationId": "PublicSiteNewsletterController_subscribe",
        "summary": "Record a newsletter signup from the newsletter widget",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSiteNewsletterStartDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessOnly"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/media/{assetKey}": {
      "get": {
        "operationId": "PublicMediaController_getAsset",
        "summary": "A library image (public).",
        "parameters": [
          {
            "name": "assetKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-none-match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The image bytes.",
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "301": {
            "description": "Stored in object storage: a permanent redirect to it."
          },
          "304": {
            "description": "`If-None-Match` matched."
          },
          "4XX": {
            "description": "400 invalid input · 404 not found · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "none",
        "x-selwise-playground": false
      }
    },
    "/public/media/{assetKey}/thumb": {
      "get": {
        "operationId": "PublicMediaController_getThumbnail",
        "summary": "A library image's thumbnail (public).",
        "parameters": [
          {
            "name": "assetKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "if-none-match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The thumbnail bytes.",
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "301": {
            "description": "Stored in object storage: a permanent redirect to it."
          },
          "304": {
            "description": "`If-None-Match` matched."
          },
          "4XX": {
            "description": "400 invalid input · 404 not found · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "none",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/contacts/consent": {
      "post": {
        "operationId": "PublicContactsConsentController_pushConsent",
        "summary": "Push marketing consent decisions for one or more contacts (server-to-server)",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushMarketingConsentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactConsentResult"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 401 no key sent · 403 key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "consent",
        "x-selwise-scope": "newsletter_subscribe",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/contacts/signup": {
      "post": {
        "operationId": "PublicSignupConsentController_recordSignupConsent",
        "summary": "Record the marketing permission ticked on a platform registration form",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSignupConsentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignupConsentResult"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/orders/{orderId}/status": {
      "post": {
        "operationId": "PublicOrderStatusController_updateStatus",
        "summary": "Report an order's status or refund after it was placed (server-to-server)",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "orderId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderStatusUpdateDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderStatusUpdateResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 401 no key sent · 403 key invalid or out of scope · 404 unknown channel key or order · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "orders",
        "x-selwise-scope": "orders_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/sites/{siteKey}/presence": {
      "post": {
        "operationId": "PublicPresenceController_heartbeat",
        "summary": "Keep a visitor live while the page or app is in use (heartbeat)",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicPresenceDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PresenceHeartbeatResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-dry-run": true,
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/scenarios/inbox": {
      "get": {
        "operationId": "PublicScenarioInboxController_list",
        "summary": "Pending on-site scenario deliveries for one visitor",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          },
          {
            "name": "visitorId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "testMode",
            "required": false,
            "in": "query",
            "description": "The visitor has `selwise_test_mode` set. Without it a test-mode scenario's claims are withheld.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "p",
            "required": false,
            "in": "query",
            "description": "The delivery protocol the client announces, as on `/config` (`?p=`). A claim whose campaign this client cannot draw stays pending instead of being served and closed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language (`tr`, `en`…), matched to the account's languages; the default language otherwise.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScenarioInboxResponseSchema"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_read",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/scenarios/inbox/ack": {
      "post": {
        "operationId": "PublicScenarioInboxController_acknowledge",
        "summary": "Report what the widget did with a delivery",
        "parameters": [
          {
            "name": "siteKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The channel key (Channels → Channel Overview → Channel Key). It names the channel and is not a secret."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScenarioInboxAckDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScenarioInboxAckResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/business-events": {
      "post": {
        "operationId": "BusinessEventsController_report",
        "summary": "Report an event from the merchant's own system",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-selwise-dry-run",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Authenticate and validate as the real call, then answer `{ dryRun: true, valid: true, request }` WITHOUT running the operation: nothing is written, recorded or queued. On an operation without dry-run support the header is a 400 (`DRY_RUN_UNSUPPORTED`), never a real write."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BusinessEventDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessEventResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 401 no key sent · 402 module not in the contract · 403 key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public"
        ],
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "business_events",
        "x-selwise-scope": "business_events_write",
        "x-selwise-dry-run": true,
        "x-selwise-playground": true
      }
    },
    "/public/segments/evaluate": {
      "post": {
        "operationId": "PublicSegmentsController_evaluateMultiple",
        "summary": "Which of the given segments the visitor is in",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvaluateMultipleSegmentsDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SegmentEvaluationResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 402 module not in the contract · 403 channel not verified, origin not allowed, key invalid or out of scope · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "security": [
          {
            "channelApiKey": []
          }
        ],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "site",
        "x-selwise-scope": "mobile_write",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/unsubscribe": {
      "get": {
        "operationId": "MessagingPublicController_unsubscribe",
        "summary": "Unsubscribe from a link in a message",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "t",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The confirmation page.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "messaging-public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-playground": false
      },
      "post": {
        "operationId": "MessagingPublicController_unsubscribePost",
        "summary": "One-click unsubscribe (RFC 8058)",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "t",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessOnly"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "messaging-public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/unsubscribe/resubscribe": {
      "post": {
        "operationId": "MessagingPublicController_resubscribe",
        "summary": "Resubscribe from the unsubscribe confirmation page",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "t",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The resubscribed (or invalid link) page.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "messaging-public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-playground": false
      }
    },
    "/public/messaging/{siteKey}/{providerId}/events": {
      "post": {
        "operationId": "MessagingPublicController_events",
        "summary": "Delivery events from a messaging provider",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "providerId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The provider's own delivery-event payload; its signature is verified per provider.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 404 not found · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "messaging-public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "none",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/push/subscribe": {
      "post": {
        "operationId": "MessagingPublicController_subscribe",
        "summary": "Record a browser push subscription",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushSubscribeDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessOnly"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "messaging-public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-playground": false
      }
    },
    "/public/sites/{siteKey}/push/unsubscribe": {
      "post": {
        "operationId": "MessagingPublicController_pushUnsubscribe",
        "summary": "Forget a browser push subscription",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PushUnsubscribeDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SuccessOnly"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "messaging-public"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-playground": false
      }
    },
    "/public/experiments/assign": {
      "get": {
        "operationId": "PublicExperimentsController_assignVariants",
        "summary": "Get variant assignments for a visitor",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "visitorId",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "p",
            "required": false,
            "in": "query",
            "description": "The `/config` protocol the client speaks (`CONFIG_PROTOCOL_CURRENT`), 1 when absent. A client below what an experiment's arms say or check (a placeholder in an override, a product condition, a variant module that needs more) is kept out of that experiment, in every arm.",
            "schema": {}
          },
          {
            "name": "capabilities",
            "required": false,
            "in": "query",
            "description": "What the client can honour, comma-separated. `holdout`: an arm flagged `holdout` draws nothing. `audience`: the client applies an arm, and counts the visitor, only where its `audience` (the experiment's own page, device, country, behaviour, segment and test-mode rules) matches. A client that does not declare one is kept out of every experiment that needs it.",
            "schema": {}
          },
          {
            "name": "forceVariant",
            "required": false,
            "in": "query",
            "description": "QA override, `<experimentId>:<variantId>`, repeatable. Bypasses the hash AND the traffic gate; the widget counts nothing for a forced arm.",
            "schema": {}
          },
          {
            "name": "lang",
            "required": false,
            "in": "query",
            "description": "The visitor's language (`tr`, `en`…), matched to the account's languages; the default language otherwise.",
            "schema": {}
          }
        ],
        "responses": {
          "200": {
            "description": "Keyed by experiment id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "$ref": "#/components/schemas/ExperimentAssignment"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "Public Experiments"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-playground": false
      }
    },
    "/public/experiments/track": {
      "post": {
        "operationId": "PublicExperimentsController_trackEvent",
        "summary": "Track experiment event",
        "parameters": [
          {
            "name": "siteKey",
            "required": true,
            "in": "query",
            "description": "Site key for tracking context",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrackExperimentEventDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExperimentTrackResponse"
                }
              }
            }
          },
          "4XX": {
            "description": "400 invalid input · 403 channel not verified · 404 unknown channel key · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "Public Experiments"
        ],
        "security": [],
        "x-selwise-tier": "widget",
        "x-selwise-auth": "verified",
        "x-selwise-playground": false
      }
    },
    "/public/feeds/{token}": {
      "post": {
        "operationId": "PublicFeedsController_updateFeed",
        "summary": "Update product feed via public API token",
        "parameters": [
          {
            "name": "token",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "string",
                "example": "<products><product><id>1</id>...</product></products>"
              }
            },
            "application/xml": {
              "schema": {
                "type": "string",
                "example": "<products><product><id>1</id>...</product></products>"
              }
            },
            "text/xml": {
              "schema": {
                "type": "string",
                "example": "<products><product><id>1</id>...</product></products>"
              }
            },
            "text/csv": {
              "schema": {
                "type": "string",
                "example": "<products><product><id>1</id>...</product></products>"
              }
            },
            "text/plain": {
              "schema": {
                "type": "string",
                "example": "<products><product><id>1</id>...</product></products>"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedPushResult"
                }
              }
            }
          },
          "4XX": {
            "description": "400 unreadable feed · 404 unknown feed token · 409 a sync of this feed is running · 413 too large · 429 rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "5XX": {
            "description": "503 pool exhausted or maintenance · 504 not finished in 30 seconds. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        },
        "tags": [
          "public-feeds"
        ],
        "security": [],
        "x-selwise-tier": "integration",
        "x-selwise-auth": "token",
        "x-selwise-playground": false
      }
    }
  },
  "components": {
    "securitySchemes": {
      "channelApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-selwise-api-key",
        "description": "A channel API key (`swpk_live_…`), created under Channels → API Keys. Each operation states the scope it needs in `x-selwise-scope`. On a WEB channel a browser request is authorised by its verified `Origin`/`Referer` instead, and when either header is present the key is not read at all — call from a server without them. An APP channel always needs the key. Purpose keys (`ssr_read`, `orders_write`, `newsletter_subscribe`, `business_events_write`, `reports_read`) are required whatever the headers."
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "required": [
          "statusCode",
          "timestamp",
          "path",
          "method",
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer",
            "example": 400
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "path": {
            "type": "string",
            "example": "/api/v1/public/sites/SITE_KEY/events/batch"
          },
          "method": {
            "type": "string",
            "example": "POST"
          },
          "message": {
            "type": "string",
            "description": "For people. A program reads `code`, never this sentence."
          },
          "error": {
            "type": "string",
            "description": "The HTTP reason phrase (`Bad Request`)."
          },
          "code": {
            "type": "string",
            "description": "Stable SCREAMING_SNAKE name on a coded error (`MODULE_NOT_ENTITLED`, `CHANNEL_NOT_VERIFIED`)."
          },
          "params": {
            "type": "object",
            "additionalProperties": true,
            "description": "The values of a coded error."
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Validation only: `field.path: reason` lines.",
            "example": [
              "events.0.name: name must be a string"
            ]
          },
          "retryAfterSeconds": {
            "type": "integer",
            "description": "On a 503 `DB_POOL_EXHAUSTED`; also sent as `Retry-After`."
          }
        }
      },
      "AppEnrichmentItemSchema": {
        "type": "object",
        "properties": {
          "assignmentId": {
            "type": "string"
          },
          "placementKey": {
            "type": "string",
            "example": "pdp-specs",
            "description": "The named slot; an app places by name, never by selector."
          },
          "order": {
            "type": "number"
          },
          "html": {
            "type": "string",
            "description": "Interpolated, sanitised markup for the whole rule."
          },
          "css": {
            "type": "string",
            "description": "Sanitised CSS scoped to the rule's blocks; `''` when none."
          },
          "reservedHeightPx": {
            "type": "number"
          },
          "segmentTargetingMode": {
            "type": "string"
          },
          "segmentIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "isTestMode": {
            "type": "boolean"
          },
          "conflictBehavior": {
            "type": "string",
            "enum": [
              "exclusive"
            ],
            "description": "Only when the rule is `exclusive`: if it is the first rule left in its slot after segment and test-mode targeting, it keeps the slot's other rules off the screen. Absent means the rule stacks."
          }
        },
        "required": [
          "assignmentId",
          "placementKey",
          "order",
          "html",
          "css"
        ]
      },
      "AppEnrichmentResponseSchema": {
        "type": "object",
        "properties": {
          "v": {
            "type": "string",
            "example": "m3k1p.4"
          },
          "code": {
            "type": "string",
            "example": "SKU-12345"
          },
          "resolved": {
            "type": "boolean",
            "description": "The catalogue carried the code (tokens resolved)."
          },
          "slots": {
            "example": [
              "pdp-specs",
              "pdp-shipping"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AppEnrichmentItemSchema"
            }
          }
        },
        "required": [
          "v",
          "code",
          "resolved",
          "slots",
          "items"
        ]
      },
      "BatchMetricsDto": {
        "type": "object",
        "properties": {
          "products": {
            "description": "Array of products with their widget configurations",
            "minItems": 1,
            "maxItems": 50,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BatchProductItemDto"
            }
          }
        },
        "required": [
          "products"
        ]
      },
      "BatchProductConfigDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "product_view_count",
              "cart_count"
            ]
          },
          "timePeriod": {
            "type": "string",
            "enum": [
              "1h",
              "24h",
              "7d",
              "30d"
            ],
            "example": "24h"
          },
          "metricType": {
            "type": "string",
            "enum": [
              "active_carts"
            ]
          }
        },
        "required": [
          "type"
        ]
      },
      "BatchProductItemDto": {
        "type": "object",
        "properties": {
          "itemCode": {
            "type": "string",
            "description": "Product item code",
            "example": "SKU-12345"
          },
          "widgetId": {
            "type": "string",
            "description": "Your own key for this entry. The response is keyed by it, so two entries for the same product (a view count and a cart count) each get their own answer.",
            "example": "widget-uuid-123"
          },
          "config": {
            "description": "Which count this entry asks for",
            "allOf": [
              {
                "$ref": "#/components/schemas/BatchProductConfigDto"
              }
            ]
          }
        },
        "required": [
          "itemCode",
          "widgetId",
          "config"
        ]
      },
      "BusinessEventDto": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "maxLength": 60,
            "pattern": "^[a-zA-Z0-9_.-]+$",
            "example": "shipment_dispatched"
          },
          "siteUserId": {
            "type": "string",
            "maxLength": 64,
            "example": "member-42"
          },
          "visitorId": {
            "type": "string",
            "maxLength": 64
          },
          "payload": {
            "type": "object",
            "additionalProperties": true
          },
          "testMode": {
            "type": "boolean"
          }
        },
        "required": [
          "key"
        ]
      },
      "BusinessEventResponse": {
        "type": "object",
        "properties": {
          "accepted": {
            "type": "boolean",
            "description": "False when the channel cannot run scenarios."
          },
          "scenarios": {
            "type": "number",
            "description": "How many published scenarios this event may start.",
            "example": 1
          }
        },
        "required": [
          "accepted",
          "scenarios"
        ]
      },
      "CampaignsResponse": {
        "type": "object",
        "properties": {
          "campaigns": {
            "description": "Every campaign whose schedule window is open now (Europe/Istanbul), test-mode ones included.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCampaign"
            }
          }
        },
        "required": [
          "campaigns"
        ]
      },
      "CardSwatchSchema": {
        "type": "object",
        "properties": {
          "itemCode": {
            "type": "string"
          },
          "color": {
            "type": "string"
          },
          "imageUrl": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "itemCode"
        ]
      },
      "ConfigChannel": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "web",
              "app"
            ]
          },
          "sharedCatalog": {
            "type": "boolean",
            "description": "The channel reads another channel's catalogue."
          },
          "currency": {
            "type": "string",
            "nullable": true,
            "example": "TRY"
          }
        },
        "required": [
          "type",
          "sharedCatalog",
          "currency"
        ]
      },
      "ConfigControlGroup": {
        "type": "object",
        "properties": {
          "percent": {
            "type": "number",
            "example": 10,
            "description": "Share of visitors held out of every surface."
          },
          "channelId": {
            "type": "string",
            "format": "uuid",
            "description": "Hashed with the visitor id to decide membership."
          }
        },
        "required": [
          "percent",
          "channelId"
        ]
      },
      "ConfigEnrichment": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "v": {
            "type": "object",
            "description": "Digest stamp; changes whenever a rule or block changes."
          },
          "slots": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Selectors the widget watches for enrichment content (`s` selector, `p` position, `h` reserved height, `k` keys)."
          },
          "keys": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "enabled",
          "slots",
          "keys"
        ]
      },
      "ConfigLocale": {
        "type": "object",
        "properties": {
          "default": {
            "type": "string",
            "example": "tr"
          },
          "available": {
            "example": [
              "tr",
              "en"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "default",
          "available"
        ]
      },
      "ConfigOnsite": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "experiments": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "required": [
          "enabled",
          "experiments"
        ]
      },
      "ConfigResponse": {
        "type": "object",
        "properties": {
          "modules": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            },
            "description": "Which modules the account has. A surface whose module is missing is sent empty.",
            "example": {
              "web_experience": true,
              "recommendations": true,
              "search": true,
              "product_enrichment": false
            }
          },
          "channel": {
            "$ref": "#/components/schemas/ConfigChannel"
          },
          "controlGroup": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/ConfigControlGroup"
              }
            ]
          },
          "campaigns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicCampaign"
            }
          },
          "widgets": {
            "type": "array",
            "items": {},
            "maxItems": 0,
            "description": "Always empty: widgets merged into campaigns."
          },
          "recommendations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicRecommendationWidgetSchema"
            }
          },
          "tracking": {
            "$ref": "#/components/schemas/TrackingSettings"
          },
          "search": {
            "$ref": "#/components/schemas/ConfigSearch"
          },
          "enrichment": {
            "$ref": "#/components/schemas/ConfigEnrichment"
          },
          "onsite": {
            "$ref": "#/components/schemas/ConfigOnsite"
          },
          "prehide": {
            "type": "object",
            "additionalProperties": true,
            "description": "Internal to the widget: what the next page hides before it paints and the CSS it paints directly. Stored on the device and read by the head bootstrap; it names surfaces, never the visitor."
          },
          "scenarios": {
            "$ref": "#/components/schemas/ConfigScenarios"
          },
          "webPush": {
            "$ref": "#/components/schemas/ConfigWebPush"
          },
          "theme": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Brand tokens (`--selwise-*`)."
          },
          "locale": {
            "$ref": "#/components/schemas/ConfigLocale"
          }
        },
        "required": [
          "modules",
          "channel",
          "controlGroup",
          "campaigns",
          "widgets",
          "recommendations",
          "tracking",
          "search",
          "enrichment",
          "onsite",
          "prehide",
          "scenarios",
          "webPush",
          "theme",
          "locale"
        ]
      },
      "ConfigScenarios": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean",
            "description": "A scenario may deliver on-site: poll `/scenarios/inbox`."
          }
        },
        "required": [
          "enabled"
        ]
      },
      "ConfigSearch": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "isTestMode": {
            "type": "boolean"
          }
        },
        "required": [
          "enabled",
          "isTestMode"
        ]
      },
      "ConfigWebPush": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "publicKey": {
            "type": "string",
            "nullable": true,
            "description": "VAPID public key."
          },
          "prompt": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          }
        },
        "required": [
          "enabled",
          "publicKey",
          "prompt"
        ]
      },
      "ConsentClientAction": {
        "type": "object",
        "properties": {
          "clearLocalStorage": {
            "type": "boolean"
          },
          "storageKey": {
            "type": "string",
            "example": "selwise_consent"
          },
          "clearCookies": {
            "type": "boolean"
          },
          "cookiePattern": {
            "type": "string",
            "example": "_selwise_"
          }
        },
        "required": [
          "clearLocalStorage",
          "storageKey",
          "clearCookies",
          "cookiePattern"
        ]
      },
      "ConsentSaveResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "error": {
            "type": "string",
            "example": "Site not verified",
            "description": "Why `success` is false. The status is still 2xx."
          }
        },
        "required": [
          "success"
        ]
      },
      "ConsentWithdrawResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string",
            "example": "Consent withdrawn successfully"
          },
          "clientAction": {
            "description": "What the client should erase on its side.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ConsentClientAction"
              }
            ]
          },
          "error": {
            "type": "string",
            "example": "visitorId or siteUserId required"
          }
        },
        "required": [
          "success"
        ]
      },
      "ContactConsentEntryResult": {
        "type": "object",
        "properties": {
          "index": {
            "type": "number",
            "description": "Position of the entry in the request."
          },
          "status": {
            "type": "string",
            "enum": [
              "subscribed",
              "resubscribed",
              "unsubscribed",
              "withdrawal_recorded",
              "unchanged",
              "not_found",
              "invalid",
              "failed"
            ]
          }
        },
        "required": [
          "index",
          "status"
        ]
      },
      "ContactConsentResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "received": {
            "type": "number",
            "example": 3
          },
          "processed": {
            "type": "number",
            "example": 3,
            "description": "Entries that were not `invalid`, `not_found` or `failed`."
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContactConsentEntryResult"
            }
          }
        },
        "required": [
          "success",
          "received",
          "processed",
          "results"
        ]
      },
      "DataLayerSettings": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "variableName": {
            "type": "string",
            "example": "selwiseLayer"
          },
          "externalDataLayerName": {
            "type": "string",
            "example": "dataLayer"
          },
          "platform": {
            "type": "string",
            "example": "generic"
          },
          "useExternalDataLayer": {
            "type": "boolean"
          },
          "testMode": {
            "type": "boolean"
          }
        },
        "required": [
          "enabled"
        ]
      },
      "EnrichmentBlockSchema": {
        "type": "object",
        "properties": {
          "blockId": {
            "type": "string"
          },
          "html": {
            "type": "string",
            "description": "Merchant HTML; the widget sanitises it before it reaches the DOM."
          },
          "css": {
            "type": "string",
            "description": "Merchant CSS, scoped to the block's root by the widget."
          },
          "reservedHeightPx": {
            "type": "number"
          }
        },
        "required": [
          "blockId",
          "html"
        ]
      },
      "EnrichmentItemSchema": {
        "type": "object",
        "properties": {
          "assignmentId": {
            "type": "string"
          },
          "selector": {
            "type": "string",
            "example": ".product-description"
          },
          "insertPosition": {
            "type": "string",
            "example": "after"
          },
          "placementKey": {
            "type": "string",
            "description": "Only on the server-side render path."
          },
          "order": {
            "type": "number",
            "description": "Render order within a selector; ascending."
          },
          "blocks": {
            "description": "In render order; never empty.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnrichmentBlockSchema"
            }
          },
          "segmentTargetingMode": {
            "type": "string"
          },
          "segmentIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "isTestMode": {
            "type": "boolean"
          },
          "deviceVisibility": {
            "type": "string",
            "enum": [
              "desktop",
              "mobile"
            ],
            "description": "Only when the rule is for one device: `mobile` (a viewport below 768px) or `desktop`. Absent means every device."
          },
          "conflictBehavior": {
            "type": "string",
            "enum": [
              "exclusive"
            ],
            "description": "Only when the rule is `exclusive`: if it wins its placement it keeps the placement's other rules off the page. The response ships every candidate a segment or a device could still remove, so the widget applies this once it knows who is looking. Absent means the rule stacks."
          }
        },
        "required": [
          "assignmentId",
          "selector",
          "insertPosition",
          "order",
          "blocks"
        ]
      },
      "EnrichmentResponseSchema": {
        "type": "object",
        "properties": {
          "v": {
            "type": "string",
            "example": "m3k1p.4",
            "description": "Digest stamp; changes whenever a rule or block changes."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnrichmentItemSchema"
            }
          },
          "tokens": {
            "type": "object",
            "additionalProperties": true,
            "description": "Product values for `${token}` interpolation (`code`, `title`, `price`, `currency`, `attrs`…).",
            "example": {
              "code": "SKU-12345",
              "title": "Ürün Adı",
              "price": 199.9,
              "currency": "TRY",
              "inStock": true
            }
          }
        },
        "required": [
          "v",
          "items",
          "tokens"
        ]
      },
      "EvaluateMultipleSegmentsDto": {
        "type": "object",
        "properties": {
          "visitorId": {
            "type": "string",
            "description": "Visitor ID from client storage"
          },
          "siteUserId": {
            "type": "string",
            "description": "Logged-in user ID from the site"
          },
          "siteUserProfileId": {
            "type": "string",
            "description": "Internal SiteUser profile ID (UUID) for merged behavior lookup after identify"
          },
          "sessionId": {
            "type": "string",
            "description": "Session ID for tracking"
          },
          "deviceType": {
            "type": "string",
            "description": "Device type: desktop, mobile, or tablet"
          },
          "referrer": {
            "type": "string",
            "description": "Referrer URL"
          },
          "pageUrl": {
            "type": "string",
            "description": "Current page URL"
          },
          "segmentIds": {
            "description": "Array of segment IDs to evaluate",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "segmentIds"
        ]
      },
      "ExperimentAssignment": {
        "type": "object",
        "properties": {
          "experimentId": {
            "type": "string",
            "format": "uuid"
          },
          "variantId": {
            "type": "string"
          },
          "variantName": {
            "type": "string"
          },
          "experimentMode": {
            "type": "string"
          },
          "isForced": {
            "type": "boolean",
            "description": "Set by `forceVariant`; nothing is counted for a forced arm."
          },
          "holdout": {
            "type": "boolean",
            "description": "The control arm: draw nothing (needs `capabilities=holdout`)."
          },
          "hasHoldout": {
            "type": "boolean"
          },
          "liveCartRequired": {
            "type": "boolean"
          },
          "audience": {
            "type": "object",
            "additionalProperties": true,
            "description": "The arm's own audience, judged by the client per page (needs `capabilities=audience`)."
          }
        },
        "required": [
          "experimentId",
          "variantId",
          "variantName",
          "experimentMode"
        ]
      },
      "ExperimentTrackResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "reason": {
            "type": "string",
            "example": "test_mode",
            "description": "Why nothing was counted."
          }
        },
        "required": [
          "success"
        ]
      },
      "FeedPushResult": {
        "type": "object",
        "properties": {
          "productCount": {
            "type": "number",
            "example": 18432,
            "description": "Products in the catalogue after the run."
          },
          "rowsRead": {
            "type": "number",
            "example": 18500
          },
          "rowsSkipped": {
            "type": "number",
            "example": 68
          },
          "productsCreated": {
            "type": "number",
            "example": 120
          },
          "productsUpdated": {
            "type": "number",
            "example": 940,
            "description": "Rows whose content changed."
          },
          "productsUnchanged": {
            "type": "number",
            "example": 17372,
            "description": "Rows identical to the stored product; nothing was written."
          },
          "productsRemoved": {
            "type": "number",
            "example": 12,
            "description": "Removed because absent from a COMPLETE read."
          },
          "skippedSamples": {
            "description": "The first few rejections.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FeedSkippedSample"
            }
          },
          "catalogSignals": {
            "type": "object",
            "additionalProperties": true,
            "description": "Price drops and restocks the run observed, for scenarios. Diagnostic; its shape may change."
          }
        },
        "required": [
          "productCount",
          "rowsRead",
          "rowsSkipped",
          "productsCreated",
          "productsUpdated",
          "productsUnchanged",
          "productsRemoved",
          "skippedSamples",
          "catalogSignals"
        ]
      },
      "FeedSkippedSample": {
        "type": "object",
        "properties": {
          "itemCode": {
            "type": "string",
            "example": "SKU-9"
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "itemCode",
          "reason"
        ]
      },
      "GeoHint": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "example": "TR",
            "description": "ISO 3166 country from the edge's geo headers."
          }
        },
        "required": [
          "country"
        ]
      },
      "IdentifiedUser": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "externalId": {
            "type": "string",
            "example": "MUSTERI-1001",
            "description": "Your customer id."
          },
          "firstSeenAt": {
            "format": "date-time",
            "type": "string"
          },
          "lastSeenAt": {
            "format": "date-time",
            "type": "string"
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "plan": "premium"
            }
          }
        },
        "required": [
          "id",
          "externalId",
          "firstSeenAt",
          "lastSeenAt"
        ]
      },
      "IdentifyPublicDto": {
        "type": "object",
        "properties": {
          "externalId": {
            "type": "string",
            "description": "Merchant's user ID (external ID)",
            "maxLength": 64,
            "example": "MUSTERI-1001"
          },
          "visitorId": {
            "type": "string",
            "description": "Current visitor ID from client",
            "example": "VISITOR_ID"
          },
          "sessionId": {
            "type": "string",
            "description": "Current session ID from client"
          },
          "email": {
            "type": "string",
            "description": "User email (will be hashed for storage)"
          },
          "traits": {
            "type": "object",
            "description": "User traits/attributes"
          },
          "pageUrl": {
            "type": "string",
            "description": "Page URL where identify was called"
          },
          "userAgent": {
            "type": "string",
            "description": "User agent string"
          },
          "userHash": {
            "type": "string",
            "description": "Hex HMAC-SHA256 of externalId (or of \"externalId:userHashTs\") with the channel identity secret, computed on your server.",
            "pattern": "^[0-9a-fA-F]{64}$"
          },
          "userHashTs": {
            "type": "number",
            "description": "Unix seconds the signature was made at, when it signs \"externalId:userHashTs\". Valid for 7 days.",
            "example": 1792700000
          }
        },
        "required": [
          "externalId"
        ]
      },
      "IdentifyResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "merged": {
            "type": "boolean",
            "description": "The visitor's anonymous history was joined to the customer."
          },
          "user": {
            "$ref": "#/components/schemas/IdentifiedUser"
          },
          "aliases": {
            "description": "Visitor ids joined to this customer.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "verified": {
            "type": "boolean",
            "description": "The customer id arrived with a valid userHash (signed identity)."
          }
        },
        "required": [
          "success",
          "merged"
        ]
      },
      "InboxAcknowledgementDto": {
        "type": "object",
        "properties": {
          "deliveryId": {
            "type": "string"
          },
          "outcome": {
            "type": "string",
            "description": "`shown`, or `suppressed:<reason>`."
          }
        },
        "required": [
          "deliveryId",
          "outcome"
        ]
      },
      "IntegrationsResponse": {
        "type": "object",
        "properties": {
          "dataLayer": {
            "$ref": "#/components/schemas/DataLayerSettings"
          }
        },
        "required": [
          "dataLayer"
        ]
      },
      "MarketingConsentEntryDto": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "email",
              "phone"
            ]
          },
          "value": {
            "type": "string"
          },
          "siteUserId": {
            "type": "string"
          },
          "iys": {
            "type": "string",
            "enum": [
              "registered",
              "rejected"
            ]
          },
          "iysSource": {
            "type": "string",
            "enum": [
              "HS_FIZIKSEL_ORTAM",
              "HS_ISLAK_IMZA",
              "HS_WEB",
              "HS_CAGRI_MERKEZI",
              "HS_SOSYAL_MEDYA",
              "HS_EPOSTA",
              "HS_MESAJ",
              "HS_MOBIL",
              "HS_EORTAM",
              "HS_ETKINLIK",
              "HS_2015",
              "HS_ATM",
              "HS_KARAR"
            ]
          },
          "optIn": {
            "type": "boolean"
          },
          "note": {
            "type": "string"
          }
        },
        "required": [
          "kind",
          "optIn"
        ]
      },
      "OrderStatusUpdateDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "description": "The order's new status, as the order system names it (`cancelled`, `refunded`, `returned`, `delivered`…). `cancelled`, `refunded`, `returned`, `failed`, `void` and `chargeback` take the order out of every revenue figure.",
            "maxLength": 20
          },
          "refundedTotal": {
            "type": "number",
            "description": "Money refunded on this order SO FAR, in the order currency — the running total, not this refund alone. A value equal to the order total refunds it in full.",
            "minimum": 0
          },
          "currency": {
            "type": "string",
            "description": "The currency `refundedTotal` is in. When sent, it must be the order currency.",
            "example": "TRY"
          }
        }
      },
      "OrderStatusUpdateResponse": {
        "type": "object",
        "properties": {
          "orderId": {
            "type": "string",
            "example": "ORDER_12345",
            "description": "Your order id, as sent."
          },
          "status": {
            "type": "string",
            "nullable": true,
            "example": "paid"
          },
          "total": {
            "type": "number",
            "example": 129.9
          },
          "refundedTotal": {
            "type": "number",
            "example": 40
          },
          "netTotal": {
            "type": "number",
            "example": 89.9,
            "description": "`total - refundedTotal`: what the attribution panels count."
          },
          "countsAsRevenue": {
            "type": "boolean",
            "description": "False once the status takes the order out of revenue."
          },
          "changed": {
            "type": "boolean",
            "description": "False when the call changed nothing (a retry)."
          }
        },
        "required": [
          "orderId",
          "status",
          "total",
          "refundedTotal",
          "netTotal",
          "countsAsRevenue",
          "changed"
        ]
      },
      "PresenceHeartbeatResponse": {
        "type": "object",
        "properties": {
          "accepted": {
            "type": "boolean",
            "description": "False when nothing was recorded: the visitor has not given analytics consent."
          },
          "live": {
            "type": "boolean",
            "description": "The visitor is counted live. A heartbeat only keeps live a visitor who sent an accepted event in the last 30 minutes; it never makes one live."
          },
          "intervalMs": {
            "type": "number",
            "example": 60000,
            "description": "Send the next heartbeat after this many milliseconds."
          }
        },
        "required": [
          "accepted",
          "live",
          "intervalMs"
        ]
      },
      "PresenceSettings": {
        "type": "object",
        "properties": {
          "intervalMs": {
            "type": "number",
            "example": 60000,
            "description": "Milliseconds between live heartbeats (`POST /presence`). Without this object, send none."
          }
        },
        "required": [
          "intervalMs"
        ]
      },
      "ProductFactsSchema": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "SKU-12345",
            "description": "The code asked about, trimmed."
          },
          "known": {
            "type": "boolean",
            "description": "The catalogue carries the code."
          },
          "pending": {
            "type": "boolean",
            "description": "Never set by the API (a client-side loading state)."
          },
          "title": {
            "type": "string",
            "nullable": true,
            "example": "Ürün Adı"
          },
          "price": {
            "type": "number",
            "nullable": true,
            "example": 199.9,
            "description": "What the shopper pays now."
          },
          "originalPrice": {
            "type": "number",
            "nullable": true,
            "example": 249.9,
            "description": "Above `price` only on sale."
          },
          "stock": {
            "type": "number",
            "nullable": true,
            "example": 3
          },
          "currency": {
            "type": "string",
            "nullable": true,
            "example": "TRY"
          }
        },
        "required": [
          "code",
          "known"
        ]
      },
      "ProductMetricBatchEntry": {
        "type": "object",
        "properties": {
          "itemCode": {
            "type": "string",
            "example": "SKU-12345"
          },
          "type": {
            "type": "string",
            "enum": [
              "product_view_count",
              "cart_count"
            ]
          },
          "count": {
            "type": "number",
            "example": 128
          },
          "formatted": {
            "type": "string",
            "example": "128"
          }
        },
        "required": [
          "itemCode",
          "type",
          "count",
          "formatted"
        ]
      },
      "ProductMetricCount": {
        "type": "object",
        "properties": {
          "count": {
            "type": "number",
            "example": 128
          },
          "formatted": {
            "type": "string",
            "example": "128",
            "description": "Shortened for display (`1.2K`)."
          }
        },
        "required": [
          "count",
          "formatted"
        ]
      },
      "PublicCampaign": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "example": "announcement_bar",
            "description": "The campaign type (see /docs/widgets)."
          },
          "isTestMode": {
            "type": "boolean",
            "description": "Only shown to visitors in test mode (`?selwise_test_mode=1`)."
          },
          "contentJson": {
            "type": "object",
            "additionalProperties": true,
            "description": "The type's content, in the visitor's language (`?lang=`).",
            "example": {
              "text": "Bugün kargo bedava"
            }
          },
          "stylesJson": {
            "type": "object",
            "additionalProperties": true
          },
          "placementConfigJson": {
            "type": "object",
            "additionalProperties": true
          },
          "devices": {
            "type": "object",
            "additionalProperties": true,
            "description": "What differs on a phone (viewport below 768px): `{ mobile: { content?, styles?, placement? } }`, laid over the three objects above.",
            "example": {
              "mobile": {
                "content": {
                  "text": "Kargo bedava"
                }
              }
            }
          },
          "customCss": {
            "type": "string"
          },
          "customJs": {
            "type": "string"
          },
          "variantId": {
            "type": "string",
            "example": "legacy-custom"
          },
          "variantVersion": {
            "type": "string",
            "example": "1.0.0"
          },
          "variantCustomized": {
            "type": "boolean"
          },
          "variantSnapshotJson": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          },
          "pageTargetingJson": {
            "$ref": "#/components/schemas/PublicPageTargeting"
          },
          "segmentTargetingMode": {
            "type": "string",
            "example": "all",
            "description": "`all`, `include` or `exclude` the listed segments."
          },
          "segmentIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "type",
          "isTestMode",
          "contentJson",
          "stylesJson",
          "placementConfigJson",
          "devices",
          "customCss",
          "customJs",
          "variantId",
          "variantVersion",
          "variantCustomized",
          "variantSnapshotJson",
          "pageTargetingJson",
          "segmentTargetingMode",
          "segmentIds"
        ]
      },
      "PublicConsentSnapshotDto": {
        "type": "object",
        "properties": {
          "granted": {
            "type": "boolean",
            "description": "Whether tracking consent is currently granted"
          },
          "categories": {
            "type": "object",
            "description": "Consent category states by key"
          },
          "timestamp": {
            "type": "number",
            "description": "Consent snapshot timestamp (ms since epoch)"
          },
          "source": {
            "type": "string",
            "description": "Consent snapshot source"
          }
        },
        "required": [
          "granted"
        ]
      },
      "PublicOrderIngestBody": {
        "type": "object",
        "properties": {
          "orderId": {
            "type": "string",
            "maxLength": 255,
            "description": "Your order id: the de-duplication key on the channel. Sending `id` instead is a 400.",
            "example": "ORDER_12345"
          },
          "sessionId": {
            "type": "string",
            "maxLength": 64,
            "description": "`Selwise.getSessionId()`; attribution reads it."
          },
          "visitorId": {
            "type": "string",
            "maxLength": 64,
            "description": "`Selwise.getVisitorId()`; attribution reads it."
          },
          "siteUserId": {
            "type": "string",
            "description": "Your customer id (`identify`). Over 64 characters the order is kept and only the customer link drops."
          },
          "currency": {
            "type": "string",
            "example": "TRY",
            "description": "ISO 4217; the channel's currency when absent or invalid."
          },
          "subtotal": {
            "type": "number",
            "example": 119.9
          },
          "discountTotal": {
            "type": "number"
          },
          "shippingTotal": {
            "type": "number",
            "example": 10
          },
          "taxTotal": {
            "type": "number"
          },
          "total": {
            "type": "number",
            "example": 129.9,
            "description": "The sum of the items when absent. Two decimals, at most 99999999.99."
          },
          "status": {
            "type": "string",
            "maxLength": 20,
            "example": "paid",
            "description": "Lower-cased. `cancelled`, `refunded`, `failed`, `voided`, `declined`, `chargeback`, `returned` and their spellings keep the order out of revenue."
          },
          "placedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Invalid is a 400."
          },
          "pageUrl": {
            "type": "string"
          },
          "referrer": {
            "type": "string"
          },
          "deviceType": {
            "type": "string",
            "maxLength": 20
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "`couponCode` (or `coupon`), `sdkPlatform` and `sdkVersion` are read."
          },
          "attribution": {
            "type": "object",
            "additionalProperties": true,
            "description": "The client's last touch. Inferred from the session's events when absent."
          },
          "experimentAssignments": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "required": [
                "experimentId",
                "variantId"
              ],
              "properties": {
                "experimentId": {
                  "type": "string"
                },
                "variantId": {
                  "type": "string"
                },
                "variantName": {
                  "type": "string"
                }
              }
            },
            "description": "Keyed by experiment id, to credit revenue to the arms."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicOrderItem"
            }
          },
          "skipPurchaseEvent": {
            "type": "boolean",
            "description": "Store the order but write no canonical `purchase` event (the data layer bridge already did)."
          },
          "marketingConsent": {
            "description": "Marketing permission ticked at checkout.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MarketingConsentEntryDto"
            }
          }
        },
        "required": [
          "orderId"
        ]
      },
      "PublicOrderIngestResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "created": {
            "type": "boolean",
            "description": "False when this `orderId` was already stored on the channel; nothing changed."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Selwise's id for the order."
          }
        },
        "required": [
          "success",
          "created",
          "id"
        ]
      },
      "PublicOrderItem": {
        "type": "object",
        "properties": {
          "productItemCode": {
            "type": "string",
            "description": "Must equal the feed `item_code`, at most 100 characters; otherwise product reports stay empty.",
            "example": "SKU-RED-XL"
          },
          "name": {
            "type": "string",
            "maxLength": 500,
            "example": "Tişört Kırmızı XL"
          },
          "quantity": {
            "type": "number",
            "minimum": 1,
            "default": 1,
            "description": "Rounded down."
          },
          "unitPrice": {
            "type": "number",
            "default": 0,
            "example": 119.9
          },
          "price": {
            "type": "number",
            "description": "Alias of `unitPrice`."
          },
          "totalPrice": {
            "type": "number",
            "description": "`unitPrice × quantity` when absent."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "PublicPageTargeting": {
        "type": "object",
        "properties": {
          "showOnAllPages": {
            "type": "boolean"
          },
          "includeUrls": {
            "example": [
              "/urun/*"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "excludeUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "showOnAllPages",
          "includeUrls",
          "excludeUrls"
        ]
      },
      "PublicPresenceDto": {
        "type": "object",
        "properties": {
          "consentSnapshot": {
            "description": "The visitor's consent, as on an event batch. Without analytics consent nothing is recorded.",
            "allOf": [
              {
                "$ref": "#/components/schemas/PublicConsentSnapshotDto"
              }
            ]
          },
          "visitorId": {
            "type": "string",
            "description": "The browser or app install id, as on an event batch."
          },
          "sessionId": {
            "type": "string"
          }
        },
        "required": [
          "consentSnapshot"
        ]
      },
      "PublicProduct": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The feed row (`item_code`), the code the strip is keyed on.",
            "example": "904240"
          },
          "_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Selwise's internal id, for tracking joins."
          },
          "itemCode": {
            "type": "string",
            "example": "904240",
            "description": "The feed row (`item_code`)."
          },
          "title": {
            "type": "string",
            "example": "Kırmızı Mini Elbise"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "shortDescription": {
            "type": "string",
            "nullable": true
          },
          "price": {
            "type": "number",
            "example": 749.9
          },
          "currency": {
            "type": "string",
            "example": "TRY"
          },
          "originalPrice": {
            "type": "number",
            "nullable": true,
            "example": 999.9
          },
          "discountRate": {
            "type": "number",
            "nullable": true,
            "example": 25
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "categories": {
            "type": "string",
            "nullable": true,
            "example": "Kadın > Elbise"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "rating": {
            "type": "number",
            "nullable": true
          },
          "reviewCount": {
            "type": "number",
            "nullable": true
          },
          "isNew": {
            "type": "boolean"
          },
          "isBestseller": {
            "type": "boolean"
          },
          "inStock": {
            "type": "boolean"
          },
          "stock": {
            "type": "number",
            "nullable": true
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "cartCode": {
            "type": "string",
            "nullable": true,
            "description": "The code the basket accepts, when it differs from `itemCode` (Akinon: the numeric product pk)."
          },
          "groupCode": {
            "type": "string",
            "nullable": true,
            "description": "Groups siblings (colours); never an identity."
          },
          "productType": {
            "type": "string",
            "nullable": true
          },
          "categoryHierarchy": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          },
          "explainability": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Why the strategy picked it."
          },
          "complement": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Only on a `complementary` strip: the role pair that put the product here."
          },
          "hasVariants": {
            "type": "boolean"
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            },
            "description": "Buyable options: the feed's nested variants, or — with none — the group's sizes of this colour (`CardSizeOption`)."
          },
          "secondaryImageUrl": {
            "type": "string",
            "description": "The image a card swaps to on hover."
          },
          "swatches": {
            "description": "This product's colour siblings.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CardSwatchSchema"
            }
          }
        },
        "required": [
          "id",
          "_uuid",
          "itemCode",
          "title",
          "price",
          "currency",
          "originalPrice",
          "discountRate",
          "cartCode",
          "groupCode",
          "hasVariants",
          "variants"
        ]
      },
      "PublicRecommendationEligibility": {
        "type": "object",
        "properties": {
          "isActive": {
            "type": "boolean"
          },
          "pageTargetingConfigured": {
            "type": "boolean"
          },
          "segmentTargetingRequired": {
            "type": "boolean"
          },
          "containerSelectorRequired": {
            "type": "boolean"
          },
          "testModeOnly": {
            "type": "boolean"
          },
          "liveCartRequired": {
            "type": "boolean",
            "description": "The strategy needs the live cart in the products request (`cart`)."
          }
        },
        "required": [
          "isActive",
          "pageTargetingConfigured",
          "segmentTargetingRequired",
          "containerSelectorRequired",
          "testModeOnly",
          "liveCartRequired"
        ]
      },
      "PublicRecommendationWidgetSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "Bunlar da ilginizi çekebilir"
          },
          "isTestMode": {
            "type": "boolean",
            "description": "Only shown to visitors in test mode (`?selwise_test_mode=1`)."
          },
          "displayType": {
            "type": "string",
            "example": "carousel"
          },
          "strategy": {
            "type": "string",
            "example": "similar_products",
            "description": "See /docs/recommendations for every strategy."
          },
          "maxProducts": {
            "type": "number",
            "example": 12
          },
          "productsPerRow": {
            "type": "number"
          },
          "slidesPerView": {
            "type": "number",
            "description": "Desktop (1280px) slides."
          },
          "slidesPerViewTablet": {
            "type": "number"
          },
          "slidesPerViewMobile": {
            "type": "number"
          },
          "slideGap": {
            "type": "number"
          },
          "autoplay": {
            "type": "boolean"
          },
          "autoplaySpeed": {
            "type": "number",
            "description": "Milliseconds."
          },
          "loop": {
            "type": "boolean"
          },
          "pauseOnHover": {
            "type": "boolean"
          },
          "arrowStyles": {
            "type": "object",
            "additionalProperties": true,
            "description": "Style settings the widget applies as they are. Their keys follow the dashboard builder."
          },
          "dotStyles": {
            "type": "object",
            "additionalProperties": true,
            "description": "Style settings the widget applies as they are. Their keys follow the dashboard builder."
          },
          "title": {
            "type": "string",
            "description": "In the visitor's language (`?lang=`)."
          },
          "titleStyles": {
            "type": "object",
            "additionalProperties": true,
            "description": "Style settings the widget applies as they are. Their keys follow the dashboard builder."
          },
          "subtitle": {
            "type": "string",
            "nullable": true
          },
          "subtitleStyles": {
            "type": "object",
            "additionalProperties": true,
            "description": "Style settings the widget applies as they are. Their keys follow the dashboard builder."
          },
          "containerStyles": {
            "type": "object",
            "additionalProperties": true,
            "description": "Style settings the widget applies as they are. Their keys follow the dashboard builder."
          },
          "customCSS": {
            "type": "string",
            "nullable": true
          },
          "customJS": {
            "type": "string",
            "nullable": true
          },
          "variantId": {
            "type": "string"
          },
          "variantVersion": {
            "type": "string"
          },
          "variantCustomized": {
            "type": "boolean"
          },
          "trigger": {
            "type": "string",
            "example": "page_load"
          },
          "triggerConfig": {
            "type": "object",
            "additionalProperties": true
          },
          "showOnAllPages": {
            "type": "boolean"
          },
          "includeUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "excludeUrls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "pageTypes": {
            "description": "Page kinds; empty means every kind.",
            "example": [
              "product"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "containerSelector": {
            "type": "string",
            "nullable": true,
            "example": ".product-detail"
          },
          "insertPosition": {
            "type": "string",
            "example": "after"
          },
          "addToCartEnabled": {
            "type": "boolean"
          },
          "ctaMode": {
            "type": "string",
            "enum": [
              "add_to_cart",
              "review"
            ]
          },
          "reviewButtonText": {
            "type": "string"
          },
          "currency": {
            "type": "string",
            "nullable": true,
            "example": "TRY"
          },
          "cartPlatform": {
            "type": "string"
          },
          "addToCartConfig": {
            "type": "object",
            "additionalProperties": true
          },
          "customCartScript": {
            "type": "string"
          },
          "productCard": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "The product card design this strip draws with (Design → Product Cards)."
          },
          "mobileProductCard": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "The card a phone (viewport below 768px) draws the strip with; null draws `productCard`."
          },
          "devices": {
            "type": "object",
            "additionalProperties": true,
            "description": "What differs on a phone (viewport below 768px): `{ mobile: { … } }`, a partial strip over its display fields (layout, product count, gap, autoplay, arrows, dots, titles and their styles, the container style), resolved over the rest."
          },
          "priority": {
            "type": "number"
          },
          "segmentTargetingMode": {
            "type": "string",
            "example": "all"
          },
          "segmentIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "reasonCodes": {
            "description": "Why the strip is or is not eligible, for debugging.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "eligibilityFlags": {
            "$ref": "#/components/schemas/PublicRecommendationEligibility"
          },
          "look": {
            "type": "object",
            "additionalProperties": true,
            "description": "Only on a `look` strip."
          }
        },
        "required": [
          "id",
          "name",
          "isTestMode",
          "displayType",
          "strategy",
          "maxProducts",
          "productsPerRow",
          "slidesPerView",
          "slidesPerViewTablet",
          "slidesPerViewMobile",
          "slideGap",
          "autoplay",
          "autoplaySpeed",
          "loop",
          "pauseOnHover",
          "arrowStyles",
          "dotStyles",
          "title",
          "titleStyles",
          "subtitle",
          "subtitleStyles",
          "containerStyles",
          "customCSS",
          "customJS",
          "trigger",
          "triggerConfig",
          "showOnAllPages",
          "includeUrls",
          "excludeUrls",
          "pageTypes",
          "containerSelector",
          "insertPosition",
          "addToCartEnabled",
          "ctaMode",
          "reviewButtonText",
          "currency",
          "cartPlatform",
          "addToCartConfig",
          "productCard",
          "mobileProductCard",
          "devices",
          "priority",
          "segmentTargetingMode",
          "segmentIds",
          "reasonCodes",
          "eligibilityFlags"
        ]
      },
      "PublicRecommendationsEligibility": {
        "type": "object",
        "properties": {
          "siteFound": {
            "type": "boolean"
          },
          "siteVerified": {
            "type": "boolean"
          },
          "subscriptionValidated": {
            "type": "boolean"
          },
          "pageUrlEvaluated": {
            "type": "boolean"
          },
          "hasEligibleWidgets": {
            "type": "boolean"
          }
        },
        "required": [
          "siteFound",
          "siteVerified",
          "subscriptionValidated",
          "pageUrlEvaluated",
          "hasEligibleWidgets"
        ]
      },
      "PublicRecommendationsResponse": {
        "type": "object",
        "properties": {
          "widgets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicRecommendationWidgetSchema"
            }
          },
          "reasonCodes": {
            "example": [
              "site_found",
              "site_verified",
              "eligible_widgets_found"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "eligibilityFlags": {
            "$ref": "#/components/schemas/PublicRecommendationsEligibility"
          },
          "error": {
            "type": "string",
            "example": "Site not verified"
          }
        },
        "required": [
          "widgets",
          "reasonCodes",
          "eligibilityFlags"
        ]
      },
      "PublicScript": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "Rozet"
          },
          "slug": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "description": "JavaScript to run on the page."
          },
          "css": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name",
          "slug",
          "code"
        ]
      },
      "PublicSignupConsentDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "The address typed into the registration form"
          },
          "phone": {
            "type": "string",
            "description": "The mobile number typed into the form (E.164). Its permission is the same checkbox, but a placeholder number is dropped server-side.",
            "maxLength": 32
          },
          "wording": {
            "type": "string",
            "description": "The label the shopper saw next to the box, verbatim. It is the consent evidence.",
            "maxLength": 500
          },
          "platform": {
            "type": "string",
            "enum": [
              "ideasoft"
            ]
          },
          "fullName": {
            "type": "string",
            "description": "First and last name typed into the form"
          },
          "locale": {
            "type": "string",
            "enum": [
              "tr",
              "en",
              "de",
              "fr",
              "es",
              "it",
              "nl",
              "pt",
              "pl",
              "ro",
              "bg",
              "el",
              "ru",
              "uk",
              "az",
              "ka",
              "ar",
              "fa"
            ]
          },
          "visitorId": {
            "type": "string",
            "description": "Public visitor ID from the widget runtime"
          },
          "sourcePath": {
            "type": "string",
            "description": "Page the form was on",
            "maxLength": 500
          }
        },
        "required": [
          "email",
          "wording",
          "platform"
        ]
      },
      "PublicSiteNewsletterStartDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "Subscriber email address"
          },
          "fullName": {
            "type": "string",
            "description": "Subscriber full name",
            "maxLength": 255
          },
          "phone": {
            "type": "string",
            "description": "Subscriber phone number (E.164, e.g. +905321112233). Required when channels includes \"sms\".",
            "maxLength": 32
          },
          "channels": {
            "type": "array",
            "description": "Contact channels this signup opts into. Defaults to [\"email\"] when omitted.",
            "items": {
              "type": "string",
              "enum": [
                "email",
                "sms"
              ]
            }
          },
          "locale": {
            "type": "string",
            "description": "UI locale",
            "enum": [
              "tr",
              "en",
              "de",
              "fr",
              "es",
              "it",
              "nl",
              "pt",
              "pl",
              "ro",
              "bg",
              "el",
              "ru",
              "uk",
              "az",
              "ka",
              "ar",
              "fa"
            ]
          },
          "visitorId": {
            "type": "string",
            "description": "Public visitor ID from widget runtime"
          },
          "siteUserId": {
            "type": "string",
            "description": "Merchant's user ID (external ID)"
          },
          "sourcePath": {
            "type": "string",
            "description": "Source page path",
            "maxLength": 500
          },
          "referrer": {
            "type": "string",
            "description": "Referrer URL",
            "maxLength": 1000
          },
          "utmSource": {
            "type": "string",
            "description": "UTM source",
            "maxLength": 120
          },
          "utmMedium": {
            "type": "string",
            "description": "UTM medium",
            "maxLength": 120
          },
          "utmCampaign": {
            "type": "string",
            "description": "UTM campaign",
            "maxLength": 160
          },
          "autoConnectUsers": {
            "type": "boolean",
            "description": "Enable auto linking to SiteUser (default true)"
          },
          "honeypot": {
            "type": "string",
            "description": "Honeypot field for bots",
            "maxLength": 255
          }
        },
        "required": [
          "email"
        ]
      },
      "PublicTrackEventItemDto": {
        "type": "object",
        "properties": {
          "eventId": {
            "type": "string",
            "description": "Client-generated idempotency key",
            "example": "evt_8c1f2d"
          },
          "eventSchemaVersion": {
            "type": "number",
            "description": "Event schema version for strict canonical validation. Defaults to 1."
          },
          "entityType": {
            "type": "string",
            "description": "campaign | widget | recommendation | search | script | page | product | basket | checkout | user | custom",
            "example": "product"
          },
          "entityId": {
            "type": "string",
            "description": "Entity ID - UUID for widgets/campaigns, or itemCode for product events, or string for other entities"
          },
          "productItemCode": {
            "type": "string",
            "description": "Product itemCode (merchant ID) - PRIMARY identifier for all product events. Use this instead of productId.",
            "example": "SKU-123"
          },
          "name": {
            "type": "string",
            "description": "Event name, e.g. impression, click, search_query, product_view, add_to_cart",
            "example": "product_view"
          },
          "metadata": {
            "type": "object",
            "description": "Additional event metadata. For product events, include productItemCode here. Limited to 2KB."
          },
          "timestamp": {
            "type": "number",
            "description": "Event timestamp (milliseconds since epoch)"
          },
          "eventTs": {
            "type": "number",
            "description": "Canonical event timestamp (milliseconds since epoch)"
          },
          "retryCount": {
            "type": "number",
            "description": "Retry count for failed events"
          },
          "correlationId": {
            "type": "string",
            "description": "Correlation ID for linking related events in attribution"
          },
          "parentEventId": {
            "type": "string",
            "description": "Parent event ID for event chains"
          },
          "journeyId": {
            "type": "string",
            "description": "Journey ID at event level (separate from batch-level journeyId)"
          },
          "journeySequence": {
            "type": "number",
            "description": "Position within journey (1, 2, 3...) for sequence analysis"
          }
        },
        "required": [
          "entityType",
          "name"
        ]
      },
      "PushMarketingConsentDto": {
        "type": "object",
        "properties": {
          "contacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MarketingConsentEntryDto"
            }
          }
        },
        "required": [
          "contacts"
        ]
      },
      "PushSubscribeDto": {
        "type": "object",
        "properties": {
          "visitorId": {
            "type": "string",
            "maxLength": 64
          },
          "siteUserId": {
            "type": "string",
            "maxLength": 64
          },
          "endpoint": {
            "type": "string",
            "maxLength": 2000,
            "description": "The browser's push service URL for this subscription."
          },
          "p256dh": {
            "type": "string",
            "maxLength": 255,
            "description": "The subscription public key (`keys.p256dh`)."
          },
          "auth": {
            "type": "string",
            "maxLength": 255,
            "description": "The subscription auth secret (`keys.auth`)."
          },
          "locale": {
            "type": "string",
            "maxLength": 35
          }
        },
        "required": [
          "visitorId",
          "endpoint",
          "p256dh",
          "auth"
        ]
      },
      "PushUnsubscribeDto": {
        "type": "object",
        "properties": {
          "endpoint": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "endpoint"
        ]
      },
      "RecommendationProductsBody": {
        "type": "object",
        "properties": {
          "currentProductId": {
            "type": "string",
            "description": "The product being viewed (`item_code`), for a product-context strategy.",
            "example": "ELB-0042"
          },
          "sessionId": {
            "type": "string"
          },
          "visitorId": {
            "type": "string"
          },
          "userId": {
            "type": "string",
            "description": "Your customer id (`identify`)."
          },
          "cart": {
            "type": "object",
            "additionalProperties": true,
            "description": "The live cart, when the strip says `liveCartRequired`."
          },
          "experimentVariantId": {
            "type": "string",
            "description": "The experiment arm the visitor is in, when the strip is under test."
          }
        }
      },
      "RecommendationProductsMeta": {
        "type": "object",
        "properties": {
          "strategy": {
            "type": "string",
            "example": "similar_products",
            "description": "The strategy that answered."
          },
          "fallbackUsed": {
            "type": "boolean",
            "description": "The strategy had too little and the fallback filled the strip."
          },
          "fallbackStrategy": {
            "type": "string",
            "enum": [
              "new_arrivals",
              "bestsellers",
              "none"
            ],
            "nullable": true
          },
          "reason": {
            "type": "string",
            "description": "Why the strip is empty or fell back."
          },
          "complementSetComputedAt": {
            "type": "string",
            "format": "date-time",
            "description": "`complementary` only: when the precomputed set was computed."
          },
          "stockCheckedAt": {
            "type": "string",
            "format": "date-time",
            "description": "`complementary` only: when stock was re-checked for this answer."
          }
        },
        "required": [
          "strategy",
          "fallbackUsed",
          "fallbackStrategy"
        ]
      },
      "RecommendationProductsResponse": {
        "type": "object",
        "properties": {
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicProduct"
            }
          },
          "productCard": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          },
          "meta": {
            "$ref": "#/components/schemas/RecommendationProductsMeta"
          },
          "liveCartRequired": {
            "type": "boolean"
          },
          "error": {
            "type": "string",
            "description": "Present when the products could not be read; `products` is then empty."
          }
        },
        "required": [
          "products"
        ]
      },
      "RecommendationTrackBehaviorBody": {
        "type": "object",
        "properties": {
          "behaviorType": {
            "type": "string",
            "enum": [
              "view",
              "add_to_cart",
              "purchase",
              "wishlist"
            ]
          },
          "productItemCode": {
            "type": "string",
            "description": "The feed `item_code`."
          },
          "productCategory": {
            "type": "string"
          },
          "productPrice": {
            "type": "number"
          },
          "sessionId": {
            "type": "string"
          },
          "visitorId": {
            "type": "string"
          },
          "siteUserId": {
            "type": "string"
          },
          "pageUrl": {
            "type": "string"
          },
          "referrer": {
            "type": "string"
          },
          "deviceType": {
            "type": "string"
          },
          "dwellTime": {
            "type": "number",
            "description": "Seconds on the product."
          },
          "eventId": {
            "type": "string"
          }
        },
        "required": [
          "behaviorType"
        ]
      },
      "RecommendationTrackEventBody": {
        "type": "object",
        "properties": {
          "widgetId": {
            "type": "string",
            "format": "uuid"
          },
          "eventType": {
            "type": "string",
            "enum": [
              "impression",
              "click",
              "add_to_cart",
              "purchase"
            ]
          },
          "productItemCode": {
            "type": "string",
            "description": "The feed `item_code`."
          },
          "sessionId": {
            "type": "string"
          },
          "visitorId": {
            "type": "string"
          },
          "journeyId": {
            "type": "string",
            "description": "The visit (`journey_id`)."
          },
          "userId": {
            "type": "string"
          },
          "pageUrl": {
            "type": "string"
          },
          "deviceType": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "eventId": {
            "type": "string",
            "description": "Your id for the event; a repeat is dropped."
          }
        },
        "required": [
          "widgetId",
          "eventType"
        ]
      },
      "ReportsAttributedSchema": {
        "type": "object",
        "properties": {
          "orders": {
            "type": "number"
          },
          "revenueByCurrency": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportsRevenueSchema"
            }
          }
        },
        "required": [
          "orders",
          "revenueByCurrency"
        ]
      },
      "ReportsChannelSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "platform": {
            "type": "string",
            "nullable": true,
            "example": "akinon"
          }
        },
        "required": [
          "name",
          "platform"
        ]
      },
      "ReportsComparisonSchema": {
        "type": "object",
        "properties": {
          "orders": {
            "type": "boolean",
            "description": "The previous window's orders and revenue are comparable."
          },
          "events": {
            "type": "boolean",
            "description": "Figures counted from the previous window's own events (visitors) are comparable."
          },
          "attributed": {
            "type": "boolean",
            "description": "Attributed figures are comparable: they need the interactions from a lookback before the previous window. When false, `previous.attributed` is null."
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "channel_created",
              "retention"
            ]
          }
        },
        "required": [
          "orders",
          "events",
          "attributed",
          "reason"
        ]
      },
      "ReportsConnectionSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "connected"
          },
          "lastError": {
            "type": "string",
            "nullable": true
          },
          "streams": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportsStreamSchema"
            }
          }
        },
        "required": [
          "status",
          "lastError",
          "streams"
        ]
      },
      "ReportsModuleSchema": {
        "type": "object",
        "properties": {
          "module": {
            "type": "string",
            "example": "recommendation"
          },
          "orders": {
            "type": "number"
          },
          "revenueByCurrency": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportsRevenueSchema"
            }
          }
        },
        "required": [
          "module",
          "orders",
          "revenueByCurrency"
        ]
      },
      "ReportsRevenueSchema": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "example": "TRY"
          },
          "orders": {
            "type": "number"
          },
          "revenue": {
            "type": "number"
          }
        },
        "required": [
          "currency",
          "orders",
          "revenue"
        ]
      },
      "ReportsStreamSchema": {
        "type": "object",
        "properties": {
          "stream": {
            "type": "string",
            "example": "orders"
          },
          "lastSuccessAt": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "lastError": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "stream",
          "lastSuccessAt",
          "lastError"
        ]
      },
      "ReportsSummaryPeriodSchema": {
        "type": "object",
        "properties": {
          "startDate": {
            "type": "string",
            "format": "date-time"
          },
          "endDate": {
            "type": "string",
            "format": "date-time"
          },
          "orders": {
            "type": "number",
            "description": "Every live revenue order in the window."
          },
          "revenueByCurrency": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportsRevenueSchema"
            }
          },
          "attributed": {
            "nullable": true,
            "description": "Orders and revenue Selwise influenced; null when the window’s events are no longer stored.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ReportsAttributedSchema"
              }
            ]
          },
          "visitors": {
            "type": "number",
            "nullable": true
          }
        },
        "required": [
          "startDate",
          "endDate",
          "orders",
          "revenueByCurrency",
          "attributed",
          "visitors"
        ]
      },
      "ReportsSummaryResponseSchema": {
        "type": "object",
        "properties": {
          "channel": {
            "$ref": "#/components/schemas/ReportsChannelSchema"
          },
          "days": {
            "type": "number",
            "example": 30
          },
          "generatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "lookbackHours": {
            "type": "number"
          },
          "current": {
            "$ref": "#/components/schemas/ReportsSummaryPeriodSchema"
          },
          "previous": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/ReportsSummaryPeriodSchema"
              }
            ]
          },
          "comparison": {
            "$ref": "#/components/schemas/ReportsComparisonSchema"
          },
          "modules": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReportsModuleSchema"
            }
          },
          "connection": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/ReportsConnectionSchema"
              }
            ]
          }
        },
        "required": [
          "channel",
          "days",
          "generatedAt",
          "lookbackHours",
          "current",
          "previous",
          "comparison",
          "modules",
          "connection"
        ]
      },
      "SaveConsentDto": {
        "type": "object",
        "properties": {
          "categories": {
            "type": "object",
            "example": {
              "necessary": true,
              "analytics": true,
              "marketing": false,
              "preferences": true
            }
          },
          "visitorId": {
            "type": "string",
            "maxLength": 64
          },
          "sessionId": {
            "type": "string",
            "maxLength": 64
          },
          "siteUserId": {
            "type": "string",
            "maxLength": 64
          },
          "action": {
            "type": "string",
            "description": "accepted, declined, customized, timeout or api",
            "maxLength": 32
          }
        },
        "required": [
          "categories"
        ]
      },
      "ScenarioInboxAckDto": {
        "type": "object",
        "properties": {
          "visitorId": {
            "type": "string"
          },
          "acknowledgements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InboxAcknowledgementDto"
            }
          }
        },
        "required": [
          "visitorId",
          "acknowledgements"
        ]
      },
      "ScenarioInboxAckResponse": {
        "type": "object",
        "properties": {
          "updated": {
            "type": "number",
            "description": "Deliveries closed by this call."
          }
        },
        "required": [
          "updated"
        ]
      },
      "ScenarioInboxEntrySchema": {
        "type": "object",
        "properties": {
          "deliveryId": {
            "type": "string",
            "format": "uuid"
          },
          "scenarioId": {
            "type": "string",
            "format": "uuid"
          },
          "runId": {
            "type": "string",
            "format": "uuid"
          },
          "nodeId": {
            "type": "string"
          },
          "campaignId": {
            "type": "string",
            "format": "uuid"
          },
          "tokens": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Merge fields, already interpolated."
          },
          "respectFrequencyCaps": {
            "type": "boolean"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "available": {
            "type": "boolean",
            "description": "False when the campaign can no longer be delivered; close it as `entity_missing`."
          },
          "scenarioOnly": {
            "type": "boolean",
            "description": "The campaign is not in `/config`; its body rides in `campaign`."
          },
          "campaign": {
            "type": "object",
            "additionalProperties": true,
            "description": "Same shape as a `/config` campaign."
          }
        },
        "required": [
          "deliveryId",
          "scenarioId",
          "runId",
          "nodeId",
          "campaignId",
          "tokens",
          "respectFrequencyCaps",
          "expiresAt"
        ]
      },
      "ScenarioInboxResponseSchema": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScenarioInboxEntrySchema"
            }
          }
        },
        "required": [
          "entries"
        ]
      },
      "ScriptsResponse": {
        "type": "object",
        "properties": {
          "scripts": {
            "description": "The scripts whose path rule matches `path`.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicScript"
            }
          }
        },
        "required": [
          "scripts"
        ]
      },
      "SearchCategoryCount": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "example": "Kadın > Elbise"
          },
          "count": {
            "type": "number",
            "example": 31
          }
        },
        "required": [
          "name",
          "count"
        ]
      },
      "SearchClickBody": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string"
          },
          "visitorId": {
            "type": "string"
          },
          "siteUserId": {
            "type": "string"
          },
          "pageUrl": {
            "type": "string"
          },
          "referrer": {
            "type": "string"
          },
          "eventId": {
            "type": "string",
            "description": "Your id for the event; a repeat is dropped."
          },
          "productItemCode": {
            "type": "string",
            "description": "The clicked product (`item_code`). Empty is a 400.",
            "example": "904236"
          },
          "category": {
            "type": "string"
          },
          "query": {
            "type": "string",
            "description": "The query that led to the click."
          },
          "journeyId": {
            "type": "string",
            "description": "The visit (`journey_id`); resolved from the session when absent."
          }
        },
        "required": [
          "productItemCode"
        ]
      },
      "SearchConfigResponse": {
        "type": "object",
        "properties": {
          "v": {
            "type": "number",
            "description": "Settings document version.",
            "example": 2
          },
          "enabled": {
            "type": "boolean",
            "description": "False when search is off (`mode: off`) or the channel never configured it."
          },
          "mode": {
            "type": "string",
            "enum": [
              "off",
              "test",
              "live"
            ],
            "description": "`test`: only browsers carrying the test flag draw it."
          },
          "settings": {
            "type": "object",
            "additionalProperties": true,
            "description": "The instant-search settings document (`SearchSettings`): placement (the field, what opens it, the desktop and phone surfaces), behavior (minChars, debounceMs, maxResults), results, suggestions, appearance, texts (in the visitor's language), cart, and `devices.mobile` — a partial document of what differs on a phone (viewport below 768px), resolved over the rest. Absent when the channel has no configuration."
          },
          "productCard": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          },
          "mobileProductCard": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "The card a phone (viewport below 768px) draws results with; null draws `productCard`."
          },
          "audience": {
            "type": "object",
            "additionalProperties": true,
            "description": "Segment targeting: mode and segment ids."
          }
        },
        "required": [
          "v",
          "enabled",
          "mode"
        ]
      },
      "SearchHit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The merchant's code: `sku`, else `item_code`.",
            "example": "ELB-0042"
          },
          "_uuid": {
            "type": "string",
            "format": "uuid",
            "description": "Selwise's internal id, for tracking joins."
          },
          "itemCode": {
            "type": "string",
            "example": "904236"
          },
          "sku": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "example": "Kırmızı Midi Elbise"
          },
          "price": {
            "type": "number",
            "example": 899.9
          },
          "originalPrice": {
            "type": "number",
            "nullable": true
          },
          "discountRate": {
            "type": "number",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "example": "TRY",
            "description": "The channel's currency when the row carries none."
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "categories": {
            "type": "string",
            "nullable": true,
            "example": "Kadın > Elbise"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "inStock": {
            "type": "boolean"
          },
          "stock": {
            "type": "number",
            "nullable": true
          },
          "hasVariants": {
            "type": "boolean"
          },
          "cartCode": {
            "type": "string",
            "nullable": true,
            "description": "The basket code when it differs from `itemCode`."
          },
          "groupCode": {
            "type": "string",
            "nullable": true,
            "description": "Groups siblings; never an identity."
          },
          "score": {
            "type": "number",
            "description": "Relevance score."
          }
        },
        "required": [
          "id",
          "_uuid",
          "itemCode",
          "title",
          "price",
          "currency"
        ]
      },
      "SearchLogBody": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string"
          },
          "visitorId": {
            "type": "string"
          },
          "siteUserId": {
            "type": "string"
          },
          "pageUrl": {
            "type": "string"
          },
          "referrer": {
            "type": "string"
          },
          "eventId": {
            "type": "string",
            "description": "Your id for the event; a repeat is dropped."
          },
          "query": {
            "type": "string",
            "example": "kırmızı elbise"
          },
          "resultsCount": {
            "type": "number",
            "example": 42
          }
        },
        "required": [
          "query"
        ]
      },
      "SearchResponse": {
        "type": "object",
        "properties": {
          "hits": {
            "description": "Card fields (`variants`, swatches) are added when the feed carries them.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchHit"
            }
          },
          "total": {
            "type": "number",
            "example": 42
          },
          "took": {
            "type": "number",
            "description": "Server time, milliseconds.",
            "example": 12
          },
          "enabled": {
            "type": "boolean",
            "description": "False when search is off on this channel; `hits` is then empty."
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchCategoryCount"
            }
          },
          "redirect": {
            "type": "string",
            "description": "The query matched a redirect rule: send the shopper here. `hits` is empty."
          },
          "suggestions": {
            "description": "\"Did you mean\" alternatives on a zero result (at most 5).",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "expandedQuery": {
            "description": "The terms searched after synonym and Turkish inflection expansion.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "error": {
            "type": "string",
            "description": "Why the search did not run as asked. The status is still 200 — read it with `strategy` (`Query parameter required`, `Query too long`, `Search service temporarily unavailable`)."
          },
          "strategy": {
            "type": "string",
            "enum": [
              "standard",
              "expanded_query",
              "redirect",
              "disabled",
              "service_unavailable",
              "validation_error",
              "error"
            ]
          },
          "debugMeta": {
            "type": "object",
            "additionalProperties": true,
            "description": "Diagnostics: the filters applied and what was clamped. Not for display."
          },
          "traceId": {
            "type": "string",
            "format": "uuid",
            "description": "Quote it to match a complaint with the server log."
          }
        },
        "required": [
          "hits",
          "total",
          "took",
          "enabled",
          "strategy",
          "debugMeta",
          "traceId"
        ]
      },
      "SearchSuggestionsResponse": {
        "type": "object",
        "properties": {
          "recentSearches": {
            "description": "A setting only: the shopper's own searches live in the browser.",
            "allOf": [
              {
                "$ref": "#/components/schemas/SuggestionList"
              }
            ]
          },
          "popularSearches": {
            "example": {
              "enabled": true,
              "items": [
                "elbise",
                "ceket"
              ]
            },
            "allOf": [
              {
                "$ref": "#/components/schemas/SuggestionList"
              }
            ]
          },
          "popularCategories": {
            "$ref": "#/components/schemas/SuggestionList"
          },
          "popularProducts": {
            "description": "Titles and URLs in the shopper's language (`?lang=`).",
            "allOf": [
              {
                "$ref": "#/components/schemas/SuggestionList"
              }
            ]
          },
          "styles": {
            "type": "object",
            "additionalProperties": true
          },
          "error": {
            "type": "string",
            "example": "Failed to get suggestions",
            "description": "Set instead of the lists when reading them failed."
          }
        }
      },
      "SearchZeroResultsBody": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "example": "krmızı elbse"
          },
          "sessionId": {
            "type": "string"
          },
          "visitorId": {
            "type": "string"
          },
          "siteUserId": {
            "type": "string"
          },
          "pageUrl": {
            "type": "string"
          },
          "eventId": {
            "type": "string",
            "description": "Your id for the event; a repeat is dropped."
          }
        },
        "required": [
          "query"
        ]
      },
      "SegmentEvaluationResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            },
            "description": "Keyed by segment id: is the visitor in it."
          }
        },
        "required": [
          "results"
        ]
      },
      "SetTraitsDto": {
        "type": "object",
        "properties": {
          "externalId": {
            "type": "string",
            "description": "Merchant's user ID (external ID)"
          },
          "visitorId": {
            "type": "string",
            "description": "Visitor ID (for anonymous users)"
          },
          "traits": {
            "type": "object",
            "description": "User traits/attributes to set"
          }
        },
        "required": [
          "externalId",
          "traits"
        ]
      },
      "SignupConsentResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "number",
            "enum": [
              true
            ]
          },
          "email": {
            "type": "boolean",
            "description": "An email permission was recorded."
          },
          "sms": {
            "type": "boolean",
            "description": "An SMS permission was recorded."
          }
        },
        "required": [
          "success",
          "email",
          "sms"
        ]
      },
      "SsrEnrichmentResponseSchema": {
        "type": "object",
        "properties": {
          "v": {
            "type": "string",
            "example": "m3k1p.4",
            "description": "Also the ETag; send it back as `If-None-Match` for a 304."
          },
          "mode": {
            "type": "string",
            "enum": [
              "anonymous"
            ],
            "description": "Carries no visitor-dependent rule, so the rendered page may be cached."
          },
          "slots": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/SsrSlotSchema"
            },
            "description": "Keyed by placement key. A slot with no content is present and empty."
          },
          "css": {
            "type": "string",
            "description": "Every block's CSS, deduplicated and scoped; print it beside the content."
          },
          "meta": {
            "$ref": "#/components/schemas/SsrMetaSchema"
          }
        },
        "required": [
          "v",
          "mode",
          "slots",
          "css",
          "meta"
        ]
      },
      "SsrMetaSchema": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "example": "ABC-1"
          },
          "resolved": {
            "type": "boolean"
          },
          "renderedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "code",
          "resolved",
          "renderedAt"
        ]
      },
      "SsrRecommendationMetaSchema": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "nullable": true
          },
          "skipped": {
            "type": "string",
            "nullable": true,
            "enum": [
              "not_found",
              "inactive",
              "test_mode",
              "segment_targeted",
              "personal_strategy",
              "anchor_missing"
            ],
            "description": "Why `products` is empty on purpose; null when the strip was answered."
          },
          "renderedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "code",
          "skipped",
          "renderedAt"
        ]
      },
      "SsrRecommendationProductSchema": {
        "type": "object",
        "properties": {
          "itemCode": {
            "type": "string",
            "example": "SKU-12345",
            "description": "The feed `item_code`."
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "imageUrl": {
            "type": "string",
            "nullable": true
          },
          "price": {
            "type": "number"
          },
          "originalPrice": {
            "type": "number",
            "nullable": true
          },
          "discountRate": {
            "type": "number",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "example": "TRY"
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "inStock": {
            "type": "boolean",
            "nullable": true
          },
          "cartCode": {
            "type": "string",
            "nullable": true,
            "description": "The code the basket accepts when it is not `itemCode`."
          }
        },
        "required": [
          "itemCode",
          "title",
          "url",
          "imageUrl",
          "price",
          "originalPrice",
          "discountRate",
          "currency",
          "brand",
          "inStock",
          "cartCode"
        ]
      },
      "SsrRecommendationResponseSchema": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "anonymous"
            ],
            "description": "Carries nothing visitor-dependent, so the rendered page may be cached."
          },
          "widget": {
            "nullable": true,
            "allOf": [
              {
                "$ref": "#/components/schemas/SsrRecommendationWidgetSchema"
              }
            ]
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SsrRecommendationProductSchema"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/SsrRecommendationMetaSchema"
          }
        },
        "required": [
          "mode",
          "widget",
          "products",
          "meta"
        ]
      },
      "SsrRecommendationWidgetSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "title": {
            "type": "string",
            "description": "Empty when the strip shows no heading."
          },
          "subtitle": {
            "type": "string",
            "nullable": true
          },
          "strategy": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "title",
          "subtitle",
          "strategy"
        ]
      },
      "SsrSlotSchema": {
        "type": "object",
        "properties": {
          "html": {
            "type": "string",
            "description": "Ready to print: interpolated, sanitised, scoped and wrapped in a stamped root."
          },
          "assignmentIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "html",
          "assignmentIds"
        ]
      },
      "SuccessOnly": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          }
        },
        "required": [
          "success"
        ]
      },
      "SuccessResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "False when the channel is unknown or unverified, or the write failed. The status is still 2xx."
          },
          "error": {
            "type": "string"
          }
        },
        "required": [
          "success"
        ]
      },
      "SuggestionList": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {}
          },
          "maxCount": {
            "type": "number"
          }
        },
        "required": [
          "enabled"
        ]
      },
      "TrackExperimentEventDto": {
        "type": "object",
        "properties": {
          "experimentId": {
            "type": "string",
            "description": "Experiment the variant belongs to"
          },
          "variantId": {
            "type": "string",
            "description": "Assigned variant"
          },
          "eventType": {
            "type": "string",
            "enum": [
              "exposure",
              "impression",
              "conversion",
              "goal"
            ]
          },
          "goalId": {
            "type": "string",
            "description": "Configured goal (required for goal events)"
          },
          "visitorId": {
            "type": "string",
            "description": "Visitor id (selwise_vid)"
          },
          "testMode": {
            "type": "boolean",
            "description": "Event came from a test-mode session"
          },
          "actionHealth": {
            "description": "Per-action match report (page experiments)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "revenue": {
            "type": "number",
            "description": "Order value for a conversion"
          }
        },
        "required": [
          "experimentId",
          "variantId",
          "eventType"
        ]
      },
      "TrackPublicEventsBatchDto": {
        "type": "object",
        "properties": {
          "requestId": {
            "type": "string",
            "description": "Client-generated request id for batch idempotency",
            "example": "rid_lz3k1p_9f2a4c1d"
          },
          "sessionId": {
            "type": "string",
            "example": "SESSION_ID"
          },
          "consentSnapshot": {
            "description": "Consent snapshot for this batch. Required; batch is dropped if missing.",
            "allOf": [
              {
                "$ref": "#/components/schemas/PublicConsentSnapshotDto"
              }
            ]
          },
          "visitorId": {
            "type": "string"
          },
          "siteUserId": {
            "type": "string"
          },
          "pageUrl": {
            "type": "string"
          },
          "referrer": {
            "type": "string"
          },
          "journeyId": {
            "type": "string",
            "description": "Journey ID for linking related events in a user session"
          },
          "testMode": {
            "type": "boolean",
            "description": "The visitor has `selwise_test_mode` set. Only scenario entry reads it: a test-mode scenario must admit only a merchant doing QA, and nothing else on this path changes behaviour on it."
          },
          "events": {
            "description": "Array of events (max 200 per batch, subject to site config)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PublicTrackEventItemDto"
            }
          }
        },
        "required": [
          "requestId",
          "sessionId",
          "consentSnapshot",
          "events"
        ]
      },
      "TrackingBatchResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "True only when every event was accepted."
          },
          "accepted": {
            "type": "number",
            "example": 2
          },
          "degraded": {
            "type": "number",
            "example": 1,
            "description": "Accepted events stored with a warning."
          },
          "rejected": {
            "type": "number",
            "example": 0
          },
          "processed": {
            "type": "number",
            "example": 2
          },
          "failed": {
            "type": "number",
            "example": 0
          },
          "results": {
            "description": "One entry per event, in no guaranteed order.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TrackingBatchResult"
            }
          }
        },
        "required": [
          "success",
          "accepted",
          "rejected",
          "processed",
          "failed",
          "results"
        ]
      },
      "TrackingBatchResult": {
        "type": "object",
        "properties": {
          "eventId": {
            "type": "string",
            "example": "evt_8c1f2d"
          },
          "success": {
            "type": "boolean"
          },
          "duplicate": {
            "type": "boolean",
            "description": "Already received under this `eventId`; nothing was written."
          },
          "degraded": {
            "type": "boolean",
            "description": "Stored, but a field the reports need was missing (see `warnings`)."
          },
          "validationStatus": {
            "type": "string",
            "enum": [
              "valid",
              "degraded"
            ]
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "warning": {
            "type": "string",
            "example": "Missing productItemCode for event: add_to_cart"
          },
          "error": {
            "type": "string",
            "description": "Why this event was rejected."
          }
        },
        "required": [
          "eventId",
          "success"
        ]
      },
      "TrackingSettings": {
        "type": "object",
        "properties": {
          "batchingEnabled": {
            "type": "boolean"
          },
          "batchSize": {
            "type": "number",
            "example": 50
          },
          "flushInterval": {
            "type": "number",
            "description": "Seconds.",
            "example": 30
          },
          "offlinePersistence": {
            "type": "boolean"
          },
          "sendBeaconOnUnload": {
            "type": "boolean"
          },
          "maxRetries": {
            "type": "number"
          },
          "maxQueueSize": {
            "type": "number"
          },
          "maxStorageEvents": {
            "type": "number"
          },
          "debugMode": {
            "type": "boolean"
          },
          "dataLayerConfig": {
            "type": "object",
            "additionalProperties": true,
            "description": "Data layer settings: page-type patterns, tracking modules, cookie consent (Settings → Data Layer)."
          },
          "presence": {
            "description": "The live heartbeat: whether to send it and how often (server-controlled).",
            "allOf": [
              {
                "$ref": "#/components/schemas/PresenceSettings"
              }
            ]
          },
          "geo": {
            "description": "Per request; absent when the edge sent no country.",
            "allOf": [
              {
                "$ref": "#/components/schemas/GeoHint"
              }
            ]
          }
        },
        "required": [
          "batchingEnabled",
          "batchSize",
          "flushInterval",
          "offlinePersistence",
          "sendBeaconOnUnload",
          "maxRetries",
          "maxQueueSize",
          "maxStorageEvents",
          "debugMode",
          "dataLayerConfig",
          "presence"
        ]
      },
      "TraitsResult": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "updated": {
            "example": [
              "plan",
              "sadakatPuani"
            ],
            "description": "Every key sent, written or unchanged.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "success",
          "updated"
        ]
      },
      "WidgetsResponse": {
        "type": "object",
        "properties": {
          "widgets": {
            "type": "array",
            "items": {},
            "maxItems": 0,
            "description": "Always empty: widgets merged into campaigns."
          }
        },
        "required": [
          "widgets"
        ]
      },
      "WithdrawConsentDto": {
        "type": "object",
        "properties": {
          "visitorId": {
            "type": "string",
            "maxLength": 64
          },
          "sessionId": {
            "type": "string",
            "maxLength": 64
          },
          "siteUserId": {
            "type": "string",
            "maxLength": 64
          }
        }
      }
    }
  }
}
