Self-hosted marketplace analytics for Wildberries & Ozon sellers
Π ΡΡΡΠΊΠΈΠΉ β’ English
Features β’ Quick Start β’ Architecture β’ Screenshots β’ API β’ Configuration β’ Documentation β’ Contributing
π Project page: ΠΏΠ΅Π΄ΠΎΠ±ΡΠ°Π·.ΡΡ/projects/bormostats
| Capability | Description |
|---|---|
| Automated Data Collection | Incremental collection of sales, orders, stocks, funnels, ads, and finances from WB & Ozon APIs |
| Analytics Warehouse | Three-layer data warehouse in ClickHouse (raw β staging β marts) |
| REST API | FastAPI backend with endpoints for sales, stocks, funnels, ads, and KPIs |
| Modern Web UI | Built-in React 19 SPA with dark theme, dashboards, and admin panel |
| BI Dashboards | Metabase integration for custom dashboards and ad-hoc SQL queries |
| Telegram Alerts | YAML-defined automation rules: high ACOS, low stock, no sales |
| Bidder | Automated bid management for WB/Ozon ad campaigns with CPM/position rules |
| Repricer | Dynamic pricing with margin validation and break-even analysis |
| P&L | Full profit & loss statements with indirect expense tracking |
| ABC/XYZ | Automated assortment analysis (revenue contribution + demand stability) |
| Actionable Insights | Daily anomaly detection β task queue with Telegram digest |
| PIM | Product enrichment: brands, categories, SEO, AI-generated descriptions |
| Webhooks | Stock update integration endpoint (1C/ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ compatible), webhook subscriptions |
| Admin API | Backfill, transforms, watermarks, task audit, and maintenance operations |
| Observability | Prometheus metrics, Grafana dashboards, alert rules |
| Supply Chain Security | pip-audit, Docker image scanning (Grype), SBOM generation (SPDX) |
- β Collects data only from your own seller accounts
- β Fully self-hosted β no data sent to third parties
- β Does not scrape competitor data or marketplace catalogues
- β Does not provide market-wide analytics
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CELERY BEAT (Scheduler) β
β Schedules collectors, transforms, marts, automation, pruning β
ββββββββββββββ¬βββββββββββββββββ¬βββββββββββββββββββ¬ββββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββββ
β WB Collector β β Ozon Collector β β Transforms & Marts β
β (API client) β β (API client) β β (SQL transformations) β
ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ βββββββββββββββ¬ββββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLICKHOUSE (Data Warehouse) β
β raw_* β stg_* β mrt_* | sys_watermarks | sys_task_runs β
βββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FastAPI Backend β
β /api/v1/* (analytics) /api/v1/admin/* (admin) β
β /ui (web UI) /metrics (Prometheus) β
βββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββ ββββββββββββββββ
β Nginx Reverse Proxy (TLS) β β Metabase β
β β public entry point β β (BI dashboards)β
ββββββββββββββββββββββββββββββββ ββββββββββββββββ
| Component | Technology | Purpose |
|---|---|---|
| Backend | FastAPI + Uvicorn | REST API, web UI, health/ready/metrics |
| Worker | Celery | Data collection, transforms, marts, automation |
| Beat | Celery Beat | Periodic task scheduler |
| ClickHouse | ClickHouse 26.x | OLAP analytics warehouse |
| Redis | Redis 7.x | Celery broker + distributed locks |
| Nginx | Nginx 1.27 | Reverse proxy with TLS termination |
| Metabase | Metabase | BI platform for dashboards |
| Prometheus | Prometheus | Metrics collection and alerting |
Data flows through three processing layers:
- Raw layer (
raw_*) β Raw API responses with JSON payloads and normalized key fields for idempotent ingestion - Staging layer (
stg_*) β Canonical normalized model with unified schema across WB and Ozon - Mart layer (
mrt_*) β Aggregated BI views ready for dashboards and API consumption
| Category | Technologies |
|---|---|
| Language | Python 3.14 |
| Web Framework | FastAPI 0.135, Uvicorn 0.41 |
| Task Queue | Celery 5.6, Redis 7.2 |
| Storage | ClickHouse 26.x (clickhouse-connect 0.13) |
| Frontend | React 19, Vite 8, Tailwind CSS 4, Recharts 3, Motion |
| HTTP Client | httpx 0.28 |
| Validation | Pydantic 2.12, pydantic-settings 2.13 |
| Metrics | prometheus_client 0.24 |
| Logging | structlog 25.5 (structured JSON) |
| Automation | PyYAML 6.0 (YAML rules engine) |
| BI | Metabase (Docker) |
| Infrastructure | Docker Compose, Nginx, Prometheus, Grafana |
| Linting | Ruff 0.15 |
| Typing | MyPy 1.19 (strict mode) |
| Tests | pytest 9.0, pytest-asyncio |
| Security | pip-audit, Anchore Grype, SPDX SBOM |
- Active Wildberries and/or Ozon seller accounts with API tokens
- make (for convenience commands)
Requires Docker & Docker Compose v2.
git clone https://github.com/Bormotoon/BormoStats.git
cd BormoStats
cp .env.example .envEdit .env and set at minimum these values:
| Variable | Where to get it |
|---|---|
WB_STATISTICS_API_KEY |
Wildberries β ΠΠΈΡΠ½ΡΠΉ ΠΊΠ°Π±ΠΈΠ½Π΅Ρ β ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ β API |
OZON_CLIENT_ID |
Ozon β ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ β API |
OZON_API_KEY |
Ozon β ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ β API |
ADMIN_API_KEY |
Generate: openssl rand -hex 32 |
make upThis starts ClickHouse, Redis, Backend, Worker, Beat, Nginx (TLS), Metabase β all containerized.
π‘ First build takes 3β5 minutes. Subsequent builds use Docker layer caching.
# Health check
curl http://localhost:18080/health
# Web UI
open https://localhost:18443/ui/
# Metabase BI
open http://localhost:13000Requires Python 3.14+, Node.js 22+, ClickHouse, and Redis installed on the host.
git clone https://github.com/Bormotoon/BormoStats.git
cd BormoStats
cp .env.example .envEdit .env as above, then:
make install
make runmake install creates a venv, installs deps, builds the frontend, and applies migrations.
make run starts Backend (uvicorn), Celery Worker, and Celery Beat in a single terminal.
For production, use the provided systemd units:
sudo make install-systemdThe built-in React SPA is available at https://localhost:18443/ui/. It features:
- Dashboard β Operational overview with key metrics, charts, and task widget
- Sales β Daily sales analytics with filters
- Stocks β Current stock levels by warehouse
- Funnel β Conversion funnel (views β cart β orders)
- Ads β Advertising performance metrics
- Bidder β Ad campaign bid management with CPM/position sliders
- Repricer β Dynamic pricing rules with break-even table
- P&L β Profit & loss statement with expense breakdown
- ABC/XYZ β Assortment analysis with badge classification (AX = Leader, CZ = Illiquid)
- KPIs β Key performance indicators over time
- PIM β Product catalog enrichment: brands, categories, SEO, AI description generation
- Integrations β Stock upload to WB/Ozon, webhook subscriptions, webhook logs
- Watermarks β Ingestion watermark cursors (admin)
- Task Runs β Worker task audit log (admin)
- Admin Actions β Backfill, transform, mart management, maintenance operations
- System β Service health, readiness, Prometheus metrics
π The admin key is stored in session memory only. It must be re-entered after closing the tab or refreshing the page.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/sales/daily |
Daily sales |
GET |
/api/v1/stocks/current |
Current stock levels |
GET |
/api/v1/funnel/daily |
Daily funnel (views β cart β orders) |
GET |
/api/v1/ads/daily |
Daily advertising |
GET |
/api/v1/kpis |
Key performance indicators |
GET |
/api/v1/abc-xyz |
ABC/XYZ assortment analysis |
GET |
/api/v1/pnl |
Profit & loss statement |
GET |
/api/v1/organizations |
Multi-tenant organization management |
GET |
/api/v1/users/me |
Current user profile |
GET |
/api/v1/accounts |
Account switcher list |
GET |
/api/v1/bidder/... |
Bidder rules & campaign status |
GET |
/api/v1/repricer/... |
Repricer rules & break-even data |
GET |
/api/v1/insights/tasks |
Actionable recommendation tasks |
PATCH |
/api/v1/insights/tasks/{id} |
Update task status |
GET |
/api/v1/pim/products |
PIM product catalog |
PATCH |
/api/v1/pim/products/{mp}/{aid}/{pid} |
Update single product PIM data |
POST |
/api/v1/pim/products/generate-description |
AI description generation |
POST |
/api/v1/pim/products/bulk-update |
Bulk product enrichment |
GET |
/api/v1/pim/brands |
Brand reference list |
POST |
/api/v1/pim/brands |
Create brand |
PATCH |
/api/v1/pim/brands/{id} |
Update brand |
DELETE |
/api/v1/pim/brands/{id} |
Delete brand |
GET |
/api/v1/pim/categories |
Category reference list |
POST |
/api/v1/pim/categories |
Create category |
PATCH |
/api/v1/pim/categories/{id} |
Update category |
DELETE |
/api/v1/pim/categories/{id} |
Delete category |
POST |
/api/v1/integrations/stock/update |
Push stock to WB/Ozon APIs |
GET |
/api/v1/integrations/subscriptions |
Webhook subscriptions |
POST |
/api/v1/integrations/subscriptions |
Create webhook subscription |
DELETE |
/api/v1/integrations/subscriptions/{id} |
Delete webhook subscription |
GET |
/api/v1/integrations/logs |
Webhook delivery logs |
Query Parameters:
marketplaceβ filter by marketplace (wborozon)account_idβ account IDdate_from/date_toβ date range (max 92 days)limit/offsetβ pagination
Error Format: {"detail":"...","error":{"code":"...","message":"..."}}
Requires X-API-Key header.
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/admin/watermarks |
Current watermarks (incremental collection cursors) |
POST |
/api/v1/admin/backfill |
Trigger data backfill |
POST |
/api/v1/admin/transforms/recent |
Run transforms for recent period |
POST |
/api/v1/admin/transforms/backfill |
Backfill transforms |
POST |
/api/v1/admin/marts/recent |
Rebuild marts for recent period |
POST |
/api/v1/admin/marts/backfill |
Backfill marts |
POST |
/api/v1/admin/maintenance/run-automation |
Run automation rules |
POST |
/api/v1/admin/maintenance/prune-raw |
Prune old raw data |
GET |
/api/v1/admin/task-runs |
Task run audit log |
| Variable | Description |
|---|---|
BOOTSTRAP_CH_ADMIN_USER |
ClickHouse admin user (for migrations) |
BOOTSTRAP_CH_ADMIN_PASSWORD |
ClickHouse admin password |
CH_USER |
ClickHouse application user |
CH_PASSWORD |
ClickHouse application password |
ADMIN_API_KEY |
Admin API key (generate: openssl rand -hex 32) |
WB_TOKEN_STATISTICS |
WB statistics API token |
WB_TOKEN_ANALYTICS |
WB analytics API token |
OZON_CLIENT_ID |
Ozon client ID |
OZON_API_KEY |
Ozon API key |
| Variable | Description | Default |
|---|---|---|
OZON_PERF_API_KEY |
Ozon Performance API key (for ads) | β |
TG_BOT_TOKEN |
Telegram bot token for alerts | β |
TG_CHAT_ID |
Telegram chat ID for alerts | β |
CH_RO_USER / CH_RO_PASSWORD |
Read-only ClickHouse user for Metabase | β |
CH_HTTP_HOST_PORT |
ClickHouse HTTP host port | 18123 |
BACKEND_HOST_PORT |
Backend HTTP host port | 18080 |
BACKEND_TLS_HOST_PORT |
Backend HTTPS host port | 18443 |
METABASE_HOST_PORT |
Metabase host port | 13000 |
STACK_NAME |
Docker Compose stack name | bormostats |
| Service | Port | Scope |
|---|---|---|
| Backend HTTP (nginx) | 18080 |
Public |
| Backend HTTPS (nginx) | 18443 |
Public |
| Metabase | 13000 |
Loopback |
| ClickHouse HTTP | 18123 |
Loopback |
| Worker metrics | 19101 |
Loopback |
| Beat metrics | 19102 |
Loopback |
π‘ Change port mappings in
.envif they conflict with existing services.
- All application containers run as non-root user (
app, uid/gid10001) read_only: trueβ container filesystems are read-onlyno-new-privilegesβ privilege escalation disabledtmpfsfor/tmpβ writable temp storage only- Public entry point is only nginx reverse proxy; backend is never exposed directly
- Loopback-only ports (ClickHouse, Metabase, metrics) on isolated
opsnetwork - Redis runs on a private Docker network with no published ports
- Admin API restricted to a typed allowlist of endpoints
- Admin key in web UI stored in session memory (tab-scoped)
- ClickHouse application uses a dedicated user (not bootstrap admin)
- Worker and beat isolated from public network
- Optional read-only ClickHouse user for Metabase
Detailed instructions in docs/credential_rotation.md:
- WB tokens (expire after 180 days)
- Ozon Client ID / API Key
- Admin API Key
- ClickHouse credentials
- Telegram secrets
Please do not file public issues for security vulnerabilities. Use GitHub Private Vulnerability Reporting or contact maintainers directly. See SECURITY.md for details.
# Run all tests
make test
# Full check suite (lint + format + typecheck + test)
make check
# Load smoke test
make perf-smoke
# Validate Docker Compose config
make docker-configtests/unit/β Unit tests (parsers, validation, business logic)tests/integration/β Integration tests (admin API, full scenarios)tests/fixtures/β JSON fixtures (e.g.,ozon_cancelled_posting.json)
Current coverage: 54 unit tests.
BormoStats/
βββ .github/ # CI/CD, issue/PR templates, Dependabot
β βββ workflows/ci.yml # 4-job GitHub Actions pipeline
β
βββ backend/ # FastAPI + Uvicorn
β βββ app/
β β βββ main.py # Entry point: routers, health, metrics
β β βββ api/v1/ # REST API routes (sales, stocks, funnel, ads, kpis, bidder, repricer, pnl, abc-xyz, insights, pim, integrations, admin)
β β βββ core/ # Config, deps, logging, rate limiting
β β βββ db/ # ClickHouse client + SQL queries
β β βββ models/ # Pydantic request/response models
β β βββ services/ # Business logic (MetricsService, AdminService, PimService, InsightsService, IntegrationsService)
β β βββ ui/ # Embedded web UI (built SPA)
β βββ Dockerfile # Multi-stage build (Node β Python)
β
βββ workers/ # Celery workers
β βββ app/
β β βββ celery_app.py # Celery application config
β β βββ beat_schedule.py # Periodic task schedule
β β βββ tasks/ # wb_collect, ozon_collect, transforms, marts, maintenance, bidder, repricer, insights
β β βββ sql/ # SQL transforms and mart definitions
β β βββ utils/ # Locking, watermarks, metrics, data quality
β βββ Dockerfile
β
βββ frontend/ # React 19 SPA
β βββ src/ # Components, pages, utilities
β βββ vite.config.js
β βββ package.json
β
βββ collectors/ # Marketplace API clients
β βββ wb/ # Wildberries: client, endpoints, parsers
β βββ ozon/ # Ozon: client, endpoints, parsers, error handling
β βββ common/ # HTTP client, retry, circuit breaker, redaction
β
βββ warehouse/ # ClickHouse schema and migrations
β βββ migrations/ # Sequential SQL migrations (0001β0020)
β βββ apply_migrations.py
β βββ ddl/ # Reference DDL
β
βββ infra/ # Infrastructure
β βββ docker/ # Docker Compose, ClickHouse, Nginx config
β βββ monitoring/ # Prometheus config + alert rules
β βββ nginx/ # Reverse proxy config + TLS certs
β
βββ automation/ # YAML automation rules engine
β βββ engine.py # AST-based rule evaluator (no exec/eval)
β βββ actions/ # Telegram action executor
β βββ rules/ # bad_acos, low_stock, no_sales_7d, turnover_alert, stagnant_stock, bad_ad_efficiency, daily_digest
β
βββ scripts/ # Operator utilities
β βββ bootstrap.sh # Full stack initialization
β βββ run_local.sh # One-command Docker launcher
β βββ backfill.py # Manual data backfill
β βββ provision_clickhouse_users.py
β
βββ tests/ # Test suite (54 unit tests)
β βββ unit/ # Unit tests
β βββ integration/ # Integration tests
β βββ fixtures/ # JSON API fixtures
β
βββ docs/ # Operational documentation
β βββ architecture.md # Architecture and data flows
β βββ environments.md # Dev/stage/prod model
β βββ observability.md # Metrics, alerts, Grafana
β βββ disaster_recovery.md # Backups, RPO/RTO
β βββ credential_rotation.md # Secret rotation procedures
β βββ troubleshooting.md # Problem diagnosis
β βββ runbooks.md # Operator procedures
β βββ ... # Release management, migration policy, etc.
β
βββ screenshots/ # UI screenshots for README
βββ .github/ # CI/CD workflows
βββ Makefile # Root Makefile
βββ pyproject.toml # Python project config
βββ requirements.txt # Pinned production dependencies
βββ requirements-dev.txt # Development dependencies
βββ .env.example # Environment template
βββ docker-compose.yml # Full stack definition
βββ README.md # English (default)
βββ README.ru.md # Π ΡΡΡΠΊΠ°Ρ Π²Π΅ΡΡΠΈΡ
βββ CONTRIBUTING.md
βββ SECURITY.md
βββ CODE_OF_CONDUCT.md
βββ LICENSE
| Document | Contents |
|---|---|
| Architecture | System architecture and data flows |
| Environments | Dev/stage/prod environment model |
| Observability | Prometheus metrics, Grafana, alerts |
| Disaster Recovery | Backups, RPO/RTO, recovery procedures |
| Credential Rotation | Secret rotation procedures |
| Migration Policy | Database migration policy |
| Performance | Performance targets and benchmarks |
| Runbooks | Operator runbooks |
| Troubleshooting | Problem diagnosis guide |
| Release Management | Versioning and deployment |
| Supply Chain Security | Dependency security and SBOM |
We welcome contributions! Please see CONTRIBUTING.md for detailed guidelines.
python3 -m venv .venv
./.venv/bin/pip install -r requirements-dev.txt
cp .env.example .env
# Set at minimum WB_STATISTICS_API_KEY and OZON_* keysmake lint # Ruff linting
make format-check # Ruff format check
make typecheck # MyPy strict typing
make test # pytest (54 tests)requirements.txtandrequirements-dev.txtare fully pinned versions- Docker images in Docker Compose are pinned by digest
- Dependency updates require a clean virtualenv and full test suite run
- CI runs pip-audit, Docker image scanning, and SBOM generation on every push
- Dependabot automatically creates PRs for dependency updates weekly
BormoStats is free and self-hosted. If it helps your marketplace business β support development:
MIT β feel free to use, modify, and distribute.









