Plenty
service_omni — Endpoints: Plenty¶
Location: backend/service_omni/app/api/v1/endpoints/plenty.py
Base path: /api/v1/omni/plenty (JWT auth unless noted).
Summary¶
- Manage Plenty API credentials
- Import sales orders into
plenty_orders - Import return orders (Retouren) into
plenty_retoursand link to parent sales orders - Legacy Shopify export tasks
For the data model and Metabase queries, see Plenty orders & retours.
Credentials¶
| Method | Route | Description |
|---|---|---|
POST |
/credentials/ |
Create credential (PlentyCredentialsCreate) |
GET |
/credentials/ |
List credentials |
PUT |
/credentials/{credential_id} |
Update credential |
POST |
/credentials/{credential_id}/toggle-active |
Toggle active_omni |
DELETE |
/credentials/{credential_id} |
Delete credential |
POST |
/credentials/test |
Validate username/password/plenty_id |
Example create body:
{
"username": "plenty_user",
"password": "secret",
"plenty_id": 69524,
"active_omni": true
}
Order and retour imports use the credential with active_omni=true.
Sales orders¶
| Method | Route | Description |
|---|---|---|
POST |
/orders?date=YYYY-MM-DD |
Fetch & store paid sales orders for one day |
POST |
/orders/range?start_date=…&end_date=… |
Backfill sales orders for each day in range |
Plenty filter: sales orders (orderTypeId=1), statusId=7, order date = query date.
Response (PlentyOrdersResponse):
{
"date": "2026-07-13",
"total_lines": 42,
"lines": [{ "order_id": 51657, "asin_sku": "…", "…": "…" }]
}
Unpaid orders (property typeId=4 ≠ fullyPaid) are queued in plenty_pending_orders for cron retry.
Example:
curl -X POST "http://localhost:8007/api/v1/omni/plenty/orders/range?start_date=2026-07-01&end_date=2026-07-13" \
-H "Authorization: Bearer $TOKEN"
Retours (returns)¶
| Method | Route | Description |
|---|---|---|
POST |
/retours?date=YYYY-MM-DD |
Fetch & store return orders for one day |
POST |
/retours/range?start_date=…&end_date=… |
Backfill retours for each day in range |
Plenty filter: return orders (orderTypeId=4), orderDate_2 on selected day.
Side effects:
- Rows upserted into
plenty_retours(one row per returned article line) - Missing parent sales orders fetched from Plenty and inserted into
plenty_orders - Parent orders marked
has_retour=trueinplenty_orders
Response (PlentyRetoursResponse):
{
"date": "2026-07-13",
"total_lines": 5,
"parent_orders_total": 5,
"parent_orders_fetched": 4,
"parent_orders_marked": 5,
"parent_orders_missing": 0,
"lines": [
{
"retour_id": 52484,
"parent_order_id": 51657,
"retour_date": "2026-07-13",
"asin_sku": "RitualsSakuraGeschenkSetS2025",
"price_gross": 39.9
}
]
}
| Field | Meaning |
|---|---|
parent_orders_total |
Unique parent sales order IDs from retours |
parent_orders_fetched |
Parents newly imported from Plenty (not in DB before) |
parent_orders_marked |
Parents now flagged has_retour=true |
parent_orders_missing |
Parent IDs Plenty did not return |
Example:
curl -X POST "http://localhost:8007/api/v1/omni/plenty/retours/range?start_date=2026-07-13&end_date=2026-07-13" \
-H "Authorization: Bearer $TOKEN"
Frontend: Statistics → Profit → Manual Plenty Retour Date Range Import.
Shopify export (legacy)¶
| Method | Route | Description |
|---|---|---|
POST |
/export/to/shopify |
Start export task |
POST |
/export/to/shopify/stop |
Stop export |
GET |
/export/to/shopify/status |
Export status |
Artifacts under shopify_export_data/ (TODO/done/failed JSON files).
Implementation¶
| Component | Path |
|---|---|
| Endpoints | plenty.py |
| Plenty manager | plenty_manager.py |
| Orders CRUD | plenty_orders.py |
| Retours CRUD | plenty_retours.py |
| Models / DB schema | schemas/plenty.py |
Operational notes¶
- Ensure the Plenty account has order read permissions before bulk import.
- Retour import date = return creation date, not original sale date — parent backfill covers older sales orders.
- Re-importing the same retour day replaces rows for the same
retour_id(idempotent upsert).