MPSTATS API MPSTATS is a Russian marketplace analytics platform with data on Wildberries, Ozon, and Yandex Market: product research, category analysis, seller/brand monitoring, SKU-level sales, stock, and review data. Work through the ready-made shell scripts in — call them via the Bash tool instead of writing HTTP code. Reference files in are API contracts only. Token setup Scripts auto-load the token from via . A per-command env var overrides the file. Setup and where to get the token: . If the token is missing, offer the user exactly 2 options before continuing: 1. User sends the token in…

; then\n URL=\"$BASE_URL/seller/compare?${QUERY}&path=${VALUE}\"\n else\n ENCODED=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$VALUE\" 2>/dev/null || node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$VALUE\" 2>/dev/null || printf '%s' \"$VALUE\" | sed 's/ /%20/g')\n URL=\"$BASE_URL/seller/compare?${QUERY}&path=${ENCODED}\"\n fi\n ;;\n *)\n echo \"scope must be one of: category | brand | seller\" >&2\n exit 1\n ;;\nesac\n\ncurl -s --location --request POST \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[]}\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2352,"content_sha256":"d3bec5871594304cda2ef76fe53009ddf32e442a87117c20cca059adb23ffd83"},{"filename":"scripts/ozon/ozon-seller.sh","content":"#!/bin/bash\n# ozon-seller.sh — Get products or analytics for an Ozon seller\n# Usage: ./ozon-seller.sh \u003cseller_id_or_name> [report] [d1] [d2] [limit] [fbs] [newsmode]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cseller_id_or_name> [report] [d1] [d2] [limit] [fbs] [newsmode]\"\n echo \" seller_id_or_name — Ozon seller ID (numeric) or seller name (path)\"\n echo \" report — products (default), categories, brands, by_date, price_segmentation, trends, keywords, niches, geography\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max results for products report, 1-5000 (default: 100)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \" newsmode — only new products for last N days: 7|14|30 (optional)\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSELLER_INPUT=\"$1\"\nREPORT=\"${2:-products}\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${5:-100}\"\nFBS=\"${6:-0}\"\nNEWSMODE=\"$7\"\n\n# In new API, seller_id is passed via path param\nif printf '%s' \"$SELLER_INPUT\" | grep -Eq '^[0-9]+

MPSTATS API MPSTATS is a Russian marketplace analytics platform with data on Wildberries, Ozon, and Yandex Market: product research, category analysis, seller/brand monitoring, SKU-level sales, stock, and review data. Work through the ready-made shell scripts in — call them via the Bash tool instead of writing HTTP code. Reference files in are API contracts only. Token setup Scripts auto-load the token from via . A per-command env var overrides the file. Setup and where to get the token: . If the token is missing, offer the user exactly 2 options before continuing: 1. User sends the token in…

; then\n SELLER_QUERY=\"path=${SELLER_INPUT}\"\nelse\n ENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SELLER_INPUT\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$SELLER_INPUT\" 2>/dev/null || \\\n printf '%s' \"$SELLER_INPUT\" | sed 's/ /%20/g')\n SELLER_QUERY=\"path=${ENCODED_PATH}\"\nfi\n\nBASE_URL=\"https://mpstats.io/api/analytics/v1/oz/seller\"\n\nQUERY=\"d1=${D1}&d2=${D2}&${SELLER_QUERY}&fbs=${FBS}\"\nif [ -n \"$NEWSMODE\" ]; then\n QUERY=\"${QUERY}&newsmode=${NEWSMODE}\"\nfi\n\n# Map report name to endpoint\ncase \"$REPORT\" in\n products) ENDPOINT=\"items\" ;;\n *) ENDPOINT=\"$REPORT\" ;;\nesac\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"${BASE_URL}/${ENDPOINT}?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\nelif [ \"$REPORT\" = \"geography\" ]; then\n GEO_DATE=\"${D1:0:7}\"\n curl -s --location --request GET \\\n \"${BASE_URL}/${ENDPOINT}?${SELLER_QUERY}&date=${GEO_DATE}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nelse\n curl -s --location --request POST \\\n \"${BASE_URL}/${ENDPOINT}?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data '{}'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2890,"content_sha256":"55da847b11cd68f887d22ea91711f0bd262b905825ac1a74a9d148496712dc40"},{"filename":"scripts/ozon/ozon-sku.sh","content":"#!/bin/bash\n# ozon-sku.sh — Ozon SKU-level endpoints\n# Usage: ./ozon-sku.sh \u003csku> [report] [d1] [d2] [fbs] [d]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003csku> [report] [d1] [d2] [fbs] [d]\"\n echo \" sku — Ozon product ID (numeric), e.g. 1252420260\"\n echo \" report — sales (default), by_day, balance, categories, keywords, full, by_period, search_stats, stores, comments\"\n echo \" d1 — start date YYYY-MM-DD (for sales/categories/keywords/by_period/search_stats)\"\n echo \" d2 — end date YYYY-MM-DD (for sales/categories/keywords/by_period/search_stats)\"\n echo \" fbs — include FBS: 0 or 1 (for sales/balance)\"\n echo \" d — point date YYYY-MM-DD (required for by_day/balance)\"\n echo \"\"\n echo \"Examples:\"\n echo \" $0 1252420260 sales 2023-12-12 2023-12-25\"\n echo \" $0 1252420260 by_day '' '' '' 2023-12-26\"\n echo \" $0 1252420260 balance '' '' 1 2023-12-26\"\n echo \" $0 1252420260 categories 2023-12-19 2023-12-26\"\n echo \" $0 1252420260 full\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSKU=\"$1\"\nREPORT=\"${2:-sales}\"\nD1=\"$3\"\nD2=\"$4\"\nFBS=\"$5\"\nPOINT_DATE=\"$6\"\n\nBASE_URL=\"https://mpstats.io/api/analytics/v1/oz/items/${SKU}\"\nURL=\"\"\nQUERY=\"\"\n\nappend_query() {\n if [ -n \"$2\" ]; then\n if [ -z \"$1\" ]; then\n printf '%s' \"$2\"\n else\n printf '%s&%s' \"$1\" \"$2\"\n fi\n else\n printf '%s' \"$1\"\n fi\n}\n\ncase \"$REPORT\" in\n sales|categories|keywords|by_period|search_stats)\n URL=\"${BASE_URL}/${REPORT}\"\n QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n if [ \"$REPORT\" = \"sales\" ]; then\n QUERY=$(append_query \"$QUERY\" \"fbs=${FBS}\")\n fi\n ;;\n by_day|balance)\n URL=\"${BASE_URL}/${REPORT}\"\n QUERY=$(append_query \"$QUERY\" \"date=${POINT_DATE}\")\n if [ \"$REPORT\" = \"balance\" ]; then\n QUERY=$(append_query \"$QUERY\" \"fbs=${FBS}\")\n fi\n ;;\n full|stores|comments)\n URL=\"${BASE_URL}/${REPORT}\"\n ;;\n *)\n echo \"Unsupported report: $REPORT\" >&2\n exit 1\n ;;\nesac\n\nif [ -n \"$QUERY\" ]; then\n URL=\"${URL}?${QUERY}\"\nfi\n\ncurl -s --location --request GET \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2327,"content_sha256":"ca3603ce50aa91036e90faa3836ecb73299a03912d4f28d1f524083e8e421ba1"},{"filename":"scripts/README.md","content":"# MPSTATS Scripts\n\nScripts are grouped by domain:\n\n- `scripts/account/` — account and quota checks\n- `scripts/wb/` — Wildberries endpoints\n- `scripts/ozon/` — Ozon endpoints\n- `scripts/ym/` — Yandex Market endpoints\n- `scripts/request.sh` — universal raw request for any MPSTATS API method\n\n## Account\n\n| Script | Purpose | When to use |\n|---|---|---|\n| `account/account-limits.sh` | API quota usage and remaining calls | Before heavy runs and when troubleshooting 429 |\n\n## Wildberries\n\n| Script | Purpose | When to use |\n|---|---|---|\n| `wb/wb-categories-list.sh` | Full WB rubricator | Need category tree / path discovery |\n| `wb/wb-category.sh` | Category product list (`POST category/items`) | Product-level analysis in a WB category |\n| `wb/wb-category-stats.sh` | Category aggregate reports (`subcategories`, `brands`, `sellers`, `trends`, `by_date`, `price_segmentation`) | Market structure, trend, and segmentation views |\n| `wb/wb-brand.sh` | Brand products and aggregate reports | Brand-level analytics |\n| `wb/wb-seller.sh` | Seller products and aggregate reports | Seller-level analytics |\n| `wb/wb-sku.sh` | SKU-level reports via `items/{id}/{report}` | Item info/sales/stocks/keywords/comments/FAQ |\n| `wb/wb-search.sh` | Subjects/niches list (`POST subject/list`) | Niche discovery and subject lookup |\n| `wb/wb-subject.sh` | Subject-level methods (`subject/*`) | Subject analytics by subject id |\n| `wb/wb-similar.sh` | Similar families (`identical`, `identical_wb`, `similar`, `in_similar`) | Similar product analysis for SKU/url |\n| `wb/wb-analytics.sh` | Forecast and season effects | AI forecasts and seasonality |\n| `wb/wb-warehouses.sh` | Warehouse breakdown (`brand/warehouses`, `seller/warehouses`) | Stock distribution by warehouse |\n| `wb/wb-compare.sh` | Period compare endpoints for category/brand/seller/subject | Two-period performance comparison |\n\n## Ozon\n\n| Script | Purpose | When to use |\n|---|---|---|\n| `ozon/ozon-categories-list.sh` | Full Ozon rubricator | Need Ozon category tree |\n| `ozon/ozon-category.sh` | Category products and aggregate reports | Ozon category analytics |\n| `ozon/ozon-brand.sh` | Brand products and aggregate reports (`categories`, `sellers`, `by_date`, `price_segmentation`) | Ozon brand analytics |\n| `ozon/ozon-seller.sh` | Seller products and aggregate reports (`categories`, `brands`, `by_date`, `price_segmentation`) | Ozon seller analytics by seller id or seller name |\n| `ozon/ozon-sku.sh` | SKU-level reports (`sales`, `balance_by_day`, `balance_by_region`, `by_category`, `by_keywords`) | Ozon item-level history, stock, category/keyword positions |\n| `ozon/ozon-compare.sh` | Ozon compare endpoints for brand/seller/category | Two-period comparison |\n\n## Yandex Market\n\n| Script | Purpose | When to use |\n|---|---|---|\n| `ym/ym-category.sh` | Category products and aggregate reports | YM category analytics |\n| `ym/ym-brand.sh` | Brand products and aggregate reports | YM brand analytics |\n| `ym/ym-seller.sh` | Seller products and aggregate reports | YM seller analytics |\n| `ym/ym-sku.sh` | Item sales history with optional date range | YM item-level history |\n| `ym/ym-compare.sh` | YM compare endpoints for brand/seller/category | Two-period comparison |\n\n## Universal\n\n| Script | Purpose | When to use |\n|---|---|---|\n| `request.sh` | Raw API call to any path with GET/POST | Endpoint not covered by dedicated script or quick prototyping |\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3430,"content_sha256":"0ccec7f3cca87ac4694532a8a70772ec4973c3ed9bccc0b3fc50476a1557a878"},{"filename":"scripts/request.sh","content":"#!/bin/bash\n# request.sh — Universal MPSTATS API request runner\n# Usage: ./request.sh \u003cMETHOD> \u003cpath> [query] [body_json]\n\nMETHOD=\"$1\"\nPATH_REL=\"$2\"\nQUERY=\"$3\"\nBODY_JSON=\"$4\"\n\nif [ -z \"$METHOD\" ] || [ -z \"$PATH_REL\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cMETHOD> \u003cpath> [query] [body_json]\"\n echo \" METHOD — GET or POST\"\n echo \" path — API path relative to marketplace base URL\"\n echo \" WB paths (auto-routed to analytics/v1/wb/): category/list, brand/items, items/{id}/full, etc.\"\n echo \" Ozon paths: ozon/... (routed to https://mpstats.io/api/ozon/...)\"\n echo \" YM paths: ym/... (routed to https://mpstats.io/api/ym/...)\"\n echo \" Legacy WB paths (wb/get/...): auto-redirected to analytics/v1/wb/ equivalents\"\n echo \" query — optional raw query, e.g. d1=2024-01-01&d2=2024-01-31&path=70\"\n echo \" body_json — optional JSON body for POST\"\n echo \"\"\n echo \"Examples:\"\n echo \" $0 GET category/list\"\n echo \" $0 POST subject/by_date 'path=70&d1=2024-01-01&d2=2024-01-31&groupBy=day'\"\n echo \" $0 POST subject/items 'path=70&d1=2024-01-01&d2=2024-01-31' '{\\\"startRow\\\":0,\\\"endRow\\\":100,\\\"filterModel\\\":{},\\\"sortModel\\\":[]}'\"\n echo \" $0 GET ozon/get/categories\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=./common.sh\nsource \"$SCRIPT_DIR/common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nMETHOD_UPPER=$(printf '%s' \"$METHOD\" | tr '[:lower:]' '[:upper:]')\n\n# Route to correct base URL based on path prefix\nif [[ \"$PATH_REL\" == ozon/* ]] || [[ \"$PATH_REL\" == ym/* ]] || [[ \"$PATH_REL\" == account/* ]]; then\n # Ozon, YM, and account paths use the old base\n URL=\"https://mpstats.io/api/${PATH_REL}\"\nelif [[ \"$PATH_REL\" == wb/get/* ]]; then\n # Legacy WB paths — strip wb/get/ prefix and route to new base\n STRIPPED=\"${PATH_REL#wb/get/}\"\n URL=\"https://mpstats.io/api/analytics/v1/wb/${STRIPPED}\"\nelif [[ \"$PATH_REL\" == analytics/v1/wb/* ]]; then\n # Already fully qualified analytics path\n URL=\"https://mpstats.io/api/${PATH_REL}\"\nelse\n # Default: treat as WB analytics/v1 path\n URL=\"https://mpstats.io/api/analytics/v1/wb/${PATH_REL}\"\nfi\n\nif [ -n \"$QUERY\" ]; then\n URL=\"${URL}?${QUERY}\"\nfi\n\nif [ \"$METHOD_UPPER\" = \"GET\" ]; then\n curl -s --location --request GET \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nelif [ \"$METHOD_UPPER\" = \"POST\" ]; then\n PAYLOAD=\"${BODY_JSON:-{\\\"startRow\\\":0,\\\"endRow\\\":100,\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}}\"\n curl -s --location --request POST \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"$PAYLOAD\"\nelse\n echo \"Unsupported METHOD: $METHOD. Use GET or POST.\" >&2\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2818,"content_sha256":"fa5b83e0b00f4633020c597cceb0c5ab9f5b7e1b4c1a2dc5fb41bfeb22c70a44"},{"filename":"scripts/wb/wb-analytics.sh","content":"#!/bin/bash\n# wb-analytics.sh — AI forecasts and seasonality for category/subject\n# Usage: ./wb-analytics.sh \u003centity> \u003creport> \u003cpath_or_subject_id> [period]\n\nif [ -z \"$1\" ] || [ -z \"$2\" ] || [ -z \"$3\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003centity> \u003creport> \u003cpath_or_subject_id> [period]\"\n echo \" entity — category | subject\"\n echo \" report — forecast/daily | forecast/trend | season_effects/annual | season_effects/weekly\"\n echo \" path_or_subject_id — category path or subject id\"\n echo \" period — optional: month12|month3 (trend), day|week|month (annual)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nENTITY=\"$1\"\nREPORT=\"$2\"\nPATH_VALUE=\"$3\"\nPERIOD=\"$4\"\n\nif [ \"$ENTITY\" != \"category\" ] && [ \"$ENTITY\" != \"subject\" ]; then\n echo \"entity must be category or subject\" >&2\n exit 1\nfi\n\nENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$PATH_VALUE\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$PATH_VALUE\" 2>/dev/null || \\\n printf '%s' \"$PATH_VALUE\" | sed 's/ /%20/g; s|/|%2F|g')\n\nURL=\"https://mpstats.io/api/analytics/v1/wb/${ENTITY}/${REPORT}?path=${ENCODED_PATH}\"\nif [ -n \"$PERIOD\" ]; then\n URL=\"${URL}&period=${PERIOD}\"\nfi\n\ncurl -s --location --request GET \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1541,"content_sha256":"5c0705d570e92395519086a57edf1295b25b94b74bb3ad4176ef2fb0a50483be"},{"filename":"scripts/wb/wb-brand.sh","content":"#!/bin/bash\n# wb-brand.sh — Get products or analytics for a Wildberries brand\n# Usage: ./wb-brand.sh \u003cbrand> [report] [d1] [d2] [limit] [fbs]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cbrand> [report] [d1] [d2] [limit] [fbs]\"\n echo \" brand — brand name, e.g. 'Nike' (sent as API param: path)\"\n echo \" report — products (default), categories, sellers, trends, by_date, price_segmentation, subjects, keywords\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max results for products report, 1-5000 (default: 100)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nBRAND=\"$1\"\nREPORT=\"${2:-products}\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${5:-100}\"\nFBS=\"${6:-0}\"\n\nENCODED_BRAND=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$BRAND\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$BRAND\" 2>/dev/null || \\\n printf '%s' \"$BRAND\" | sed 's/ /%20/g')\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"https://mpstats.io/api/analytics/v1/wb/brand/items?d1=${D1}&d2=${D2}&path=${ENCODED_BRAND}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\nelse\n curl -s --location --request POST \\\n \"https://mpstats.io/api/analytics/v1/wb/brand/${REPORT}?d1=${D1}&d2=${D2}&path=${ENCODED_BRAND}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2056,"content_sha256":"ea14ee8ca63c63a747911833c456c03cfe44dd8cd8d2eb42e0fbfd4e456ce535"},{"filename":"scripts/wb/wb-card-content.sh","content":"#!/bin/bash\n# wb-card-content.sh — Fetch WB product card content (description + characteristics)\n#\n# IMPORTANT: This script does NOT call MPSTATS API. It uses Wildberries' internal\n# CDN (basket-N.wbbasket.ru) which is NOT a documented public API. It works without\n# any token but may change or break without notice. Use it when MPSTATS analytics\n# is not enough and you need the actual card text — description, options,\n# composition, exact dimensions, vendor_code, etc.\n#\n# Why this exists in mpstats skill: MPSTATS API is analytics-only and does not\n# return card content (description/characteristics). For product card design,\n# copy work, or content audits this data is required, so the skill ships this\n# CDN helper to keep all WB-card workflows in one place.\n#\n# Usage: ./wb-card-content.sh \u003csku> [field]\n# sku — WB product ID (numeric), e.g. 290784358\n# field — optional jq path to extract a single field, e.g. .description\n# or .options. Without it, full JSON is printed.\n#\n# Examples:\n# ./wb-card-content.sh 290784358\n# ./wb-card-content.sh 290784358 .description\n# ./wb-card-content.sh 290784358 .grouped_options\n\nset -e\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ] || [ \"$1\" = \"-h\" ]; then\n sed -n '2,22p' \"$0\" | sed 's/^# \\{0,1\\}//'\n exit 0\nfi\n\nSKU=\"$1\"\nFIELD=\"${2:-}\"\n\nif ! [[ \"$SKU\" =~ ^[0-9]+$ ]]; then\n echo \"Error: SKU must be numeric, got: $SKU\" >&2\n exit 1\nfi\n\n# Path layout on basket CDN:\n# vol = SKU / 100000 (integer division)\n# part = SKU / 1000 (integer division)\n# basket-N number is determined by vol range and grows as WB scales.\n# Mapping below is current as of 2026-05; update if a new basket appears.\nvol=$((SKU / 100000))\npart=$((SKU / 1000))\n\nif [ \"$vol\" -le 143 ]; then basket=\"01\"\nelif [ \"$vol\" -le 287 ]; then basket=\"02\"\nelif [ \"$vol\" -le 431 ]; then basket=\"03\"\nelif [ \"$vol\" -le 719 ]; then basket=\"04\"\nelif [ \"$vol\" -le 1007 ]; then basket=\"05\"\nelif [ \"$vol\" -le 1061 ]; then basket=\"06\"\nelif [ \"$vol\" -le 1115 ]; then basket=\"07\"\nelif [ \"$vol\" -le 1169 ]; then basket=\"08\"\nelif [ \"$vol\" -le 1313 ]; then basket=\"09\"\nelif [ \"$vol\" -le 1601 ]; then basket=\"10\"\nelif [ \"$vol\" -le 1655 ]; then basket=\"11\"\nelif [ \"$vol\" -le 1919 ]; then basket=\"12\"\nelif [ \"$vol\" -le 2045 ]; then basket=\"13\"\nelif [ \"$vol\" -le 2189 ]; then basket=\"14\"\nelif [ \"$vol\" -le 2405 ]; then basket=\"15\"\nelif [ \"$vol\" -le 2621 ]; then basket=\"16\"\nelif [ \"$vol\" -le 2837 ]; then basket=\"17\"\nelif [ \"$vol\" -le 3053 ]; then basket=\"18\"\nelif [ \"$vol\" -le 3269 ]; then basket=\"19\"\nelif [ \"$vol\" -le 3485 ]; then basket=\"20\"\nelif [ \"$vol\" -le 3701 ]; then basket=\"21\"\nelif [ \"$vol\" -le 3917 ]; then basket=\"22\"\nelif [ \"$vol\" -le 4133 ]; then basket=\"23\"\nelif [ \"$vol\" -le 4349 ]; then basket=\"24\"\nelif [ \"$vol\" -le 4565 ]; then basket=\"25\"\nelif [ \"$vol\" -le 4781 ]; then basket=\"26\"\nelse basket=\"27\"\nfi\n\nURL=\"https://basket-${basket}.wbbasket.ru/vol${vol}/part${part}/${SKU}/info/ru/card.json\"\n\n# Primary attempt with computed basket\nRESPONSE=$(curl -sfL -A \"Mozilla/5.0\" \"$URL\" 2>/dev/null || true)\n\n# Fallback: probe baskets 01..27 if mapping is stale (range tables drift over time)\nif [ -z \"$RESPONSE\" ]; then\n for b in 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27; do\n [ \"$b\" = \"$basket\" ] && continue\n TRY_URL=\"https://basket-${b}.wbbasket.ru/vol${vol}/part${part}/${SKU}/info/ru/card.json\"\n RESPONSE=$(curl -sfL -A \"Mozilla/5.0\" \"$TRY_URL\" 2>/dev/null || true)\n if [ -n \"$RESPONSE\" ]; then\n URL=\"$TRY_URL\"\n break\n fi\n done\nfi\n\nif [ -z \"$RESPONSE\" ]; then\n echo \"Error: could not fetch card.json for SKU $SKU from any basket CDN.\" >&2\n echo \"Tried: $URL\" >&2\n echo \"WB CDN may have changed. Inspect MPSTATS photo URL for current basket number:\" >&2\n echo \" ./wb-sku.sh $SKU full | jq '.photo.list[0].f'\" >&2\n exit 2\nfi\n\nif [ -n \"$FIELD\" ]; then\n echo \"$RESPONSE\" | jq -r \"$FIELD\"\nelse\n echo \"$RESPONSE\"\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":3933,"content_sha256":"cf3606b82f4e3b47d3f523b64da8724358b5d49441ecdec7f3e4d1390285cb11"},{"filename":"scripts/wb/wb-categories-list.sh","content":"#!/bin/bash\n# wb-categories-list.sh — Get full WB category tree (rubricator)\n# Usage: ./wb-categories-list.sh\n\nif [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0\"\n echo \" Returns the full Wildberries category tree.\"\n echo \" Each item: {url, name, path}\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\ncurl -s --location --request POST 'https://mpstats.io/api/analytics/v1/wb/category/list' \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data '{}'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":719,"content_sha256":"b0365fbe10733c9d057067f2bb82c8c5d2592f3f6c8f35fc1cfc7ca9d28ea3ff"},{"filename":"scripts/wb/wb-category-stats.sh","content":"#!/bin/bash\n# wb-category-stats.sh — Get subcategory/brand/seller breakdown or trends for a WB category\n# Usage: ./wb-category-stats.sh \u003ccategory_path> \u003creport> [d1] [d2] [fbs]\n\nif [ -z \"$1\" ] || [ -z \"$2\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003ccategory_path> \u003creport> [d1] [d2] [fbs]\"\n echo \" category_path — e.g. 'Электроника/Смартфоны и телефоны'\"\n echo \" report — one of: subcategories, brands, sellers, trends, by_date, price_segmentation\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nCATEGORY_PATH=\"$1\"\nREPORT=\"$2\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nFBS=\"${5:-0}\"\n\n# Map old report name to new API path\ncase \"$REPORT\" in\n subcategories) API_PATH=\"categories\" ;;\n *) API_PATH=\"$REPORT\" ;;\nesac\n\nENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$CATEGORY_PATH\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$CATEGORY_PATH\" 2>/dev/null || \\\n printf '%s' \"$CATEGORY_PATH\" | sed 's/ /%20/g; s|/|%2F|g')\n\ncurl -s --location --request POST \\\n \"https://mpstats.io/api/analytics/v1/wb/category/${API_PATH}?d1=${D1}&d2=${D2}&path=${ENCODED_PATH}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1793,"content_sha256":"b65d440c34f4d944a5f017e271af085b48a46abe1814630c71a55f5b37f0791b"},{"filename":"scripts/wb/wb-category.sh","content":"#!/bin/bash\n# wb-category.sh — Get products in a Wildberries category\n# Usage: ./wb-category.sh \u003ccategory_path> [d1] [d2] [limit] [fbs]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003ccategory_path> [d1] [d2] [limit] [fbs]\"\n echo \" category_path — e.g. 'Электроника/Смартфоны и телефоны/Планшеты'\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max results, 1-5000 (default: 100)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \"\"\n echo \"Response: {total, data:[{id,name,brand,seller,sales,revenue,final_price,...}]}\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nCATEGORY_PATH=\"$1\"\nD1=\"${2:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${3:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${4:-100}\"\nFBS=\"${5:-0}\"\n\nENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$CATEGORY_PATH\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$CATEGORY_PATH\" 2>/dev/null || \\\n printf '%s' \"$CATEGORY_PATH\" | sed 's/ /%20/g; s|/|%2F|g')\n\ncurl -s --location --request POST \\\n \"https://mpstats.io/api/analytics/v1/wb/category/items?d1=${D1}&d2=${D2}&path=${ENCODED_PATH}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1806,"content_sha256":"85f3a500d88d48d098bedb60f7b904c1f734138251bf20798d6a2b2de0272415"},{"filename":"scripts/wb/wb-compare.sh","content":"#!/bin/bash\n# wb-compare.sh — Compare two periods for category/brand/seller/subject\n# Usage: ./wb-compare.sh \u003cscope> \u003cvalue> \u003cd11> \u003cd12> \u003cd21> \u003cd22> [d1] [d2] [fbs] [limit]\n\nif [ -z \"$1\" ] || [ -z \"$2\" ] || [ -z \"$3\" ] || [ -z \"$4\" ] || [ -z \"$5\" ] || [ -z \"$6\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cscope> \u003cvalue> \u003cd11> \u003cd12> \u003cd21> \u003cd22> [d1] [d2] [fbs] [limit]\"\n echo \" scope — category | brand | seller | subject\"\n echo \" value — path/category string, brand name, supplier_id, or subject_id\"\n echo \" d11/d12 — first comparison period\"\n echo \" d21/d22 — second comparison period\"\n echo \" d1/d2 — base range for endpoint query (default: d11/d22)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \" limit — endRow for result page (default: 100)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSCOPE=\"$1\"\nVALUE=\"$2\"\nD11=\"$3\"\nD12=\"$4\"\nD21=\"$5\"\nD22=\"$6\"\nD1=\"${7:-$D11}\"\nD2=\"${8:-$D22}\"\nFBS=\"${9:-0}\"\nLIMIT=\"${10:-100}\"\n\nBASE_URL=\"https://mpstats.io/api/analytics/v1/wb\"\nQUERY=\"d11=${D11}&d12=${D12}&d21=${D21}&d22=${D22}&fbs=${FBS}\"\n\ncase \"$SCOPE\" in\n category)\n ENCODED=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$VALUE\" 2>/dev/null || node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$VALUE\" 2>/dev/null || printf '%s' \"$VALUE\" | sed 's/ /%20/g; s|/|%2F|g')\n URL=\"$BASE_URL/category/compare?${QUERY}&path=${ENCODED}\"\n ;;\n brand)\n ENCODED=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$VALUE\" 2>/dev/null || node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$VALUE\" 2>/dev/null || printf '%s' \"$VALUE\" | sed 's/ /%20/g')\n URL=\"$BASE_URL/brand/compare?${QUERY}&path=${ENCODED}\"\n ;;\n seller)\n URL=\"$BASE_URL/seller/compare?${QUERY}&path=${VALUE}\"\n ;;\n subject)\n URL=\"$BASE_URL/subject/compare?${QUERY}&path=${VALUE}\"\n ;;\n *)\n echo \"scope must be one of: category | brand | seller | subject\" >&2\n exit 1\n ;;\nesac\n\ncurl -s --location --request POST \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[]}\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2361,"content_sha256":"ee4417f0a78e40a1d1d4bf65dc075262a8526f99452abfc94d449728f768b83c"},{"filename":"scripts/wb/wb-search.sh","content":"#!/bin/bash\n# wb-search.sh — Get WB niche/subject list for research (subjects selection)\n# Usage: ./wb-search.sh [date]\n\nif [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 [date]\"\n echo \" date — single date YYYY-MM-DD (default: today)\"\n echo \"\"\n echo \" Returns list of WB subjects/niches available for analysis.\"\n echo \" Use subject IDs from this list with wb-subject.sh\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nDATE=\"${1:-$(date +%Y-%m-%d)}\"\n\ncurl -s --location --request POST \\\n \"https://mpstats.io/api/analytics/v1/wb/subject/list?date=${DATE}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":874,"content_sha256":"5b5d68764c4183d5ec9b17526ccc7d5dcc5f90981c6b57cf1b1afa272b6b10ab"},{"filename":"scripts/wb/wb-seller.sh","content":"#!/bin/bash\n# wb-seller.sh — Get products or analytics for a Wildberries seller\n# Usage: ./wb-seller.sh \u003csupplier_id> [report] [d1] [d2] [limit] [fbs]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003csupplier_id> [report] [d1] [d2] [limit] [fbs]\"\n echo \" supplier_id — WB seller/supplier ID (numeric, sent as API param: path)\"\n echo \" report — products (default), categories, brands, trends, by_date, price_segmentation, subjects, keywords\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max results for products report, 1-5000 (default: 100)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSUPPLIER_ID=\"$1\"\nREPORT=\"${2:-products}\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${5:-100}\"\nFBS=\"${6:-0}\"\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"https://mpstats.io/api/analytics/v1/wb/seller/items?d1=${D1}&d2=${D2}&path=${SUPPLIER_ID}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\nelse\n curl -s --location --request POST \\\n \"https://mpstats.io/api/analytics/v1/wb/seller/${REPORT}?d1=${D1}&d2=${D2}&path=${SUPPLIER_ID}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1853,"content_sha256":"999d67ca359b9cf80e2593344f1c1f4eefcbbd05081788bfef4bef1427ce22c5"},{"filename":"scripts/wb/wb-similar.sh","content":"#!/bin/bash\n# wb-similar.sh — Similar/identical/in_similar families for SKU or URL\n# Usage: ./wb-similar.sh \u003cfamily> \u003cpath_value> [report] [d1] [d2] [limit] [fbs]\n\nif [ -z \"$1\" ] || [ -z \"$2\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cfamily> \u003cpath_value> [report] [d1] [d2] [limit] [fbs]\"\n echo \" family — identical | identical_wb | similar | in_similar\"\n echo \" path_value — SKU or product URL\"\n echo \" report — products (default), categories, brands, sellers, price_segmentation, trends, by_date, keywords, warehouses, compare\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max rows for products report (POST), 1-5000 (default: 100)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nFAMILY=\"$1\"\nPATH_VALUE=\"$2\"\nREPORT=\"${3:-products}\"\nD1=\"${4:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${5:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${6:-100}\"\nFBS=\"${7:-0}\"\n\nif [ \"$FAMILY\" != \"identical\" ] && [ \"$FAMILY\" != \"identical_wb\" ] && [ \"$FAMILY\" != \"similar\" ] && [ \"$FAMILY\" != \"in_similar\" ]; then\n echo \"family must be one of: identical | identical_wb | similar | in_similar\" >&2\n exit 1\nfi\n\nENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$PATH_VALUE\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$PATH_VALUE\" 2>/dev/null || \\\n printf '%s' \"$PATH_VALUE\" | sed 's/ /%20/g; s|/|%2F|g')\n\nBASE_URL=\"https://mpstats.io/api/analytics/v1/wb/${FAMILY}\"\nQUERY=\"d1=${D1}&d2=${D2}&path=${ENCODED_PATH}&fbs=${FBS}\"\n\n# Map report to API path\ncase \"$REPORT\" in\n products) API_SUFFIX=\"items\" ;;\n *) API_SUFFIX=\"$REPORT\" ;;\nesac\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"$BASE_URL/${API_SUFFIX}?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\nelse\n curl -s --location --request POST \\\n \"$BASE_URL/${API_SUFFIX}?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2465,"content_sha256":"d301b3a8dc1921ad80837dd71ddc6aeb1fd582e5f98e6be2208cfc7bebc57e9a"},{"filename":"scripts/wb/wb-sku.sh","content":"#!/bin/bash\n# wb-sku.sh — Get analytics for a specific Wildberries SKU\n# Usage: ./wb-sku.sh \u003csku> \u003creport> [d1] [d2] [fbs]\n\nif [ -z \"$1\" ] || [ -z \"$2\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003csku> \u003creport> [d1] [d2] [fbs]\"\n echo \" sku — WB product ID (numeric), e.g. 152490541\"\n echo \" report — one of:\"\n echo \" info\"\n echo \" full\"\n echo \" sales (alias for full)\"\n echo \" by_period\"\n echo \" balance_by_day (alias for by_period)\"\n echo \" balance_stores\"\n echo \" balance_by_region (alias for balance_stores)\"\n echo \" balance_sizes\"\n echo \" balance_by_size (alias for balance_sizes)\"\n echo \" balance_stores_and_sizes\"\n echo \" balance_colors\"\n echo \" sales_stores\"\n echo \" sales_by_region (alias for sales_stores)\"\n echo \" sales_sizes\"\n echo \" sales_by_size (alias for sales_sizes)\"\n echo \" sales_heatmap\"\n echo \" stores\"\n echo \" search_stats\"\n echo \" keywords\"\n echo \" keywords_hourly\"\n echo \" comments\"\n echo \" faq\"\n echo \" photos_history\"\n echo \" d1 — start date YYYY-MM-DD (optional)\"\n echo \" d2 — end date YYYY-MM-DD (optional)\"\n echo \" fbs — include FBS: 0 or 1 (optional)\"\n echo \"\"\n echo \"Examples:\"\n echo \" $0 152490541 sales 2026-03-01 2026-03-31\"\n echo \" $0 152490541 full\"\n echo \" $0 152490541 keywords 2026-03-01 2026-03-31\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSKU=\"$1\"\nREPORT=\"$2\"\nD1=\"$3\"\nD2=\"$4\"\nFBS=\"$5\"\n\nBASE_URL=\"https://mpstats.io/api/analytics/v1/wb/items/${SKU}\"\nURL=\"\"\nQUERY=\"\"\nHTTP_METHOD=\"GET\"\n\nappend_query() {\n if [ -n \"$2\" ]; then\n if [ -z \"$1\" ]; then\n printf '%s' \"$2\"\n else\n printf '%s&%s' \"$1\" \"$2\"\n fi\n else\n printf '%s' \"$1\"\n fi\n}\n\ncase \"$REPORT\" in\n info)\n URL=\"$BASE_URL\"\n ;;\n full|sales)\n URL=\"$BASE_URL/full\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n by_period|balance_by_day)\n URL=\"$BASE_URL/by_period\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n balance_stores|balance_by_region)\n URL=\"$BASE_URL/balance/stores\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n balance_sizes|balance_by_size)\n URL=\"$BASE_URL/balance/sizes\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n balance_stores_and_sizes)\n URL=\"$BASE_URL/balance/stores_and_sizes\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n balance_colors)\n URL=\"$BASE_URL/balance/colors\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n sales_stores|sales_by_region)\n URL=\"$BASE_URL/sales/stores\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n sales_sizes|sales_by_size)\n URL=\"$BASE_URL/sales/sizes\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n sales_heatmap)\n URL=\"$BASE_URL/sales/heatmap\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n stores)\n URL=\"$BASE_URL/stores\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n search_stats)\n URL=\"$BASE_URL/search_stats\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n keywords)\n URL=\"$BASE_URL/keywords\"\n HTTP_METHOD=\"POST\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n keywords_hourly)\n URL=\"$BASE_URL/keywords/hourly\"\n HTTP_METHOD=\"POST\"\n [ -n \"$D1\" ] && QUERY=$(append_query \"$QUERY\" \"d1=${D1}\")\n [ -n \"$D2\" ] && QUERY=$(append_query \"$QUERY\" \"d2=${D2}\")\n ;;\n comments)\n URL=\"$BASE_URL/comments\"\n ;;\n faq)\n URL=\"$BASE_URL/faq\"\n ;;\n photos_history)\n URL=\"$BASE_URL/photos_history\"\n ;;\n *)\n echo \"Unsupported report: $REPORT\" >&2\n exit 1\n ;;\nesac\n\nif [ -n \"$QUERY\" ]; then\n URL=\"${URL}?${QUERY}\"\nfi\n\ncurl -s --location --request \"$HTTP_METHOD\" \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":5032,"content_sha256":"a823f60040ed7ed25e600d74ae54f3a4b3bb4d8d62a6412b48dbd83beefdb57d"},{"filename":"scripts/wb/wb-subject.sh","content":"#!/bin/bash\n# wb-subject.sh — Subject (niche) endpoints: products and aggregate reports\n# Usage: ./wb-subject.sh \u003csubject_id> [report] [d1] [d2] [limit] [fbs] [groupBy]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003csubject_id> [report] [d1] [d2] [limit] [fbs] [groupBy]\"\n echo \" subject_id — WB subject id (numeric), e.g. 70\"\n echo \" report — products (default), categories, brands, sellers, trends, by_date, price_segmentation, keywords, similar, geography, warehouses\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max rows for products report, 1-5000 (default: 100)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \" groupBy — for by_date: day|week|month (optional)\"\n echo \"\"\n echo \"Examples:\"\n echo \" $0 70 products\"\n echo \" $0 70 by_date 2024-01-01 2024-01-31 100 0 day\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSUBJECT_ID=\"$1\"\nREPORT=\"${2:-products}\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${5:-100}\"\nFBS=\"${6:-0}\"\nGROUP_BY=\"$7\"\n\nBASE_URL=\"https://mpstats.io/api/analytics/v1/wb\"\n\n# Map old report names to new API paths\ncase \"$REPORT\" in\n products) API_PATH=\"subject/items\" ;;\n by_keywords) API_PATH=\"subject/keywords\" ;;\n *) API_PATH=\"subject/$REPORT\" ;;\nesac\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"$BASE_URL/${API_PATH}?d1=${D1}&d2=${D2}&path=${SUBJECT_ID}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\n exit $?\nfi\n\n# similar and geography are GET, not POST\nif [ \"$REPORT\" = \"similar\" ]; then\n curl -s --location --request GET \\\n \"$BASE_URL/${API_PATH}?path=${SUBJECT_ID}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n exit $?\nfi\n\nif [ \"$REPORT\" = \"geography\" ]; then\n # geography uses date=YYYY-MM, not d1/d2\n GEO_DATE=\"${D1:0:7}\"\n curl -s --location --request GET \\\n \"$BASE_URL/${API_PATH}?path=${SUBJECT_ID}&date=${GEO_DATE}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n exit $?\nfi\n\nQUERY=\"d1=${D1}&d2=${D2}&path=${SUBJECT_ID}&fbs=${FBS}\"\n\nif [ \"$REPORT\" = \"by_date\" ] && [ -n \"$GROUP_BY\" ]; then\n QUERY=\"${QUERY}&groupBy=${GROUP_BY}\"\nfi\n\ncurl -s --location --request POST \\\n \"$BASE_URL/${API_PATH}?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2852,"content_sha256":"1958f6050168d16750b4526906d15afe8ef9b2787d3844cd119d4e32f0bedd13"},{"filename":"scripts/wb/wb-warehouses.sh","content":"#!/bin/bash\n# wb-warehouses.sh — Warehouse breakdown for brand or seller\n# Usage: ./wb-warehouses.sh \u003ckind> \u003cid_or_name> [d1] [d2]\n\nif [ -z \"$1\" ] || [ -z \"$2\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003ckind> \u003cid_or_name> [d1] [d2]\"\n echo \" kind — brand | seller\"\n echo \" id_or_name — brand name (for brand) or supplier_id (for seller)\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nKIND=\"$1\"\nVALUE=\"$2\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\n\nif [ \"$KIND\" = \"brand\" ]; then\n ENCODED=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$VALUE\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$VALUE\" 2>/dev/null || \\\n printf '%s' \"$VALUE\" | sed 's/ /%20/g')\n URL=\"https://mpstats.io/api/analytics/v1/wb/brand/warehouses?d1=${D1}&d2=${D2}&path=${ENCODED}\"\nelif [ \"$KIND\" = \"seller\" ]; then\n URL=\"https://mpstats.io/api/analytics/v1/wb/seller/warehouses?d1=${D1}&d2=${D2}&path=${VALUE}\"\nelse\n echo \"kind must be brand or seller\" >&2\n exit 1\nfi\n\ncurl -s --location --request POST \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1509,"content_sha256":"81953b018ab729341f38b540fc6f1a094ddae467a498d07df4644a4de830e97d"},{"filename":"scripts/ym/ym-brand.sh","content":"#!/bin/bash\n# ym-brand.sh — Get products or analytics for a Yandex Market brand\n# Usage: ./ym-brand.sh \u003cbrand_name> [report] [d1] [d2] [limit]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cbrand_name> [report] [d1] [d2] [limit]\"\n echo \" brand_name — YM brand name (path), e.g. 'Samsung'\"\n echo \" report — products (default), categories, sellers, by_date, price_segmentation\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max results for products report, 1-5000 (default: 100)\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nBRAND_NAME=\"$1\"\nREPORT=\"${2:-products}\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${5:-100}\"\n\nENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$BRAND_NAME\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$BRAND_NAME\" 2>/dev/null || \\\n printf '%s' \"$BRAND_NAME\" | sed 's/ /%20/g')\n\nQUERY=\"d1=${D1}&d2=${D2}&path=${ENCODED_PATH}\"\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"https://mpstats.io/api/ym/get/brand?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\nelse\n curl -s --location --request GET \\\n \"https://mpstats.io/api/ym/get/brand/${REPORT}?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1924,"content_sha256":"3eee12200869d37363b4201d3c16e4f5752bf1caf45d05dce9bcb037de0503c3"},{"filename":"scripts/ym/ym-category.sh","content":"#!/bin/bash\n# ym-category.sh — Get products or stats for a Yandex Market category\n# Usage: ./ym-category.sh \u003ccategory_path> [report] [d1] [d2] [limit] [fbs]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003ccategory_path> [report] [d1] [d2] [limit] [fbs]\"\n echo \" category_path — YM category path, e.g. 'Электроника/Смартфоны'\"\n echo \" report — products (default), categories, brands, sellers, by_date, price_segmentation\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max results for products report, 1-5000 (default: 100)\"\n echo \" fbs — include FBS: 0 or 1 (default: 0)\"\n echo \"\"\n echo \" Note: YM does not have a rubricator endpoint. Use known category paths.\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nCATEGORY_PATH=\"$1\"\nREPORT=\"${2:-products}\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${5:-100}\"\nFBS=\"${6:-0}\"\n\nENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$CATEGORY_PATH\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$CATEGORY_PATH\" 2>/dev/null || \\\n printf '%s' \"$CATEGORY_PATH\" | sed 's/ /%20/g; s|/|%2F|g')\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"https://mpstats.io/api/ym/get/category?d1=${D1}&d2=${D2}&path=${ENCODED_PATH}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\nelse\n # categories sub-report uses different endpoint name\n ENDPOINT=\"$REPORT\"\n if [ \"$REPORT\" = \"subcategories\" ]; then\n ENDPOINT=\"categories\"\n fi\n curl -s --location --request GET \\\n \"https://mpstats.io/api/ym/get/category/${ENDPOINT}?d1=${D1}&d2=${D2}&path=${ENCODED_PATH}&fbs=${FBS}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2384,"content_sha256":"173d5246549951e83f2c0c18c5cd5273934c7639c394e20ca0d3251a3300f884"},{"filename":"scripts/ym/ym-compare.sh","content":"#!/bin/bash\n# ym-compare.sh — Compare two periods for category/brand/seller\n# Usage: ./ym-compare.sh \u003cscope> \u003cvalue> \u003cd11> \u003cd12> \u003cd21> \u003cd22> [d1] [d2] [fbs] [limit]\n\nif [ -z \"$1\" ] || [ -z \"$2\" ] || [ -z \"$3\" ] || [ -z \"$4\" ] || [ -z \"$5\" ] || [ -z \"$6\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cscope> \u003cvalue> \u003cd11> \u003cd12> \u003cd21> \u003cd22> [d1] [d2] [fbs] [limit]\"\n echo \" scope — category | brand | seller\"\n echo \" value — category path, brand name, seller name\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSCOPE=\"$1\"\nVALUE=\"$2\"\nD11=\"$3\"\nD12=\"$4\"\nD21=\"$5\"\nD22=\"$6\"\nD1=\"${7:-$D11}\"\nD2=\"${8:-$D22}\"\nFBS=\"${9:-0}\"\nLIMIT=\"${10:-100}\"\n\nBASE_URL=\"https://mpstats.io/api/ym/get\"\nQUERY=\"d1=${D1}&d2=${D2}&fbs=${FBS}\"\n\ncase \"$SCOPE\" in\n category)\n ENCODED=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$VALUE\" 2>/dev/null || node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$VALUE\" 2>/dev/null || printf '%s' \"$VALUE\" | sed 's/ /%20/g; s|/|%2F|g')\n URL=\"$BASE_URL/category/compare?${QUERY}&path=${ENCODED}\"\n ;;\n brand)\n ENCODED=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$VALUE\" 2>/dev/null || node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$VALUE\" 2>/dev/null || printf '%s' \"$VALUE\" | sed 's/ /%20/g')\n URL=\"$BASE_URL/brand/compare?${QUERY}&path=${ENCODED}\"\n ;;\n seller)\n ENCODED=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$VALUE\" 2>/dev/null || node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$VALUE\" 2>/dev/null || printf '%s' \"$VALUE\" | sed 's/ /%20/g')\n URL=\"$BASE_URL/seller/compare?${QUERY}&path=${ENCODED}\"\n ;;\n *)\n echo \"scope must be one of: category | brand | seller\" >&2\n exit 1\n ;;\nesac\n\ncurl -s --location --request POST \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[],\\\"d11\\\":\\\"${D11}\\\",\\\"d12\\\":\\\"${D12}\\\",\\\"d21\\\":\\\"${D21}\\\",\\\"d22\\\":\\\"${D22}\\\"}\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":2240,"content_sha256":"058606da06fd7ce960def24b45ce282a09834ea763ad0bb93534e4866622a385"},{"filename":"scripts/ym/ym-seller.sh","content":"#!/bin/bash\n# ym-seller.sh — Get products or analytics for a Yandex Market seller\n# Usage: ./ym-seller.sh \u003cseller_name> [report] [d1] [d2] [limit]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cseller_name> [report] [d1] [d2] [limit]\"\n echo \" seller_name — YM seller name (path), e.g. 'Эльдорадо'\"\n echo \" report — products (default), categories, brands, by_date, price_segmentation\"\n echo \" d1 — start date YYYY-MM-DD (default: 30 days ago)\"\n echo \" d2 — end date YYYY-MM-DD (default: today)\"\n echo \" limit — max results for products report, 1-5000 (default: 100)\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nSELLER_NAME=\"$1\"\nREPORT=\"${2:-products}\"\nD1=\"${3:-$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)}\"\nD2=\"${4:-$(date +%Y-%m-%d)}\"\nLIMIT=\"${5:-100}\"\n\nENCODED_PATH=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SELLER_NAME\" 2>/dev/null || \\\n node -e \"process.stdout.write(encodeURIComponent(process.argv[1]))\" \"$SELLER_NAME\" 2>/dev/null || \\\n printf '%s' \"$SELLER_NAME\" | sed 's/ /%20/g')\n\nQUERY=\"d1=${D1}&d2=${D2}&path=${ENCODED_PATH}\"\n\nif [ \"$REPORT\" = \"products\" ]; then\n curl -s --location --request POST \\\n \"https://mpstats.io/api/ym/get/seller?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json' \\\n --data \"{\\\"startRow\\\":0,\\\"endRow\\\":${LIMIT},\\\"filterModel\\\":{},\\\"sortModel\\\":[{\\\"colId\\\":\\\"revenue\\\",\\\"sort\\\":\\\"desc\\\"}]}\"\nelse\n curl -s --location --request GET \\\n \"https://mpstats.io/api/ym/get/seller/${REPORT}?${QUERY}\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1951,"content_sha256":"3d79e3f6bcda621d4bb33b2e420139c76c1509e079c59d15142f25d7549769a0"},{"filename":"scripts/ym/ym-sku.sh","content":"#!/bin/bash\n# ym-sku.sh — Get sales and stock history for a Yandex Market item\n# Usage: ./ym-sku.sh \u003cid> [d1] [d2]\n\nif [ -z \"$1\" ] || [ \"$1\" = \"--help\" ]; then\n echo \"Usage: $0 \u003cid> [d1] [d2]\"\n echo \" id — Yandex Market item ID (numeric), e.g. 12345678\"\n echo \" d1 — start date YYYY-MM-DD (optional)\"\n echo \" d2 — end date YYYY-MM-DD (optional)\"\n echo \"\"\n echo \" Returns sales and stock history for the item.\"\n echo \"\"\n echo \"Environment:\"\n echo \" MPSTATS_TOKEN — API token (or set in config/.env)\"\n exit 0\nfi\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# shellcheck source=../common.sh\nsource \"$SCRIPT_DIR/../common.sh\"\n\nload_config\nTOKEN=\"${MPSTATS_TOKEN}\"\n\nITEM_ID=\"$1\"\nD1=\"$2\"\nD2=\"$3\"\nQUERY=\"\"\n\nif [ -n \"$D1\" ]; then\n QUERY=\"d1=${D1}\"\nfi\nif [ -n \"$D2\" ]; then\n if [ -n \"$QUERY\" ]; then\n QUERY=\"${QUERY}&\"\n fi\n QUERY=\"${QUERY}d2=${D2}\"\nfi\n\nURL=\"https://mpstats.io/api/ym/get/item/${ITEM_ID}/sales\"\nif [ -n \"$QUERY\" ]; then\n URL=\"${URL}?${QUERY}\"\nfi\n\ncurl -s --location --request GET \\\n \"$URL\" \\\n --header \"X-Mpstats-TOKEN: $TOKEN\" \\\n --header 'Content-Type: application/json'\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":1131,"content_sha256":"8ad1b6e45ce72d5a54a84ad26165a0c37e141f7e3bb2ff8b319e6c4b01776229"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"MPSTATS API","type":"text"}]},{"type":"paragraph","content":[{"text":"MPSTATS is a Russian marketplace analytics platform with data on Wildberries, Ozon, and Yandex Market: product research, category analysis, seller/brand monitoring, SKU-level sales, stock, and review data.","type":"text"}]},{"type":"paragraph","content":[{"text":"Work through the ready-made shell scripts in ","type":"text"},{"text":"scripts/","type":"text","marks":[{"type":"code_inline"}]},{"text":" — call them via the Bash tool instead of writing HTTP code. Reference files in ","type":"text"},{"text":"references/","type":"text","marks":[{"type":"code_inline"}]},{"text":" are API contracts only.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Token setup","type":"text"}]},{"type":"paragraph","content":[{"text":"Scripts auto-load the token from ","type":"text"},{"text":"config/.env","type":"text","marks":[{"type":"code_inline"}]},{"text":" via ","type":"text"},{"text":"scripts/common.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":". A per-command ","type":"text"},{"text":"MPSTATS_TOKEN","type":"text","marks":[{"type":"code_inline"}]},{"text":" env var overrides the file.","type":"text"}]},{"type":"paragraph","content":[{"text":"Setup and where to get the token: ","type":"text"},{"text":"config/README.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"If the token is missing, offer the user exactly 2 options before continuing:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User sends the token in chat → agent creates ","type":"text"},{"text":"config/.env","type":"text","marks":[{"type":"code_inline"}]},{"text":" itself.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User runs locally: ","type":"text"},{"text":"cp config/.env.example config/.env","type":"text","marks":[{"type":"code_inline"}]},{"text":" and pastes the token into ","type":"text"},{"text":"config/.env","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Token page: https://mpstats.io/userpanel (API token block). Requires an active MPSTATS subscription.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"paragraph","content":[{"text":"API contracts (endpoints, params, response semantics) — read on demand:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/auth.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — base URL, auth headers, response codes, rate limits","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/pagination-filter-sort.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — common request/response model for all POST endpoints","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/wb-categories.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"references/wb-brands-sellers.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"references/wb-similar-sku.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Wildberries","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/ozon-categories.md","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"references/ozon-brands-sellers-sku.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Ozon","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/ym-categories.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — Yandex Market","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/account.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — API limits","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/coverage.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — what is wrapped by scripts vs. still uncovered","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"references/presentation.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" — how to format analytical answers and brand-styled HTML/PDF reports","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Result formatting","type":"text"}]},{"type":"paragraph","content":[{"text":"Lead with a concise conclusion, then evidence. Use compact tables for multi-entity results, charts for trends/segmentation/comparisons. Don't dump raw JSON unless asked — interpret what the numbers mean for the decision. For HTML/PDF reports follow the MPSTATS brand style in ","type":"text"},{"text":"references/presentation.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Sanity check — flag anomalies, never report blindly","type":"text"}]},{"type":"paragraph","content":[{"text":"MPSTATS data can contain outliers, seller errors, unit mismatches, and stale rows. Reporting them as fact misleads the user. ","type":"text"},{"text":"Before presenting any number, sanity-check its magnitude.","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"Flag explicitly","type":"text","marks":[{"type":"strong"}]},{"text":" when you see:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Price far outside the category norm","type":"text","marks":[{"type":"strong"}]},{"text":" — e.g. napkins at 500 000 ₽ per item, a phone case at 50 ₽, a refrigerator at 200 ₽. Compare to the category median; if it's roughly >10× off, it is almost certainly a seller-side price error, a unit mismatch (pack vs piece), or a placeholder.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Implausible volumes","type":"text","marks":[{"type":"strong"}]},{"text":" — a small seller suddenly at 1 000 000 units/month; revenue without sales; revenue ≠ approximately ","type":"text"},{"text":"price × units","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Zero / null / negative values where they shouldn't be","type":"text","marks":[{"type":"strong"}]},{"text":" — rating 0 on a SKU with reviews, stock = -5, \"0 days since last sale\" on an obviously inactive SKU.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Date / period weirdness","type":"text","marks":[{"type":"strong"}]},{"text":" — requested period ≠ returned period, gaps in by-date series, future-dated rows.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Unit mismatches","type":"text","marks":[{"type":"strong"}]},{"text":" — price per pack treated as price per piece; m² vs piece; liters vs ml.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"How to flag, in this order:","type":"text","marks":[{"type":"strong"}]}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Show the anomalous row clearly, with the value called out (e.g. \"500 000 ₽ за упаковку — похоже на ошибку ценника продавца\").","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"State your best guess at the cause (unit mismatch, seller error, stale data, placeholder).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Either drop the row from aggregates (and say you did) or note that aggregates are skewed by it.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Continue the analysis on cleaned data.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Do NOT","type":"text","marks":[{"type":"strong"}]},{"text":" silently drop or \"round\" anomalies. ","type":"text"},{"text":"Do NOT","type":"text","marks":[{"type":"strong"}]},{"text":" report them as if they were real and let the user spot the absurdity. The conclusion must rely on cleaned data; the raw outlier is mentioned for transparency.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Scripts","type":"text"}]},{"type":"paragraph","content":[{"text":"Ready-to-use shell scripts in ","type":"text"},{"text":"scripts/","type":"text","marks":[{"type":"code_inline"}]},{"text":". Call via the Bash tool, do not rewrite HTTP. Full catalog with per-script use-cases and routing guidance: ","type":"text"},{"text":"scripts/README.md","type":"text","marks":[{"type":"code_inline"}]},{"text":". Run any script with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" for parameters.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Script","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Purpose","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Usage","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"account/account-limits.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Check API quota remaining","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/account/account-limits.sh","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-categories-list.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Full WB category tree","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-categories-list.sh","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-category.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB category products","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-category.sh \"Электроника/Смартфоны\" 2024-01-01 2024-03-01","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-category-stats.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB category breakdown (subcategories/brands/sellers/trends)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-category-stats.sh \"Электроника\" subcategories","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-sku.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB SKU analytics (full/sales/balance/keywords/comments)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-sku.sh 152490541 sales","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-card-content.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB card content (description, characteristics, dimensions) — uses WB CDN, not MPSTATS","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-card-content.sh 290784358 .description","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-brand.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB brand products or analytics","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-brand.sh \"Nike\" products","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-seller.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB seller products or analytics","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-seller.sh 123456 products","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-search.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB subjects/niches list for research","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-search.sh","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-subject.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB subject endpoints (","type":"text"},{"text":"products","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"categories","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"brands","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"sellers","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"trends","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"by_date","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"price_segmentation","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"keywords","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"similar","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"geography","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"warehouses","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-subject.sh 70 products","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-similar.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB similar families (","type":"text"},{"text":"identical","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"identical_wb","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"similar","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"in_similar","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-similar.sh similar 72124874 products","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-analytics.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB AI forecasts and season effects","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-analytics.sh category forecast/daily \"Женщинам/Платья и сарафаны\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-warehouses.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB warehouse distribution for brand/seller","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-warehouses.sh brand \"Mango\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"wb/wb-compare.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"WB period compare for category/brand/seller/subject","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/wb/wb-compare.sh subject 70 2024-01-01 2024-01-15 2024-01-16 2024-01-31","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ozon/ozon-categories-list.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Full Ozon category tree","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ozon/ozon-categories-list.sh","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ozon/ozon-category.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ozon category products or stats","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ozon/ozon-category.sh \"Автотовары\" products","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ozon/ozon-sku.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ozon SKU reports (","type":"text"},{"text":"sales","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"by_day","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"balance","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"categories","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"keywords","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"full","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"by_period","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"search_stats","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"stores","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"comments","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ozon/ozon-sku.sh 123456789 keywords 2023-11-27 2023-12-26","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ozon/ozon-brand.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ozon brand products or analytics","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ozon/ozon-brand.sh \"Samsung\" categories","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ozon/ozon-seller.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ozon seller products or analytics by seller id or name","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ozon/ozon-seller.sh 987654 products","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ozon/ozon-compare.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ozon period compare for category/brand/seller","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ozon/ozon-compare.sh category \"Автотовары/...\" 2024-01-01 2024-01-15 2024-01-16 2024-01-31","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ym/ym-category.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yandex Market category products or stats","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ym/ym-category.sh \"Электроника/Смартфоны\"","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ym/ym-brand.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yandex Market brand products or analytics","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ym/ym-brand.sh \"Samsung\" categories","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ym/ym-seller.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yandex Market seller products or analytics","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ym/ym-seller.sh \"Эльдорадо\" products","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ym/ym-sku.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yandex Market item sales history with optional dates","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ym/ym-sku.sh 12345678 2024-01-01 2024-01-31","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ym/ym-compare.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Yandex Market period compare for category/brand/seller","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/ym/ym-compare.sh category \"Электроника/Смартфоны\" 2024-01-01 2024-01-15 2024-01-16 2024-01-31","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"request.sh","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Universal raw API caller for any MPSTATS method/path","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"./scripts/request.sh POST subject/items 'path=70&d1=2024-01-01&d2=2024-01-31'","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]}]},"metadata":{"date":"2026-11-02","name":"mpstats","author":"@skillopedia","source":{"stars":12,"repo_name":"claude-code-skills","origin_url":"https://github.com/mpstats-io/claude-code-skills/blob/HEAD/mpstats/SKILL.md","repo_owner":"mpstats-io","body_sha256":"e62cd9d42db41686910078ef65be88be516b1c6d2563fc72a457ccbc43c06d0c","cluster_key":"2028b92fc8c0fd2f670247663091fba021bc8f9359c8df798fb1690dcddd737e","clean_bundle":{"format":"clean-skill-bundle-v1","source":"mpstats-io/claude-code-skills/mpstats/SKILL.md","text_bytes":114193,"source_commit":"1ef970e8b28183daab413b7c87156044a4558056","skills_sh_rank":15382,"attachment_count":40,"text_attachments":40,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"mpstats/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"data-analytics","category_label":"Data"},"exact_dupes_collapsed_into_this":0},"license":"MIT","version":"v1","category":"data-analytics","metadata":{"version":"2.0.0"},"import_tag":"skills-sh-top20k-2026-11","description":"MPSTATS marketplace analytics API. Use when working with MPSTATS API, Wildberries analytics, Ozon analytics, Yandex Market analytics, marketplace data, product research, sales analytics, competitor analysis, niche research, SKU analysis, seller analytics, brand analytics."}},"renderedAt":1793671348978}

MPSTATS API MPSTATS is a Russian marketplace analytics platform with data on Wildberries, Ozon, and Yandex Market: product research, category analysis, seller/brand monitoring, SKU-level sales, stock, and review data. Work through the ready-made shell scripts in — call them via the Bash tool instead of writing HTTP code. Reference files in are API contracts only. Token setup Scripts auto-load the token from via . A per-command env var overrides the file. Setup and where to get the token: . If the token is missing, offer the user exactly 2 options before continuing: 1. User sends the token in…