Skip to content

Otto Articles Endpoints

Base path: /api/v1/multi + router prefix /otto/articles → full base: /api/v1/multi/otto/articles

Summary: Endpoints that manage Otto-specific flows: cron control for the Otto price monitor, sync from Otto API, price monitoring (Selenium-based), recalculate pricing, single-price changes, and XLSX upload/download utilities used to provide category/provision mappings.

Auth: Bearer JWT required for all endpoints.

Rate limiting: Subject to global rate limiter (250 requests / 60s). Monitoring and price-change flows spawn concurrent Selenium sessions; coordinate usage to avoid resource exhaustion.


Cron job control

  • POST /cron/start — Start or update the Otto price monitor cron job
  • Payload/params: schedule (cron string, default 0 8 * * *), discord_webhook (optional), sync (bool to run sync step)
  • Response: CronStartResponse with schedule

  • POST /cron/stop — Stop the Otto cron job

  • GET /cron/status — Retrieve cron job status (next run, last run, arguments)

Notes: Cron jobs are managed with services.cron_service.CronJobManager and persist jobs in DB so they are restored on startup.


Sync & monitoring

  • POST /sync_from_otto — Trigger background sync to import active SKUs and create/update DB OttoDetails. Uses a multi-step flow to fetch active-status in bulk and then fetch product details for candidates. After listings, also runs SPA ads sync (step 5) when credentials allow.

  • POST /sync_ads_from_otto — Ads-only background job (since 1.8.19). Creates an Otto SPA product-performance report (SKU, TOTAL_COSTS, TOTAL_ORDERED_SKUS, grouped by SKU), polls until READY, downloads the CSV, and writes per-SKU rollups:

  • otto_details.total_ad_costsTOTAL_COSTS (cents → euros, ÷ 100)
  • otto_details.total_ad_salesTOTAL_ORDERED_SKUS (ordered unit qty, not revenue)
  • Optional query param sku to apply a single SKU from the report.
  • Requires OAuth scope advertising-services. Date window: year start → yesterday, clamped to Otto’s last 90 days.
  • Websocket task name: sync_ads.

  • POST /monitor/{sku} — Manually trigger the price monitoring flow for a specific SKU (or null for all active items). Monitoring uses concurrent Selenium sessions via services.otto.Otto_Service and updates OttoDetails and RepricerArticle records. Emits websocket notifications and can send summary webhooks.

  • monitor_all_prices — Internal function orchestrating concurrent Selenium-based price checks and updates for all active items. Handles driver lifecycle, proxies, and history recording.


Recalculation & exports

  • POST /recalculate and POST /recalculate/{sku} — Trigger Otto-specific recalculation using category provision mappings (from uploaded XLSX) and package mapping. Persists min_price, max_price, expected_profit, margin_rule_id, and provision_percentage for Otto details. UI Recalculate All uses force_min_max=True for rules-on SKUs only.

Penner/renner (1.11.3+): article_type penner/renner is never rewritten from margin rules, even with force_min_max=True. Recalc reconstructs the last n8n Adapt step from pricing_history (penner ×0.98, renner floor(×1.02)+0.90), writes those min/max, sets use_min_max_rules=False, marks UPDATE_NEEDED when bounds changed, and pushes the healed max sale price. Shopping-table buy-price force still clears article_type first, then may rewrite bounds.

Missing bounds bootstrap (1.8.10+): when min_price or max_price is NULL before recalc: - Standard min/max are calculated and stored. - sale_price is set to max_price. - use_min_max_rules is enabled. - max_price is pushed to the Otto API and Plenty Otto channel via push_otto_sale_price_to_channels. - Response includes exported count.

Buy-price change export (1.8.10+): when recalculate_articles is called with export_max_sale_price=True (base cron buy-price force recalc via force_recalc_channels_for_buy_price_change): - Min/max are recalculated from the new buy price (force_min_max=True). - sale_price is set to the new max_price. - max_price is pushed to Otto API and Plenty (same helper as bootstrap). - Does not enable use_min_max_rules if it was already configured — only updates sale price and bounds. - UVP articles are excluded from this path.

  • POST /change-price/{sku} — Synchronous single-item price change against Otto API. Updates the DB and calls Plenty channel updates to keep channels in sync. Uses the same push helper as bootstrap export.

File upload / XLSX utilities

  • POST /upload-xlsx — Upload an XLSX file for category provision mappings. Allowed extensions: .xlsx, .xls; max size 100MB.
  • GET /xlsx-content — Return parsed content (columns, row_count, data) for the uploaded file. Uses pandas.read_excel.
  • GET /xlsx-exists — Check whether uploaded file exists and return file metadata.
  • GET /download-xlsx — Download the stored XLSX file.
  • GET /workflow-result-exists and GET /download-workflow-result — Query and download generated workflow result JSONs.

Notes: The XLSX file format is expected to include category and provision columns used by recalc flows; see get_category_provision_mapping for parsing rules.


Operational notes

  • Monitoring uses Selenium drivers and may spawn many concurrent browser sessions — ensure host has available resources and appropriate proxies configured (see proxy endpoints/service).
  • The module uses Otto_Service.cleanup_all_selenium_sessions() to clear drivers before large runs and otto_service.kill_driver() after work completes.
  • Use cron/start with sync=true to perform a full cron-run: sync → recalc → monitor.

  • Endpoint implementation: backend/service_multi-repricer/app/api/v1/endpoints/otto_articles.py
  • Otto service (incl. SPA reporting): backend/service_multi-repricer/app/services/otto/otto_service.py
  • SQL: docker/postgres/updates/add_otto_ad_performance_columns.sql
  • Patch: 1.8.19 — Otto SPA ads

Generated: detailed reference for otto_articles endpoints and operational guidance.