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, default0 8 * * *),discord_webhook(optional),sync(bool to run sync step) -
Response:
CronStartResponsewith 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 bySKU), polls untilREADY, downloads the CSV, and writes per-SKU rollups: otto_details.total_ad_costs←TOTAL_COSTS(cents → euros, ÷ 100)otto_details.total_ad_sales←TOTAL_ORDERED_SKUS(ordered unit qty, not revenue)- Optional query param
skuto 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
nullfor all active items). Monitoring uses concurrent Selenium sessions viaservices.otto.Otto_Serviceand updatesOttoDetailsandRepricerArticlerecords. 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, andprovision_percentagefor Otto details. UI Recalculate All usesforce_min_max=Truefor 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
proxyendpoints/service). - The module uses
Otto_Service.cleanup_all_selenium_sessions()to clear drivers before large runs andotto_service.kill_driver()after work completes. - Use
cron/startwithsync=trueto perform a full cron-run: sync → recalc → monitor.
Links¶
- 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.