Skip to content

Health & Verification Endpoints

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

Summary: Lightweight audit endpoints that help you notice repricer problems early (missing records, stale buy-price sync, suspected “stuck” exports).

These checks are tuned for a once-per-day base repricer cron and are designed to be safe: they do not recalculate or export anything — they only report likely issues.


Get last stored reports

  • GET /report
  • Returns the last stored audit payloads for:
    • base (last stored report on the base cron job, if present)
    • health_audit (last stored health audit report)

Response (shape):

{
  "base": { "generated_at": "..." },
  "health_audit": {
    "generated_at": "...",
    "checked": 123,
    "buy_price_mismatch_count": 0
  }
}

Run buy-price audit (on demand)

  • POST /audit/buy-price

Query parameters:

  • days (int, default 3): window for shopping-table entries to inspect
  • max_hours_after_base_run (int, default 48): how long after the last base cron run we still consider a missing update “acceptable” (base cron typically runs once daily)
  • limit (int, default 50): cap for returned example rows per category

What it checks:

  • Missing local: shopping_table.asin_sku exists but there is no local base article with that SKU.
  • Buy price mismatch: the latest shopping-table EK within the window differs from repricer_articles.brutto_buy_price and the shopping row is not newer than the last base cron run.
  • Pending next base run: shopping-table EK is newer than the last base cron run (expected until tomorrow’s cron).
  • FBA stuck UPDATE_NEEDED (heuristic): if last base run had update_prices=true and the EK row is “old”, but FBA detail is still update_needed.

Notes:

  • This audit focuses on buy-price correctness & freshness (the root cause class for issues like “EK changed but Sellerlogic bounds didn’t update”).
  • It does not yet verify external platforms by API (Sellerlogic/Kaufland/Otto/Shopify); that can be added incrementally later.
  • On success the audit writes eval/health_audit_YYYYMMDD_HHMMSS.json (File Manager → eval_multi) and returns capped detail lists (missing_local, buy_price_mismatch, …).
  • Buy-price mismatches ignore tiny rounding differences (≤ €0.01), e.g. 52.8507 vs 52.85.
  • Cross-platform bound check: compares min/max prices across Otto, Kaufland, FBA (DE + exportable regions), and FBM (exportable regions). Articles with ≥2 channel bounds are compared; mismatches beyond €0.01 are flagged in cross_platform_bound_mismatch.
  • External API bound check: verifies every article with marketplace bounds against live Kaufland (minimum_price / listing_price) and Sellerlogic FBA/FBM (min_price_b2c / max_price_b2c). Uses existing rate limiters + 250ms throttle between calls. Set external_verify_limit > 0 only to sample; 0 (default) = all. Otto has no external min/max API.
  • Eval files (health_audit_*, sync_eval_*) older than 30 days are deleted automatically.
  • Discord alerts include counts plus sample SKUs and the eval filename when findings are non-zero.

Debug / observability test endpoints

For verifying Sentry and Prometheus integration (JWT required). Useful from the dashboard Debug → Observability page.

  • GET /debug/status
  • Returns whether SENTRY_DSN is configured and lists available debug endpoints.

  • POST /debug/sentry/crash

  • Intentional ZeroDivisionError — should appear in Sentry via FastAPI integration.

  • POST /debug/sentry/log-error

  • Logs ERROR with exc_info=True via the custom backend_logging logger (Loki + Sentry).

  • POST /debug/sentry/capture-message

  • Query param message (optional) — manual sentry_sdk.capture_message.

  • POST /debug/prometheus/test

  • Increments test counter repricer_debug_test_total (visible on service GET /metrics).

Configure the audit cron (webhook + window)

  • GET /cron/status
  • Returns the current cron config for repricer_health_audit (expression, next/last run, arguments) and the last stored report.

  • POST /cron/config

  • Updates the cron job’s arguments and optionally the schedule.

Query parameters:

  • schedule (string, optional): cron expression (defaults to the current one)
  • days (int, default 3)
  • max_hours_after_base_run (int, default 48)
  • discord_webhook (string, optional): Discord webhook URL for alerts
  • notify_on_nonzero (bool, default true): only notify when findings are > 0

Cron job

On service startup, a new cron job is auto-created if missing:

  • Name: repricer_health_audit
  • Default schedule: every 48 hours (0 0 */2 * *, midnight every second day)
  • A safety guard skips runs if the previous audit was less than 48 hours ago
  • Default arguments: {"days": 3, "max_hours_after_base_run": 48, "discord_webhook": null, "notify_on_nonzero": true}

The audit report is persisted into cron_jobs.arguments.last_report for this job.


Implementation

  • Source: backend/service_multi-repricer/app/api/v1/endpoints/health.py