{
  "info": {
    "name": "Trooply Search API",
    "_postman_id": "trooply-search-api-2026-05-06",
    "description": "Auto-generated from FastAPI's OpenAPI schema. Three Postman variables drive every request:\n\n- `{{base_url}}` \u2014 the API host (default `https://search.trooply.ai`)\n- `{{access_token}}` \u2014 JWT from `/oauth/login` or `/oauth/token`\n- `{{admin_api_key}}` \u2014 static admin secret from server env, only needed for `/admin/*` endpoints (NOT `/admin/sa/*` which use the JWT)\n- `{{tenant_slug}}` \u2014 the active store slug, sent as `X-Trooply-Active-Tenant` header on `/v1/*` requests for users with multi-store memberships.\n\nAuth scheme is auto-set per-request based on the OpenAPI security requirement: bearer JWT for most paths, the admin API key for /admin (legacy) endpoints, no auth for the OAuth grant endpoints and the public-key widget search.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "_exporter_id": "auto-generated"
  },
  "item": [
    {
      "name": "AI",
      "description": "6 endpoints",
      "item": [
        {
          "name": "Chat completion (OpenAI-compatible)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/ai/chat/completions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "ai",
                "chat",
                "completions"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Forwards to the Trooply AI chat endpoint. Supports `stream=true` for SSE.\nToken usage is recorded per-client per-month in Redis.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"messages\": [\n    {}\n  ],\n  \"model\": \"string\",\n  \"stream\": false,\n  \"temperature\": 0,\n  \"max_tokens\": 0,\n  \"top_p\": 0,\n  \"tools\": [\n    {}\n  ],\n  \"response_format\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "AI proxy + upstream health",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/ai/health",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "ai",
                "health"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Combined health check.\n\nPublic response is minimal (`ok` + `upstream_ok`). Full upstream model\nlist is only revealed when the caller supplies the `X-Admin-Token`\nmatching `ADMIN_HEALTH_TOKEN`. This keeps the Altair/Gemma masking\nconsistent with the rest of the platform (BUG-104)."
          },
          "response": []
        },
        {
          "name": "End-to-end NL search: parse + vector retrieval",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/ai/search/nl",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "ai",
                "search",
                "nl"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Parses the query with Gemma, then runs the parsed core query through CLIP + Qdrant against the caller's product collection. Filter fields are returned in the response but not yet applied at retrieval \u2014 clients can post-filter, or wait for filter-application in a future phase.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"query\": \"string\",\n  \"limit\": 10,\n  \"threshold\": 0.0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Parse a natural-language shopping query into query + filters",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/ai/search/parse",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "ai",
                "search",
                "parse"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Extract structured filters from an NL query. Cached in Redis for 24h.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"query\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Spell-correct + expand a shopping query",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/ai/search/suggest",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "ai",
                "search",
                "suggest"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Return a corrected query plus 3 related expansions. Cached 24h.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"query\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Current-month AI token usage for this client",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/ai/usage",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "ai",
                "usage"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Current-month AI token usage for this client"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Admin",
      "description": "11 endpoints",
      "item": [
        {
          "name": "Get activity logs",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/activity?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "activity"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "100",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "action",
                  "value": "string",
                  "description": "Filter by action type e.g. auth.login",
                  "disabled": true
                },
                {
                  "key": "email",
                  "value": "string",
                  "description": "Filter by actor email",
                  "disabled": true
                },
                {
                  "key": "hours",
                  "value": "0",
                  "description": "Filter to last N hours",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "string",
                  "description": "Filter by status: success or failed",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "View platform activity logs (user actions, logins, registrations, etc.)"
          },
          "response": []
        },
        {
          "name": "Get activity statistics",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/activity/stats?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "activity",
                "stats"
              ],
              "query": [
                {
                  "key": "hours",
                  "value": "24",
                  "description": "Stats for the last N hours",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Summary counts of activity by action type"
          },
          "response": []
        },
        {
          "name": "Get billing overview",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/billing/overview",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "billing",
                "overview"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get billing metrics: MRR, active subscriptions, revenue by plan"
          },
          "response": []
        },
        {
          "name": "List all clients",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/clients?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "clients"
              ],
              "query": [
                {
                  "key": "offset",
                  "value": "0",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "is_active",
                  "value": "False",
                  "description": "Filter by active status",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get a list of all registered clients"
          },
          "response": []
        },
        {
          "name": "Create a new client",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/admin/clients",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "clients"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Register a new API client (requires admin API key)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"client_name\": \"string\",\n  \"email\": \"string\",\n  \"password\": \"string\",\n  \"plan\": \"free\",\n  \"is_admin\": false,\n  \"webhook_url\": \"string\",\n  \"notes\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete client",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/clients/{client_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "clients",
                "{client_id}"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Deactivate a client and delete all of their per-tenant data"
          },
          "response": []
        },
        {
          "name": "Get client details",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/clients/{client_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "clients",
                "{client_id}"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get detailed information about a client including usage stats"
          },
          "response": []
        },
        {
          "name": "Update client",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/admin/clients/{client_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "clients",
                "{client_id}"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Update client settings (plan, limits, status)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"client_name\": \"string\",\n  \"email\": \"string\",\n  \"password\": \"string\",\n  \"plan\": \"free\",\n  \"is_active\": false,\n  \"webhook_url\": \"string\",\n  \"rate_limit_per_minute\": 0,\n  \"max_products\": 0,\n  \"notes\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get tenant payment history",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/clients/{client_id}/payments",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "clients",
                "{client_id}",
                "payments"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "View Stripe invoices for a specific tenant"
          },
          "response": []
        },
        {
          "name": "Get global usage stats",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/usage",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "usage"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get global usage statistics across all clients"
          },
          "response": []
        },
        {
          "name": "Trigger usage alert check",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/usage-alerts/check",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "usage-alerts",
                "check"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Manually run the usage alert check for all tenants"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Admin - App Logs",
      "description": "2 endpoints",
      "item": [
        {
          "name": "Search Logs",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/logs/search?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "logs",
                "search"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "string",
                  "description": "Full-text search (message + exception)",
                  "disabled": true
                },
                {
                  "key": "level",
                  "value": "string",
                  "description": "Exact level: INFO / WARNING / ERROR / CRITICAL",
                  "disabled": true
                },
                {
                  "key": "level_min",
                  "value": "string",
                  "description": "Minimum level (e.g. WARNING = no INFO)",
                  "disabled": true
                },
                {
                  "key": "request_id",
                  "value": "string",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "client_id",
                  "value": "string",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "user_id",
                  "value": "string",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "path",
                  "value": "string",
                  "description": "Exact request path, e.g. /v1/search/text",
                  "disabled": true
                },
                {
                  "key": "method",
                  "value": "string",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "logger",
                  "value": "string",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "since",
                  "value": "string",
                  "description": "ISO timestamp lower bound (inclusive)",
                  "disabled": true
                },
                {
                  "key": "until",
                  "value": "string",
                  "description": "ISO timestamp upper bound (inclusive)",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "200",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "scan_bytes",
                  "value": "8388608",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Return up to `limit` recent log lines matching every supplied filter.\n\nResults come back **newest first**. Each entry is the parsed JSON of the\noriginal log line \u2014 `ts`, `level`, `logger`, `message`, and whatever\ncontext + extras were attached."
          },
          "response": []
        },
        {
          "name": "Log Stats",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/logs/stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "logs",
                "stats"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Quick health metadata about the log pipeline for the UI header."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Admin - Error Logs",
      "description": "5 endpoints",
      "item": [
        {
          "name": "Get error logs",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/errors?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "errors"
              ],
              "query": [
                {
                  "key": "offset",
                  "value": "0",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "level",
                  "value": "string",
                  "description": "Filter by error level",
                  "disabled": true
                },
                {
                  "key": "error_type",
                  "value": "string",
                  "description": "Filter by error type",
                  "disabled": true
                },
                {
                  "key": "endpoint",
                  "value": "string",
                  "description": "Filter by endpoint",
                  "disabled": true
                },
                {
                  "key": "resolved",
                  "value": "False",
                  "description": "Filter by resolved status",
                  "disabled": true
                },
                {
                  "key": "hours",
                  "value": "0",
                  "description": "Only errors in last N hours",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get a list of system error logs with filtering options"
          },
          "response": []
        },
        {
          "name": "Clear old error logs",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/errors/clear?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "errors",
                "clear"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "Delete errors older than N days (0 = delete all)",
                  "disabled": true
                },
                {
                  "key": "resolved_only",
                  "value": "True",
                  "description": "Only delete resolved errors",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Delete error logs older than specified days"
          },
          "response": []
        },
        {
          "name": "Get error statistics",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/errors/stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "errors",
                "stats"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get aggregated error statistics"
          },
          "response": []
        },
        {
          "name": "Get error details",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/errors/{error_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "errors",
                "{error_id}"
              ],
              "variable": [
                {
                  "key": "error_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get detailed information about a specific error"
          },
          "response": []
        },
        {
          "name": "Update error log",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/admin/errors/{error_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "errors",
                "{error_id}"
              ],
              "variable": [
                {
                  "key": "error_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Mark error as resolved or add notes",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"resolved\": false,\n  \"notes\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Admin - Plans",
      "description": "5 endpoints",
      "item": [
        {
          "name": "Get all plan configurations",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/plans",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "plans"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Get current limits for all subscription plans"
          },
          "response": []
        },
        {
          "name": "Create a new plan",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/admin/plans",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "plans"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Create a custom subscription plan",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"plan_name\": \"string\",\n  \"max_products\": 0,\n  \"rate_limit_per_minute\": 0,\n  \"bulk_allowed\": false,\n  \"max_hits_per_month\": 0,\n  \"pricing\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a custom plan",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/plans/{plan_name}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "plans",
                "{plan_name}"
              ],
              "variable": [
                {
                  "key": "plan_name",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Delete a plan (only if no clients are using it)"
          },
          "response": []
        },
        {
          "name": "Update plan limits",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/admin/plans/{plan_name}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "plans",
                "{plan_name}"
              ],
              "variable": [
                {
                  "key": "plan_name",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Update the limits for a specific plan",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"plan_name\": \"string\",\n  \"max_products\": 0,\n  \"rate_limit_per_minute\": 0,\n  \"bulk_allowed\": false,\n  \"max_hits_per_month\": 0,\n  \"pricing\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Reset plan to defaults",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/plans/{plan_name}/reset",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "plans",
                "{plan_name}",
                "reset"
              ],
              "variable": [
                {
                  "key": "plan_name",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Reset plan limits to their default values"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Admin - Tests",
      "description": "3 endpoints",
      "item": [
        {
          "name": "Get latest test report",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/tests/report",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "tests",
                "report"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Returns the latest HTML test report"
          },
          "response": []
        },
        {
          "name": "Run system tests",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/tests/run",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "tests",
                "run"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Execute the integration test suite against the live API"
          },
          "response": []
        },
        {
          "name": "Get test runner status",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/tests/status",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "tests",
                "status"
              ]
            },
            "auth": {
              "type": "apikey",
              "apikey": [
                {
                  "key": "key",
                  "value": "X-Admin-Api-Key"
                },
                {
                  "key": "value",
                  "value": "{{admin_api_key}}"
                },
                {
                  "key": "in",
                  "value": "header"
                }
              ]
            },
            "description": "Check if tests are currently running and last run info"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Advanced Search",
      "description": "7 endpoints",
      "item": [
        {
          "name": "Get search history",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/history?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "history"
              ],
              "query": [
                {
                  "key": "offset",
                  "value": "0",
                  "description": "Number of records to skip",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Maximum records to return",
                  "disabled": true
                },
                {
                  "key": "search_type",
                  "value": "string",
                  "description": "Filter by search type",
                  "disabled": true
                },
                {
                  "key": "saved_only",
                  "value": "False",
                  "description": "Show only saved searches",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Retrieve search history for the authenticated client"
          },
          "response": []
        },
        {
          "name": "Delete search history",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/history/{history_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "history",
                "{history_id}"
              ],
              "variable": [
                {
                  "key": "history_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Delete a search history record"
          },
          "response": []
        },
        {
          "name": "Hybrid search",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/hybrid",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "hybrid"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Search using visual + text + colors + metadata filters",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_url\": \"string\",\n  \"query\": \"string\",\n  \"colors\": [\n    \"string\"\n  ],\n  \"color_threshold\": 50.0,\n  \"metadata_filters\": [],\n  \"limit\": 10,\n  \"threshold\": 0.0,\n  \"visual_weight\": 0.7\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Multi-image search",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/multi-image",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "multi-image"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Search using multiple images with aggregation",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_urls\": [\n    \"string\"\n  ],\n  \"aggregation\": \"average\",\n  \"limit\": 10,\n  \"threshold\": 0.0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Save a search",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/save",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "save"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Save a search with a custom name for later reuse",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"string\",\n  \"search_type\": \"string\",\n  \"query_text\": \"string\",\n  \"image_url\": \"string\",\n  \"filters\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get saved searches",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/saved",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "saved"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Retrieve all saved searches for the authenticated client"
          },
          "response": []
        },
        {
          "name": "Get search suggestions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/suggestions?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "suggestions"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "10",
                  "description": "Maximum suggestions",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get popular search suggestions based on history"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Authentication",
      "description": "4 endpoints",
      "item": [
        {
          "name": "Login with email and password",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/oauth/login",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "oauth",
                "login"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Authenticate using email and password to get an access token",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"string\",\n  \"password\": \"string\",\n  \"totp_code\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Refresh an access token",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/oauth/refresh",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "oauth",
                "refresh"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Exchange a still-valid (or *just*-expired, within grace window) bearer token for a fresh one. Revoked tokens are rejected. No refresh token is required \u2014 the old access token itself is the input (short-expiry sliding-window refresh). Rate-limited to 30/min per IP."
          },
          "response": []
        },
        {
          "name": "Revoke access token",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/oauth/revoke",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "oauth",
                "revoke"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "OAuth 2.0 Token Revocation (RFC 7009). Submit the token to revoke in the form body as `token` (application/x-www-form-urlencoded). The `Authorization: Bearer` header authenticates the caller \u2014 the bearer is NOT revoked unless it matches the submitted token. If `token` is omitted, the bearer token itself is revoked (legacy 'sign out' behaviour for UIs).",
            "body": {
              "mode": "urlencoded",
              "urlencoded": []
            }
          },
          "response": []
        },
        {
          "name": "Get access token",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/oauth/token",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "oauth",
                "token"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Exchange client credentials for an access token (OAuth 2.0 client_credentials grant)",
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "grant_type",
                  "value": "string",
                  "type": "text"
                },
                {
                  "key": "client_id",
                  "value": "string",
                  "type": "text"
                },
                {
                  "key": "client_secret",
                  "value": "string",
                  "type": "text"
                }
              ]
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Billing",
      "description": "6 endpoints",
      "item": [
        {
          "name": "Cancel subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/cancel",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "billing",
                "cancel"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Cancel the current subscription at end of billing period."
          },
          "response": []
        },
        {
          "name": "Create Stripe checkout session",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/checkout",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "billing",
                "checkout"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a Stripe Checkout Session to subscribe to a plan.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"plan_name\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get current plan and usage",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/current-plan",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "billing",
                "current-plan"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get the current plan details and usage stats."
          },
          "response": []
        },
        {
          "name": "Get invoice history",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/invoices",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "billing",
                "invoices"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get the client's invoice history from Stripe."
          },
          "response": []
        },
        {
          "name": "Open Stripe Customer Portal",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/portal",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "billing",
                "portal"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a Stripe Customer Portal session for managing payments."
          },
          "response": []
        },
        {
          "name": "Get current usage stats",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/usage",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "billing",
                "usage"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get current month's API usage statistics."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Client Portal",
      "description": "37 endpoints",
      "item": [
        {
          "name": "Stop A/B experiment",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/ab-experiment",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "ab-experiment"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Stop the active A/B experiment."
          },
          "response": []
        },
        {
          "name": "Get active A/B experiment",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/ab-experiment",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "ab-experiment"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get current A/B experiment status."
          },
          "response": []
        },
        {
          "name": "Create A/B experiment",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/ab-experiment",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "ab-experiment"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a new A/B experiment comparing two weight configs.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get client analytics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/analytics?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "analytics"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "Number of days to analyze",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get detailed usage analytics for the authenticated client"
          },
          "response": []
        },
        {
          "name": "Backfill quality scores for existing products",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/backfill-quality",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "backfill-quality"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Retroactively compute quality scores and indexed_at for products that were indexed before quality scoring was added"
          },
          "response": []
        },
        {
          "name": "Get branding settings",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/branding",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "branding"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get tenant's white-label branding configuration"
          },
          "response": []
        },
        {
          "name": "Update branding settings",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/branding",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "branding"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Customize white-label branding (Enterprise plan)",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Install demo products",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/demo",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "demo"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Install demo products for testing visual search",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"count\": 10,\n  \"pack\": \"fashion\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Find duplicate products",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/duplicates?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "duplicates"
              ],
              "query": [
                {
                  "key": "threshold",
                  "value": "0.95",
                  "description": "Similarity threshold",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Max products to scan",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Scan indexed products and find near-duplicate pairs (>95% similarity)"
          },
          "response": []
        },
        {
          "name": "Generate visual attention heatmap",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/heatmap",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "heatmap"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Shows which image regions the AI focuses on during search",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get client information",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/info",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "info"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get account information for the authenticated client"
          },
          "response": []
        },
        {
          "name": "Get language settings",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/languages",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "languages"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get tenant's multilingual configuration"
          },
          "response": []
        },
        {
          "name": "Update language settings",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/languages",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "languages"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Configure auto-translation and target languages",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get recent API hits",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/logs?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "logs"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "100",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "offset",
                  "value": "0",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "endpoint_filter",
                  "value": "string",
                  "description": "Filter by endpoint path",
                  "disabled": true
                },
                {
                  "key": "status_filter",
                  "value": "0",
                  "description": "Filter by HTTP status code",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "View the last 500 API requests for your account"
          },
          "response": []
        },
        {
          "name": "List downloadable log archives",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/logs/files",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "logs",
                "files"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List archived log files available for download"
          },
          "response": []
        },
        {
          "name": "Download a log archive file",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/logs/files/{filename}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "logs",
                "files",
                "{filename}"
              ],
              "variable": [
                {
                  "key": "filename",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Download a specific archived log file (JSONL format)"
          },
          "response": []
        },
        {
          "name": "Delete all products",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/products",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "products"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Delete all indexed products for the client"
          },
          "response": []
        },
        {
          "name": "Remove background and save processed image",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/products/{product_id}/remove-background",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "products",
                "{product_id}",
                "remove-background"
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Removes background, saves the clean image, updates the product to use it"
          },
          "response": []
        },
        {
          "name": "Reprocess a single product",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/products/{product_id}/reprocess",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "products",
                "{product_id}",
                "reprocess"
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Re-download image, remove background, recompute embedding and metadata"
          },
          "response": []
        },
        {
          "name": "Get my profile",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Return the LOGGED-IN identity's profile. If the JWT belongs to a team-member User, returns User-level fields (email, full_name) plus the parent tenant's client_name + plan as read-only context. If the JWT belongs to the Client owner, returns the full tenant-level profile including phone / timezone / logo. The flags `can_edit_branding` and `can_delete_account` tell the UI which controls to render."
          },
          "response": []
        },
        {
          "name": "Update my profile",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Patch any subset of profile fields the caller is allowed to edit.\n\n**Client owner** can patch: client_name, email, phone, timezone, logo_url. Changing the email re-flips email_verified to false.\n\n**Team-member User** can patch: full_name, email. Tenant fields (client_name / phone / timezone / logo_url) are 403.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"client_name\": \"string\",\n  \"full_name\": \"string\",\n  \"email\": \"user@example.com\",\n  \"phone\": \"string\",\n  \"timezone\": \"string\",\n  \"logo_url\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete my account",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile/delete",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile",
                "delete"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Self-serve account deletion. Requires both the current password and the literal confirmation string `DELETE`. Deactivates the client, drops the Qdrant collection (irreversible), and revokes all sessions. Billing rows + audit log are kept for compliance.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"confirmation\": \"string\",\n  \"password\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Export my catalog data",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile/export",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile",
                "export"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Returns a JSON export of the merchant's catalog \u2014 every Qdrant product payload (name, image, price, metadata) \u2014 plus profile info. Streams as `attachment` so the browser saves it. Vector embeddings are NOT included; they're rebuildable from images."
          },
          "response": []
        },
        {
          "name": "Change my password",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile/password",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile",
                "password"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Verify the current password, accept a new one, and revoke ALL existing access tokens. The caller's current token is invalidated too \u2014 they need to log in again afterwards.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"current_password\": \"string\",\n  \"new_password\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Revoke all OTHER sessions",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile/sessions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile",
                "sessions"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Revokes every active access token except the one used to make this request. Useful when you suspect a stolen token."
          },
          "response": []
        },
        {
          "name": "List my active sessions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile/sessions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile",
                "sessions"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Lists all access tokens issued for this account \u2014 non-revoked first. Use `DELETE /profile/sessions/{id}` to revoke a single one, or `DELETE /profile/sessions` to revoke every other session except the current call."
          },
          "response": []
        },
        {
          "name": "Revoke a single session",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/profile/sessions/{session_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "profile",
                "sessions",
                "{session_id}"
              ],
              "variable": [
                {
                  "key": "session_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Revoke a single session"
          },
          "response": []
        },
        {
          "name": "Get real-time rate limit usage",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/rate-usage",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "rate-usage"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "View current minute's API call count vs rate limit"
          },
          "response": []
        },
        {
          "name": "Get referral info",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/referral",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "referral"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get your unique referral code, link, and stats"
          },
          "response": []
        },
        {
          "name": "Re-process all product images",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/reprocess-images",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "reprocess-images"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Re-download and re-index all products with background removal, quality scoring, and type prediction"
          },
          "response": []
        },
        {
          "name": "Get custom search weights",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/search-weights",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "search-weights"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get the tenant's custom search re-ranking weights"
          },
          "response": []
        },
        {
          "name": "Set custom search weights",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/search-weights",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "search-weights"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Customize the search re-ranking weights for your account",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Calculate optimal search threshold",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/smart-threshold",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "smart-threshold"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Analyzes your product catalog to recommend the best similarity threshold"
          },
          "response": []
        },
        {
          "name": "Get client statistics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "stats"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get usage statistics for the authenticated client"
          },
          "response": []
        },
        {
          "name": "Bulk translate all products",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/translate-all",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "translate-all"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Auto-translate all existing products to configured target languages"
          },
          "response": []
        },
        {
          "name": "Get webhook delivery logs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/webhook-logs?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "webhook-logs"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "View recent webhook delivery attempts with retry status"
          },
          "response": []
        },
        {
          "name": "Get zero-result queries",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/client/zero-results?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "client",
                "zero-results"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "20",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "View queries that returned no results \u2014 identify gaps in your product catalog"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Custom Fields",
      "description": "4 endpoints",
      "item": [
        {
          "name": "List custom metadata fields",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/custom-fields",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "custom-fields"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List custom metadata fields"
          },
          "response": []
        },
        {
          "name": "Create a custom metadata field",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/custom-fields",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "custom-fields"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a custom metadata field",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"field_key\": \"string\",\n  \"display_name\": \"string\",\n  \"data_type\": \"string\",\n  \"enum_values\": [\n    \"string\"\n  ],\n  \"is_filterable\": true,\n  \"is_required\": false,\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a custom metadata field",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/custom-fields/{field_key}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "custom-fields",
                "{field_key}"
              ],
              "variable": [
                {
                  "key": "field_key",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Delete a custom metadata field"
          },
          "response": []
        },
        {
          "name": "Update a custom metadata field",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/custom-fields/{field_key}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "custom-fields",
                "{field_key}"
              ],
              "variable": [
                {
                  "key": "field_key",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Update a custom metadata field",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"display_name\": \"string\",\n  \"data_type\": \"string\",\n  \"enum_values\": [\n    \"string\"\n  ],\n  \"is_filterable\": false,\n  \"is_required\": false,\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Dashboard",
      "description": "5 endpoints",
      "item": [
        {
          "name": "Dashboard",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/dashboard",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "dashboard"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Serve the admin dashboard UI."
          },
          "response": []
        },
        {
          "name": "Developer Portal",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/developers",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "developers"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Serve the developer dashboard UI."
          },
          "response": []
        },
        {
          "name": "Client Portal",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/portal",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "portal"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Serve the client portal UI (login form / profile picker)."
          },
          "response": []
        },
        {
          "name": "Signup Page",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/signup",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "signup"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Serve the registration page."
          },
          "response": []
        },
        {
          "name": "Verify Page",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/verify",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "verify"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Serve the email verification page."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Developer Tools",
      "description": "5 endpoints",
      "item": [
        {
          "name": "Regenerate client secret",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/developer/credentials/regenerate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "developer",
                "credentials",
                "regenerate"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Generate a new client_secret. The old secret immediately becomes invalid."
          },
          "response": []
        },
        {
          "name": "Authenticated OpenAPI 3 specification",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/developer/openapi.json",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "developer",
                "openapi.json"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Returns the OpenAPI 3 spec for the Trooply integration surface \u2014 the endpoints an ecommerce-platform backend or storefront actually needs to call. Scope: auth (token / refresh), product indexing (POST / PUT / single DELETE / bulk / facets), job polling, the core and advanced search endpoints, NL \u2192 search, and the public-key widget search.\n\nExcluded from this spec (use the portal UI instead): merchant-portal CRUD for custom fields, search config, merchandising rules, widget keys, promo banners, and webhooks; billing; team management; admin; analytics; batch search; demo / seed utilities; OpenAI-compatible chat proxy; ops-only AI health + usage; and the collection-level DELETE /v1/products (catastrophic if called by mistake). A single-product DELETE remains available at DELETE /v1/products/{product_id}.\n\nRequires a valid bearer token."
          },
          "response": []
        },
        {
          "name": "Download Postman collection (integration surface)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/developer/postman/collection",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "developer",
                "postman",
                "collection"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Postman v2.1 collection scoped to the developer-integration surface \u2014 what an external developer needs to wire visual + text + voice search into their own platform. Excludes merchant-portal admin endpoints (custom fields CRUD, merchandising rules, promo banners, billing, team management, moderation, AI ops). Auth is included so the collection works out of the box."
          },
          "response": []
        },
        {
          "name": "Download Postman environment",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/developer/postman/environment",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "developer",
                "postman",
                "environment"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Generate a Postman environment pre-filled with your credentials"
          },
          "response": []
        },
        {
          "name": "Get developer quick stats",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/developer/quick-stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "developer",
                "quick-stats"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Quick stats for the developer dashboard overview."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Enhanced Search",
      "description": "19 endpoints",
      "item": [
        {
          "name": "Search analytics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/analytics?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "analytics"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get search analytics data (top queries, zero-result searches, etc.)"
          },
          "response": []
        },
        {
          "name": "Conversion attribution rollup (S10)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/analytics/conversion?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "analytics",
                "conversion"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "20",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "currency",
                  "value": "string",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Revenue attributed to each distinct shopper query in the window. Per-query numbers come from joining `search_feedback` rows where `action='purchase'` and `order_value` is non-null against their linked `search_history.query_text`. Powers the portal's conversion dashboard."
          },
          "response": []
        },
        {
          "name": "Conversion attribution segmented by search mode (#12)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/analytics/conversion-by-mode?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "analytics",
                "conversion-by-mode"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "currency",
                  "value": "string",
                  "description": "Filter to a single ISO-4217 currency (e.g. 'USD').",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Rolls up purchase feedback by which kind of search surfaced the result \u2014 text, image-URL, multipart upload, NL, widget-* variants \u2014 by joining `search_feedback` to `search_history` on `search_id` and grouping by `search_history.search_type`. Returns one row per (search_type, currency) pair. Powers the conversion-rate-by-mode panel on /portal/analytics. Rows where `search_id` is NULL (legacy feedback or feedback with no linked history row) collapse into `search_type='unattributed'`. Permission: `search:execute`."
          },
          "response": []
        },
        {
          "name": "Demand-vs-inventory gap report (#8)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/analytics/demand-gap?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "analytics",
                "demand-gap"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "20",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "min_count",
                  "value": "3",
                  "description": "Drop queries with fewer than this many total searches.",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Popular queries ranked by demand-to-inventory gap severity \u2014 a merchandising prompt list for the retailer. Combines two signals per query in the chosen window: raw search volume, and the fraction of those searches that returned zero or very few results.\n\nScoring: `gap_score = ln(1 + total) \u00d7 sqrt(zero_rate)`. Queries with a handful of zero-result hits don't score; queries that are frequent *and* frequently empty do. The report is actionable \u2014 each row is a candidate for a synonym mapping, a catalog gap, or a stock-ordering decision.\n\n`min_count` defaults to 3 to suppress one-offs. Per-tenant Redis cache 5 min. Permission: `search:execute`."
          },
          "response": []
        },
        {
          "name": "Filter usage analytics (S15)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/analytics/filters?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "analytics",
                "filters"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "top_values",
                  "value": "5",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Rollup of the `filters` dict merchants' shoppers passed on search calls. Returns, per field key, the hit count and top values. Drives the portal's facet-usage chart and helps merchandisers decide which custom fields are worth keeping in the filter sidebar."
          },
          "response": []
        },
        {
          "name": "Rising / trending queries (#8 seasonality)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/analytics/rising-searches?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "analytics",
                "rising-searches"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "Total analysis window. Must be >= 14 to leave a meaningful baseline after the 7-day recent slice.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "20",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "min_recent",
                  "value": "5",
                  "description": "Drop queries with fewer than this many searches in the last 7 days.",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Queries whose daily search rate in the last 7 days exceeds their rate over the preceding baseline. A lightweight seasonality signal for merchandising: stock up for queries on the way up; deprioritise homepage real-estate for ones on the way down.\n\nScoring: `rise_ratio = recent_daily_rate / max(\u03b5, prior_daily_rate)`. Queries with no prior activity in the window are flagged `is_new=true` and sorted above established queries at the same ratio. Queries are filtered to have `>= min_recent` hits in the last 7 days to suppress single-visit noise.\n\nPer-tenant Redis cache 10 min. Permission: `search:execute`."
          },
          "response": []
        },
        {
          "name": "Zero-result report (#8)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/analytics/zero-results?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "analytics",
                "zero-results"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "min_count",
                  "value": "2",
                  "description": "Drop queries with fewer than this many zero-result hits.",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Shopper queries that returned no products, ranked by how many times they were run. This is a demand-signal report for merchandising + inventory: high-volume misses tell you either (a) to add a synonym mapping, (b) to index stock you don't yet have, or (c) that the catalog has a dead zone the search engine can't bridge.\n\nGroup-by is case-insensitive (`lower(query_text)`) so 'Sneakers' and 'sneakers' collapse to one row. `min_count` defaults to 2 to suppress one-offs. Per-tenant Redis-cached 5 minutes so the portal dashboard doesn't re-aggregate on each refresh. Permission: `search:execute`."
          },
          "response": []
        },
        {
          "name": "Batch search",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/batch",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "batch"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Execute multiple search queries in a single request",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"queries\": [\n    {}\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Crop & region search",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/crop",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "crop"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Search using a cropped region of an image",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_url\": \"string\",\n  \"x\": 0,\n  \"y\": 0,\n  \"width\": 0,\n  \"height\": 0,\n  \"limit\": 10,\n  \"threshold\": 0.0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Record search feedback",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/feedback",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "feedback"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Record user click/purchase on a search result for relevance boosting",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"search_id\": \"string\",\n  \"query_product_id\": \"string\",\n  \"query_text\": \"string\",\n  \"result_product_id\": \"string\",\n  \"action\": \"click\",\n  \"session_id\": \"string\",\n  \"order_value\": 0,\n  \"currency\": \"string\",\n  \"quantity\": 0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get popular products from feedback",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/feedback/popular?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "feedback",
                "popular"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "20",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "action",
                  "value": "string",
                  "description": "Filter by action type",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Products most frequently clicked/purchased in search results"
          },
          "response": []
        },
        {
          "name": "Revenue attributed to search",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/feedback/revenue?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "feedback",
                "revenue"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "currency",
                  "value": "string",
                  "description": "Filter to a single currency (ISO 4217, e.g. 'USD'). Omit for a per-currency breakdown.",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Total attributed revenue + order count + AOV for purchase feedback events in the chosen window. Only aggregates rows where `order_value` was supplied on `action='purchase'`. Permission: `search:execute`."
          },
          "response": []
        },
        {
          "name": "Filtered search",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/filtered",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "filtered"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Search with Qdrant-level payload filters for exact field matching",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_url\": \"string\",\n  \"query\": \"string\",\n  \"filters\": {},\n  \"limit\": 10,\n  \"threshold\": 0.0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Frequently bought together",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/frequently-bought-with/{product_id}?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "frequently-bought-with",
                "{product_id}"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "90",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "10",
                  "description": "",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Products most often purchased in the same shopper session as the anchor product. Aggregates `search_feedback` rows grouped by `session_id` (strong signal) with `search_id` as a fallback for historical rows. Action weights: `purchase`=1.0, `add_to_cart`=0.5; clicks are ignored.\n\nScores are Laplace-smoothed by the anchor's own purchase count so bestsellers don't dominate every FBT strip. Results are cached per tenant+product for 5 minutes.\n\nReturns an empty `products` list when the anchor has zero purchase events in the window (nothing to co-purchase with)."
          },
          "response": []
        },
        {
          "name": "More Like This",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/similar/{product_id}?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "similar",
                "{product_id}"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "10",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "threshold",
                  "value": "0.0",
                  "description": "",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Find products visually similar to an existing product"
          },
          "response": []
        },
        {
          "name": "Trending search queries",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/trending?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "trending"
              ],
              "query": [
                {
                  "key": "window",
                  "value": "24h",
                  "description": "Rollup window. One of: 1h, 24h, 7d, 30d.",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "10",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "min_count",
                  "value": "2",
                  "description": "Drop queries with fewer than this many hits. Default 2 suppresses one-offs \u2014 typos, test traffic, accidental submits.",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Most-searched text queries in the chosen window, with their count and last-seen timestamp. Rolled up live from search history; per-tenant Redis-cached 5 minutes so opening the portal does not hammer Postgres. Permission: `search:execute`."
          },
          "response": []
        },
        {
          "name": "List webhooks",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "webhooks"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List all registered webhooks"
          },
          "response": []
        },
        {
          "name": "Register webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/webhooks",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "webhooks"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Register a webhook URL for product lifecycle events",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"string\",\n  \"events\": [\n    \"product.indexed\",\n    \"product.updated\",\n    \"product.deleted\"\n  ],\n  \"secret\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete webhook",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/webhooks/{webhook_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "webhooks",
                "{webhook_id}"
              ],
              "variable": [
                {
                  "key": "webhook_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Remove a webhook registration"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Health",
      "description": "1 endpoints",
      "item": [
        {
          "name": "Health Check",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/health",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "health"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Minimal public health probe \u2014 no implementation details leaked (BUG-005)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Invite Acceptance",
      "description": "2 endpoints",
      "item": [
        {
          "name": "Accept an invite (new user) or join with existing login",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/auth/invite/accept",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "auth",
                "invite",
                "accept"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Single endpoint for both flavours. Server picks the path based on whether a `users` row already exists for the invite's email. New users: provide `password` + optional `full_name` \u2014 User + Membership created atomically. Existing users: provide `password` (their existing password) \u2014 Membership added to their identity. Returns a fresh JWT with the new memberships embedded.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"token\": \"string\",\n  \"password\": \"string\",\n  \"full_name\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Resolve a magic-link invite token",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/auth/invite/{token}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "auth",
                "invite",
                "{token}"
              ],
              "variable": [
                {
                  "key": "token",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Public endpoint. The magic-link landing page calls this to decide what UI to show. Does NOT consume the invite \u2014 accept is a separate POST. Tokens not found / expired / used return 401."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Jobs",
      "description": "2 endpoints",
      "item": [
        {
          "name": "List jobs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/jobs?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "jobs"
              ],
              "query": [
                {
                  "key": "offset",
                  "value": "0",
                  "description": "Number of records to skip",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "20",
                  "description": "Maximum records to return",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List all bulk indexing jobs for this client"
          },
          "response": []
        },
        {
          "name": "Get job status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/jobs/{job_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "jobs",
                "{job_id}"
              ],
              "variable": [
                {
                  "key": "job_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get the status of a bulk indexing job"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Merchandising",
      "description": "4 endpoints",
      "item": [
        {
          "name": "List merchandising rules",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/merchandising/rules",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "merchandising",
                "rules"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List merchandising rules"
          },
          "response": []
        },
        {
          "name": "Create a merchandising rule",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/merchandising/rules",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "merchandising",
                "rules"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a merchandising rule",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"rule_type\": \"pin\",\n  \"scope_type\": \"always\",\n  \"scope_value\": \"string\",\n  \"product_ids\": [\n    \"string\"\n  ],\n  \"boost_multiplier\": 0,\n  \"priority\": 100,\n  \"is_active\": true,\n  \"start_at\": \"2026-01-01T00:00:00Z\",\n  \"end_at\": \"2026-01-01T00:00:00Z\",\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a merchandising rule",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/merchandising/rules/{rule_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "merchandising",
                "rules",
                "{rule_id}"
              ],
              "variable": [
                {
                  "key": "rule_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Delete a merchandising rule"
          },
          "response": []
        },
        {
          "name": "Update a merchandising rule",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/merchandising/rules/{rule_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "merchandising",
                "rules",
                "{rule_id}"
              ],
              "variable": [
                {
                  "key": "rule_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Update a merchandising rule",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"rule_type\": \"pin\",\n  \"scope_type\": \"always\",\n  \"scope_value\": \"string\",\n  \"product_ids\": [\n    \"string\"\n  ],\n  \"boost_multiplier\": 0,\n  \"priority\": 0,\n  \"is_active\": false,\n  \"start_at\": \"2026-01-01T00:00:00Z\",\n  \"end_at\": \"2026-01-01T00:00:00Z\",\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Moderation",
      "description": "4 endpoints",
      "item": [
        {
          "name": "Recent moderation decisions (read-only)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/moderation/events?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "moderation",
                "events"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "decision",
                  "value": "string",
                  "description": "Filter to rows with this decision ('allow' | 'flag' | 'block').",
                  "disabled": true
                },
                {
                  "key": "surface",
                  "value": "string",
                  "description": "Filter to rows from this surface ('index' | 'search_url' | 'search_upload' | 'search_crop' | 'bulk_index').",
                  "disabled": true
                },
                {
                  "key": "days",
                  "value": "7",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Paginated list of the last-N moderation scans for this tenant. One row per scan with the per-category scores, decision, and which categories flagged. Drives the portal's Moderation Events table. Permission: `search:advanced`."
          },
          "response": []
        },
        {
          "name": "Read moderation policy",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/moderation/policy",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "moderation",
                "policy"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Returns the tenant's current `{mode, enforce, thresholds}` plus the platform-default thresholds and the enforced-category list for the current mode. Creates a default row (mode=shadow, enforce=false) on first read if the tenant has none yet."
          },
          "response": []
        },
        {
          "name": "Update moderation policy",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/moderation/policy",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "moderation",
                "policy"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Partial update of the tenant's moderation policy. Only fields present in the request body are modified. `thresholds` fully replaces the stored dict when provided \u2014 the UI reads the current value first and sends the merged result back.\n\nFlipping `enforce` from false to true starts blocking images on the next request. Do this only after a week of shadow-mode data confirms the threshold distribution is where you want it.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"mode\": \"shadow\",\n  \"enforce\": false,\n  \"thresholds\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Moderation shadow-mode summary",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/moderation/summary?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "moderation",
                "summary"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "7",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Aggregate counts over the window: total scans, per-decision breakdown (allow / flag / block), per-category flag counts, and the number of would-blocks shadow mode let through. Feeds the portal's distribution cards. Permission: `search:advanced`."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Products",
      "description": "15 endpoints",
      "item": [
        {
          "name": "Delete all products",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Delete all indexed products for the client"
          },
          "response": []
        },
        {
          "name": "List products",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products"
              ],
              "query": [
                {
                  "key": "offset",
                  "value": "0",
                  "description": "Number of records to skip",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "100",
                  "description": "Maximum records to return",
                  "disabled": true
                },
                {
                  "key": "locale",
                  "value": "string",
                  "description": "Return metadata in this locale",
                  "disabled": true
                },
                {
                  "key": "q",
                  "value": "string",
                  "description": "Substring match on name / product_id",
                  "disabled": true
                },
                {
                  "key": "category",
                  "value": "string",
                  "description": "Exact match on metadata.category",
                  "disabled": true
                },
                {
                  "key": "predicted_type",
                  "value": "string",
                  "description": "Exact match on metadata.predicted_type",
                  "disabled": true
                },
                {
                  "key": "price_min",
                  "value": "0",
                  "description": "Minimum price",
                  "disabled": true
                },
                {
                  "key": "price_max",
                  "value": "0",
                  "description": "Maximum price",
                  "disabled": true
                },
                {
                  "key": "min_quality",
                  "value": "0",
                  "description": "Minimum quality score (0..1)",
                  "disabled": true
                },
                {
                  "key": "has_image",
                  "value": "False",
                  "description": "true = only products with image_url; false = only without",
                  "disabled": true
                },
                {
                  "key": "sort",
                  "value": "string",
                  "description": "Sort field: name|price|quality|indexed_at",
                  "disabled": true
                },
                {
                  "key": "sort_dir",
                  "value": "string",
                  "description": "asc|desc (default desc)",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List indexed products with optional filters, sort and pagination. All filter params are optional; `q` does a case-insensitive substring match over the product name and product_id."
          },
          "response": []
        },
        {
          "name": "Index a product",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Index a single product image for visual search",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"product_id\": \"string\",\n  \"image_url\": \"string\",\n  \"image_urls\": [\n    \"string\"\n  ],\n  \"metadata\": {},\n  \"locales\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Bulk index products",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/bulk",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "bulk"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a background job to index multiple products",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"products\": [\n    {}\n  ],\n  \"callback_url\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Check for duplicate products",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/check-duplicates",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "check-duplicates"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Check if an image has near-duplicate products in the index",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"product_id\": \"string\",\n  \"image_url\": \"string\",\n  \"image_urls\": [\n    \"string\"\n  ],\n  \"metadata\": {},\n  \"locales\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Install demo products",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/demo",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "demo"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Install demo products from an industry pack (fashion, electronics, home)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"count\": 10,\n  \"pack\": \"fashion\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "List available demo packs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/demo/packs",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "demo",
                "packs"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get a list of industry-specific demo product packs"
          },
          "response": []
        },
        {
          "name": "Product filter facets",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/facets",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "facets"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Return distinct filter values (categories, predicted types, price/quality ranges, image-presence counts) for populating the portal filter bar dropdowns."
          },
          "response": []
        },
        {
          "name": "Catalogue-wide image-quality audit",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/quality-audit?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "quality-audit"
              ],
              "query": [
                {
                  "key": "worst_n",
                  "value": "20",
                  "description": "How many worst products to return",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Scrolls every product and returns the quality-tier distribution, average score, top-N lowest-quality products with actionable photography fix hints, and a rollup of which problems occur most often. Trooply-unique insight \u2014 merchants use this to find the product images hurting their conversion and know what to re-shoot."
          },
          "response": []
        },
        {
          "name": "Get product statistics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/stats",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "stats"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get statistics about indexed products"
          },
          "response": []
        },
        {
          "name": "Index a product with multiple variants",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/with-variants",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "with-variants"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Index a parent product together with N size / colour / pattern variants. Each variant is stored as its own CLIP point in Qdrant (own image, own embedding, own payload) and tagged with `parent_product_id` so the widget and `GET /v1/products/{id}/variants` can group siblings.\n\nWhy separate points per variant: shoppers searching by image of a red T-shirt should rank the red variant first, not the generic parent. Collapsing siblings into one row loses that visual signal.\n\nEach variant counts as one product against your plan's quota. A 5-colour \u00d7 3-size shirt = 15 products billed. Use `collapse_variants=true` on search endpoints to deduplicate at render time while still ranking variant-accurately.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"product_id\": \"string\",\n  \"metadata\": {},\n  \"variants\": [\n    {}\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a product",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/{product_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "{product_id}"
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Remove a product from the search index"
          },
          "response": []
        },
        {
          "name": "Get a product",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/{product_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "{product_id}"
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get a single product's metadata"
          },
          "response": []
        },
        {
          "name": "Update a product",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/{product_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "{product_id}"
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Update a product's image and/or metadata",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_url\": \"string\",\n  \"image_urls\": [\n    \"string\"\n  ],\n  \"metadata\": {},\n  \"locales\": {}\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "List sibling variants of a product (S14)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/products/{product_id}/variants?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "products",
                "{product_id}",
                "variants"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Return every variant that shares `parent_product_id` with the given product (or every variant of the given product if it's the parent). Uses a Qdrant payload-filter scroll, so response time is O(variant count), not O(catalog size).\n\nTypical shopper-side use: render an 'Other colours' chip strip on a product card when the current result has `metadata.parent_product_id` set."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Promo Banners",
      "description": "4 endpoints",
      "item": [
        {
          "name": "List promo banners",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/promo-banners",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "promo-banners"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List promo banners"
          },
          "response": []
        },
        {
          "name": "Create a promo banner",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/promo-banners",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "promo-banners"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a promo banner",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"string\",\n  \"body\": \"string\",\n  \"cta_text\": \"string\",\n  \"cta_url\": \"string\",\n  \"image_url\": \"string\",\n  \"background_color\": \"string\",\n  \"foreground_color\": \"string\",\n  \"position\": \"top\",\n  \"scope_type\": \"always\",\n  \"scope_value\": \"string\",\n  \"priority\": 100,\n  \"is_active\": true,\n  \"start_at\": \"2026-01-01T00:00:00Z\",\n  \"end_at\": \"2026-01-01T00:00:00Z\",\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a promo banner",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/promo-banners/{banner_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "promo-banners",
                "{banner_id}"
              ],
              "variable": [
                {
                  "key": "banner_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Delete a promo banner"
          },
          "response": []
        },
        {
          "name": "Update a promo banner",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/promo-banners/{banner_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "promo-banners",
                "{banner_id}"
              ],
              "variable": [
                {
                  "key": "banner_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Update a promo banner",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"title\": \"string\",\n  \"body\": \"string\",\n  \"cta_text\": \"string\",\n  \"cta_url\": \"string\",\n  \"image_url\": \"string\",\n  \"background_color\": \"string\",\n  \"foreground_color\": \"string\",\n  \"position\": \"top\",\n  \"scope_type\": \"always\",\n  \"scope_value\": \"string\",\n  \"priority\": 0,\n  \"is_active\": false,\n  \"start_at\": \"2026-01-01T00:00:00Z\",\n  \"end_at\": \"2026-01-01T00:00:00Z\",\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Registration",
      "description": "3 endpoints",
      "item": [
        {
          "name": "Register a new account",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/auth/register",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "auth",
                "register"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Create a new account. A verification email will be sent.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"client_name\": \"string\",\n  \"email\": \"user@example.com\",\n  \"password\": \"string\",\n  \"referral_code\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Resend verification email",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/auth/resend-verification",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "auth",
                "resend-verification"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Resend the email verification link.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"user@example.com\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Verify email address",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/auth/verify?token=string",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "auth",
                "verify"
              ],
              "query": [
                {
                  "key": "token",
                  "value": "string",
                  "description": "Verification token",
                  "disabled": false
                }
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Verify email using the token sent via email."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Root",
      "description": "1 endpoints",
      "item": [
        {
          "name": "Api Info",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Root API endpoint with service information."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Sandbox",
      "description": "1 endpoints",
      "item": [
        {
          "name": "Get instant sandbox API credentials",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/sandbox",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "sandbox"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a temporary sandbox account (10 products, 24h expiry).\n\nProvisions a real Client row + AccessToken so the returned token works\nagainst all authenticated endpoints. Rows are marked `notes='sandbox:...'`\nso a cleanup job can reap expired sandboxes."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Search",
      "description": "6 endpoints",
      "item": [
        {
          "name": "Search by image",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Search for similar products using an image (upload or URL)",
            "body": {
              "mode": "formdata",
              "formdata": []
            }
          },
          "response": []
        },
        {
          "name": "Instant-search autocomplete (type-ahead)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/autocomplete?q=string",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "autocomplete"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "string",
                  "description": "Partial query the shopper has typed.",
                  "disabled": false
                },
                {
                  "key": "limit",
                  "value": "5",
                  "description": "Max product previews to return.",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Sub-50 ms type-ahead endpoint for the widget dropdown. Returns two parallel lookups in one call: (a) the top historical query completions for the shopper's partial input (grouped by `lower(query_text)`, sorted by 30-day popularity), and (b) preview product cards matched by CLIP text similarity against the partial.\n\nSkips the heavy rerank pipeline (popularity boost, per-category scoring profiles, merchandising rules, session personalisation) because latency on the dropdown trumps ranking fidelity \u2014 the shopper is still typing. Once they commit, route to `/v1/search/text` for the full-quality response.\n\nThe Redis cache on completions is 60 s per `(tenant, prefix)` and the CLIP text embedding is shared with the main search path. A single shopper hammering the field at 5 chars per second pays Postgres once, the GPU once, and Qdrant on every keystroke (which is the fast part)."
          },
          "response": []
        },
        {
          "name": "Multi-modal fusion search",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/fusion",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "fusion"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Combine image and text for refined search. Example: upload a red dress image + text 'in blue' to find blue dresses.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_url\": \"string\",\n  \"query\": \"string\",\n  \"image_weight\": 0.6,\n  \"limit\": 10,\n  \"threshold\": 0.0,\n  \"category\": \"string\",\n  \"price_min\": 0,\n  \"price_max\": 0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Search by text",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/text",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "text"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Search for products using a text description (CLIP text-to-image)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"query\": \"string\",\n  \"limit\": 10,\n  \"threshold\": 0.0,\n  \"locale\": \"string\",\n  \"filters\": {},\n  \"session_id\": \"string\",\n  \"collapse_variants\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Search by image URL",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/url",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "url"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Search for similar products using an image URL (JSON body)",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_url\": \"string\",\n  \"limit\": 10,\n  \"threshold\": 0.0,\n  \"locale\": \"string\",\n  \"filters\": {},\n  \"session_id\": \"string\",\n  \"collapse_variants\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Search by voice (speech-to-text + text search)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search/voice",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search",
                "voice"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Accepts a short audio clip, transcribes it via Gemma 4 E4B's native audio capability, and runs the transcript through the same CLIP + Qdrant pipeline as `/v1/search/text`. Intended for a browser MediaRecorder blob \u2014 WebM/Opus works best; WAV, MP3, M4A also accepted.\n\nResponse includes both the transcript and the results so the storefront can show *\"Searching for: red nike shoes\"* above the grid.",
            "body": {
              "mode": "formdata",
              "formdata": []
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Search Config",
      "description": "6 endpoints",
      "item": [
        {
          "name": "Get tenant stop-word list",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search-config/stopwords",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search-config",
                "stopwords"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get tenant stop-word list"
          },
          "response": []
        },
        {
          "name": "Replace tenant stop-word list",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search-config/stopwords",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search-config",
                "stopwords"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Replace tenant stop-word list",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"words\": [\n    \"string\"\n  ],\n  \"is_active\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "List synonym groups",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search-config/synonyms",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search-config",
                "synonyms"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "List synonym groups"
          },
          "response": []
        },
        {
          "name": "Create a synonym group",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search-config/synonyms",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search-config",
                "synonyms"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a synonym group",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"terms\": [\n    \"string\"\n  ],\n  \"is_active\": true,\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a synonym group",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search-config/synonyms/{group_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search-config",
                "synonyms",
                "{group_id}"
              ],
              "variable": [
                {
                  "key": "group_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Delete a synonym group"
          },
          "response": []
        },
        {
          "name": "Update a synonym group",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/search-config/synonyms/{group_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "search-config",
                "synonyms",
                "{group_id}"
              ],
              "variable": [
                {
                  "key": "group_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Update a synonym group",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"terms\": [\n    \"string\"\n  ],\n  \"is_active\": false,\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Security",
      "description": "16 endpoints",
      "item": [
        {
          "name": "Disable 2FA",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/2fa/disable",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "2fa",
                "disable"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Disable 2FA for the account",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"totp_code\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Enable 2FA",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/2fa/enable",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "2fa",
                "enable"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Verify TOTP code and enable 2FA for the account",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"totp_code\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Initialize 2FA setup",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/2fa/setup",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "2fa",
                "setup"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Generate TOTP secret and QR code for 2FA setup"
          },
          "response": []
        },
        {
          "name": "Get 2FA status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/2fa/status",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "2fa",
                "status"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Check if 2FA is enabled for the current user"
          },
          "response": []
        },
        {
          "name": "List API keys",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/api-keys",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "api-keys"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get all API keys for the current client"
          },
          "response": []
        },
        {
          "name": "Create API key",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/api-keys",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "api-keys"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Create a new scoped API key with specific permissions",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"string\",\n  \"scopes\": {},\n  \"expires_in_days\": 0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get scope examples",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/api-keys/scope-examples",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "api-keys",
                "scope-examples"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get example API key scope configurations"
          },
          "response": []
        },
        {
          "name": "Revoke API key",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/api-keys/{key_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "api-keys",
                "{key_id}"
              ],
              "variable": [
                {
                  "key": "key_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Revoke (deactivate) an API key"
          },
          "response": []
        },
        {
          "name": "Get IP whitelist",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/ip-whitelist",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "ip-whitelist"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get all IP whitelist entries for the current client"
          },
          "response": []
        },
        {
          "name": "Add IP to whitelist",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/ip-whitelist",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "ip-whitelist"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Add an IP address or CIDR range to the whitelist",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"ip_address\": \"string\",\n  \"description\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Remove IP from whitelist",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/ip-whitelist/{entry_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "ip-whitelist",
                "{entry_id}"
              ],
              "variable": [
                {
                  "key": "entry_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Remove an IP address from the whitelist"
          },
          "response": []
        },
        {
          "name": "Toggle IP whitelist entry",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/ip-whitelist/{entry_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "ip-whitelist",
                "{entry_id}"
              ],
              "variable": [
                {
                  "key": "entry_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Enable or disable an IP whitelist entry",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"is_active\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get security overview",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/overview",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "overview"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get overview of all security settings for the current client"
          },
          "response": []
        },
        {
          "name": "Check permissions",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/permissions/check",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "permissions",
                "check"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Check if current client has specific permissions",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"permission_names\": [\n    \"string\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Get my permissions",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/permissions/me",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "permissions",
                "me"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get all permissions for the current client (from all roles)"
          },
          "response": []
        },
        {
          "name": "Get my roles",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/security/roles/me",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "security",
                "roles",
                "me"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Get all roles assigned to the current client"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Super Admin",
      "description": "2 endpoints",
      "item": [
        {
          "name": "Member counts per store (super-admin)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/sa/clients/member-counts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "sa",
                "clients",
                "member-counts"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Augments the existing /admin/clients listing with per-store member count, computed from `user_memberships`. Useful for the super-admin dashboard's 'how lonely is this store' column."
          },
          "response": []
        },
        {
          "name": "Cross-store user list (super-admin)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/admin/sa/users?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "admin",
                "sa",
                "users"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "string",
                  "description": "Search email or name",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "offset",
                  "value": "0",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Returns every user on the platform with their full membership list embedded. Pagination via `limit` + `offset`. Optional `q` does a case-insensitive substring match on email + full_name. Requires JWT with `is_super_admin: true`."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Team & Invites",
      "description": "5 endpoints",
      "item": [
        {
          "name": "Invite someone to the active store",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/team/invite",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "team",
                "invite"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Creates a `user_invites` row, mints a single-use magic-link token (SHA-256 hashed at rest, raw token only in the email), and sends a branded invite email. If the invitee already has a `users` row the email tells them to sign in with their existing password. If not, the link takes them to a set-password page. Owner-only.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"user@example.com\",\n  \"role\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Cancel a pending invite",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/team/invites/{invite_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "team",
                "invites",
                "{invite_id}"
              ],
              "variable": [
                {
                  "key": "invite_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Removes the `user_invites` row before the invitee accepts. Owner-only."
          },
          "response": []
        },
        {
          "name": "List members of the active store",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/team/members",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "team",
                "members"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Lists every user with a `user_memberships` row for the active store, plus any pending invites that haven't been accepted yet. Owner-only."
          },
          "response": []
        },
        {
          "name": "Remove a member from the active store",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/team/members/{user_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "team",
                "members",
                "{user_id}"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Drops the `user_memberships` row for (user_id, active_store). The user keeps their global identity and access to other stores. Cannot remove the last owner. Owner-only."
          },
          "response": []
        },
        {
          "name": "Change a member's role",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/team/members/{user_id}/role",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "team",
                "members",
                "{user_id}",
                "role"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Update the role on the `user_memberships` row for (user_id, active_store). Cannot demote the last owner. Owner-only.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"role\": \"string\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Users & Groups",
      "description": "15 endpoints",
      "item": [
        {
          "name": "DEPRECATED \u2014 group rewrite pending",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/user-groups",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "user-groups"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 group rewrite pending"
          },
          "response": []
        },
        {
          "name": "DEPRECATED",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/user-groups",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "user-groups"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED"
          },
          "response": []
        },
        {
          "name": "DEPRECATED",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/user-groups/permissions",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "user-groups",
                "permissions"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED"
          },
          "response": []
        },
        {
          "name": "DEPRECATED",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/user-groups/{group_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "user-groups",
                "{group_id}"
              ],
              "variable": [
                {
                  "key": "group_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED"
          },
          "response": []
        },
        {
          "name": "DEPRECATED",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/user-groups/{group_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "user-groups",
                "{group_id}"
              ],
              "variable": [
                {
                  "key": "group_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED"
          },
          "response": []
        },
        {
          "name": "DEPRECATED",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/user-groups/{group_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "user-groups",
                "{group_id}"
              ],
              "variable": [
                {
                  "key": "group_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 use GET /v1/team/members",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 use GET /v1/team/members"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 use POST /v1/team/invite",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 use POST /v1/team/invite"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 use the JWT claims directly",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/me",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users",
                "me"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 use the JWT claims directly"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 use DELETE /v1/team/members/{user_id}",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/{user_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 use DELETE /v1/team/members/{user_id}"
          },
          "response": []
        },
        {
          "name": "DEPRECATED",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/{user_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 use PATCH /v1/team/members/{user_id}/role",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/{user_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 use PATCH /v1/team/members/{user_id}/role"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 not yet ported",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/{user_id}/active",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}",
                "active"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 not yet ported"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 not yet ported",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/{user_id}/impersonate",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}",
                "impersonate"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 not yet ported"
          },
          "response": []
        },
        {
          "name": "DEPRECATED \u2014 cancel + re-invite",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-Trooply-Active-Tenant",
                "value": "{{tenant_slug}}",
                "type": "text",
                "description": "Slug of the active store. Required for users with 2+ memberships; optional fallback to single-membership for single-store users."
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/{user_id}/resend-invite",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "users",
                "{user_id}",
                "resend-invite"
              ],
              "variable": [
                {
                  "key": "user_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "DEPRECATED \u2014 cancel + re-invite"
          },
          "response": []
        }
      ]
    },
    {
      "name": "Webhooks",
      "description": "1 endpoints",
      "item": [
        {
          "name": "Stripe webhook endpoint",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/webhooks/stripe",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "webhooks",
                "stripe"
              ]
            },
            "auth": {
              "type": "bearer",
              "bearer": [
                {
                  "key": "token",
                  "value": "{{access_token}}"
                }
              ]
            },
            "description": "Handles Stripe webhook events. No authentication required (uses signature verification)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Widget Keys",
      "description": "4 endpoints",
      "item": [
        {
          "name": "List widget keys",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/widget-keys",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget-keys"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "List widget keys"
          },
          "response": []
        },
        {
          "name": "Create a widget key",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/widget-keys",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget-keys"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Create a widget key",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"Widget key\",\n  \"allowed_origins\": [\n    \"string\"\n  ],\n  \"rate_limit_per_min\": 60,\n  \"is_active\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Delete a widget key",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/widget-keys/{key_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget-keys",
                "{key_id}"
              ],
              "variable": [
                {
                  "key": "key_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Delete a widget key"
          },
          "response": []
        },
        {
          "name": "Update a widget key",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/widget-keys/{key_id}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget-keys",
                "{key_id}"
              ],
              "variable": [
                {
                  "key": "key_id",
                  "value": "00000000-0000-0000-0000-000000000000",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Update a widget key",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"string\",\n  \"allowed_origins\": [\n    \"string\"\n  ],\n  \"rate_limit_per_min\": 0,\n  \"is_active\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Widget Search",
      "description": "6 endpoints",
      "item": [
        {
          "name": "Widget: instant-search autocomplete (public-key auth)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/widget/search/autocomplete?q=string",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget",
                "search",
                "autocomplete"
              ],
              "query": [
                {
                  "key": "q",
                  "value": "string",
                  "description": "",
                  "disabled": false
                },
                {
                  "key": "limit",
                  "value": "5",
                  "description": "",
                  "disabled": true
                }
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Origin-bound type-ahead for the drop-in widget. Same shape and same Redis / Qdrant plumbing as the admin `/v1/search/autocomplete`, authenticated via the `pk_live_\u2026` key in the `X-Trooply-Key` header. Called on every keystroke (debounced 150 ms in the widget)."
          },
          "response": []
        },
        {
          "name": "Widget: record search feedback (public-key auth)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/widget/search/feedback",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget",
                "search",
                "feedback"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Origin-bound feedback recorder for the drop-in widget. Required: `result_product_id` and `action` (`click` | `add_to_cart` | `purchase`). When `action='purchase'`, supply `order_value` (decimal) and `currency` (ISO-4217) for revenue attribution; `quantity` defaults to 1 when omitted. Unknown actions return 422.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"search_id\": \"string\",\n  \"query_product_id\": \"string\",\n  \"query_text\": \"string\",\n  \"result_product_id\": \"string\",\n  \"action\": \"click\",\n  \"session_id\": \"string\",\n  \"order_value\": 0,\n  \"currency\": \"string\",\n  \"quantity\": 0\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Widget: frequently-bought-together (public-key auth)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/widget/search/frequently-bought-with/{product_id}?",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget",
                "search",
                "frequently-bought-with",
                "{product_id}"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "90",
                  "description": "",
                  "disabled": true
                },
                {
                  "key": "limit",
                  "value": "6",
                  "description": "",
                  "disabled": true
                }
              ],
              "variable": [
                {
                  "key": "product_id",
                  "value": "string",
                  "description": ""
                }
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Returns products most often purchased alongside the anchor in the same shopper session. Same engine as the admin endpoint at `/v1/search/frequently-bought-with/{product_id}` \u2014 aggregated from `search_feedback` rows grouped by `session_id` with `search_id` as a fallback. Origin-bound via the widget's `pk_live_\u2026` key. Cached for 5 minutes per (tenant, product)."
          },
          "response": []
        },
        {
          "name": "Widget: text search (public-key auth)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/widget/search/text",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget",
                "search",
                "text"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Origin-bound text search for the drop-in widget. Requires a `pk_live_\u2026` key in the `X-Trooply-Key` header; the request Origin must match one allow-listed for that key.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"query\": \"string\",\n  \"limit\": 10,\n  \"threshold\": 0.0,\n  \"locale\": \"string\",\n  \"filters\": {},\n  \"session_id\": \"string\",\n  \"collapse_variants\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        },
        {
          "name": "Widget: search by direct image upload (public-key auth)",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/widget/search/upload",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget",
                "search",
                "upload"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Origin-bound visual search for the drop-in widget \u2014 accepts a direct multipart image upload from the shopper's browser. Counterpart to `/search/url`; use this when you don't have a URL to point at (drag-and-drop, file picker, paste-from-clipboard).",
            "body": {
              "mode": "formdata",
              "formdata": []
            }
          },
          "response": []
        },
        {
          "name": "Widget: search by image URL (public-key auth)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/widget/search/url",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "v1",
                "widget",
                "search",
                "url"
              ]
            },
            "auth": {
              "type": "noauth"
            },
            "description": "Origin-bound visual search for the drop-in widget \u2014 shopper uploads an image that the widget uploads elsewhere and passes the URL here. For direct-from-browser uploads, use `/v1/widget/search/upload`.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"image_url\": \"string\",\n  \"limit\": 10,\n  \"threshold\": 0.0,\n  \"locale\": \"string\",\n  \"filters\": {},\n  \"session_id\": \"string\",\n  \"collapse_variants\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{access_token}}"
      }
    ]
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://search.trooply.ai",
      "type": "string"
    },
    {
      "key": "access_token",
      "value": "",
      "type": "string",
      "description": "JWT from POST /oauth/login or POST /oauth/token"
    },
    {
      "key": "admin_api_key",
      "value": "",
      "type": "string",
      "description": "Server env ADMIN_API_KEY \u2014 only needed for legacy /admin/* endpoints"
    },
    {
      "key": "tenant_slug",
      "value": "",
      "type": "string",
      "description": "Active store slug for multi-membership users (e.g. 'acme-store')"
    }
  ]
}