Endpoint reference
REST 1.5 has 126 routes: 51 GET and 75 writes, including 67 inventory-planning routes (17 GET, 50 writes). The tables below are a quick scan of the routes, their filters and what they return. For full request and response schemas, the interactive explorer is the richer view.
OpenAPI spec
Section titled “OpenAPI spec”The full machine-readable contract is served publicly (no auth, no shop data) at:
GET https://prod.logistified.app/api/v1/openapi.jsonPoint Postman, Insomnia, or any OpenAPI 3.1 client at that URL to generate a typed client or browse every parameter and response shape.
Routes per collection
Section titled “Routes per collection”| Collection | Routes | GET | Writes |
|---|---|---|---|
| Purchase orders | 40 | 15 | 25 |
| Stock takes | 4 | 4 | 0 |
| Stock adjustments | 3 | 3 | 0 |
| Transfer orders | 7 | 7 | 0 |
| Manufacturing orders | 3 | 3 | 0 |
| Forecast views | 2 | 2 | 0 |
| Inventory commitments | 13 | 3 | 10 |
| New product plans | 23 | 6 | 17 |
| Sales plans | 15 | 4 | 11 |
| Promotional events | 11 | 2 | 9 |
| Promotional event catalogue | 1 | 1 | 0 |
| Inventory planning options | 4 | 1 | 3 |
| Total | 126 | 51 | 75 |
Endpoints
Section titled “Endpoints”GET endpoints need a read-scope bearer token (a write key works too).
POST / PATCH / DELETE need a write-scope token. Paths below are under /api/v1.
Writes answer 200 unless the row says 201.
Purchase orders: reading
Section titled “Purchase orders: reading”| Path | Returns |
|---|---|
GET /purchase-orders | List (filters: status, supplierId, search, dateField, dateFrom, dateTo, paidStatus, locationId, variantId, sku, limit, cursor). dateField picks the date that dateFrom / dateTo filter |
GET /purchase-orders/{id} | Full detail: header, line items, shipment, addresses, payments, documents |
GET /purchase-orders/{id}/line-items | Line items, each with its delivery schedules[] |
GET /purchase-orders/{id}/payments | Payments |
GET /purchase-orders/{id}/documents | Document metadata |
GET /purchase-orders/{id}/shipment | Shipment (the first one) |
GET /purchase-orders/{id}/shipments | All shipments, each with its line allocations |
GET /purchase-orders/{id}/addresses | Billing + shipping addresses |
GET /purchase-orders/{id}/receipt-schedule | Receiving / incoming schedule |
GET /purchase-orders/{id}/cost-sync-history | Cost-sync history: every unit-cost update this order proposed, with its outcome (?variantIds=a,b narrows). “Proposed” and “failed” rows may still have been applied |
GET /purchase-orders/{id}/log | Activity log |
GET /purchase-orders/{id}/credits | Applied + available supplier credits |
Purchase orders: writing
Section titled “Purchase orders: writing”| Path | Does |
|---|---|
POST /purchase-orders | Create a draft. 201 + Location. An empty body {} is a valid empty draft |
PATCH /purchase-orders/{id} | Update header fields (at least one). status is not accepted here |
DELETE /purchase-orders/{id} | Delete a Draft outright, or soft-delete a Cancelled order |
POST /purchase-orders/{id}/line-items | Add catalog line items (bulk, 1–500). 201 |
POST /purchase-orders/{id}/line-items/custom | Add one non-catalog line. 201 |
PATCH /purchase-orders/{id}/line-items | Update line items (bulk, 1–500). updateSupplier: true also writes the supplier-related values back to the supplier’s catalogue |
PATCH /purchase-orders/{id}/line-items/schedules | Replace the delivery schedule of the named lines (lines[], 1–200 lines, 1–50 deliveries each). Rows you omit are removed |
PATCH /purchase-orders/{id}/line-discounts | Apply or clear a per-unit percentage or fixed discount on selected lines (updates[]), all or nothing |
PATCH /purchase-orders/{id}/addresses/{addressType} | Set the order’s billing, shipping or supplier address: a saved profileId, or custom address fields |
DELETE /purchase-orders/{id}/line-items?lineItemIds=a,b | Delete line items (bulk). Can partly succeed; check failed[] |
POST /purchase-orders/{id}/status | Move the order’s status |
POST /purchase-orders/{id}/confirm | Record confirmed quantities: lines or confirmAll |
POST /purchase-orders/{id}/receive | Record received quantities (absolute totals) |
POST /purchase-orders/{id}/unreceive | Take back received quantities (deltas) |
POST /purchase-orders/{id}/complete | Complete the order and run the cost sync |
POST /purchase-orders/{id}/quick-complete | Receive + sync + complete, in one call from In Progress |
POST /purchase-orders/{id}/shopify-sync | Push received quantities to Shopify |
POST /purchase-orders/{id}/shopify-sync/reset | Clear the sync bookkeeping (Shopify untouched) |
Purchase-order address profiles
Section titled “Purchase-order address profiles”Reusable billing (company) and shipping addresses for new purchase orders. Editing or archiving a profile never rewrites the address already stored on an order.
| Path | Does |
|---|---|
GET /purchase-order-address-profiles | List profiles. Archived ones are hidden unless includeArchived=true |
POST /purchase-order-address-profiles | Save a profile (name, addressType, address). Send profileId to update an existing one. 200 |
POST /purchase-order-address-profiles/{profileId}/archive | Archive a profile so it can’t be picked for new orders |
POST /purchase-order-address-profiles/{profileId}/restore | Restore an archived profile |
GET /suppliers/{supplierId}/address-profile-defaults | The supplier’s default billing and shipping profile ids |
PATCH /suppliers/{supplierId}/address-profile-defaults/{addressType} | Set the supplier’s default profile for that type; { "profileId": null } clears it |
Purchase-order cost sync
Section titled “Purchase-order cost sync”Follow-up actions on the unit-cost updates a completed order sends to Shopify and to supplier
catalogues. Each write takes an optional body requestKey: reuse it only to recover a lost reply,
and use a new one after a refusal. These routes can refuse with their own error codes; see
Errors.
| Path | Does |
|---|---|
POST /purchase-orders/{id}/resync-costs | Re-send the costs of a Completed order that has cost tracking (optional targets: shopify, supplier). Per-target results[] |
POST /purchase-order-cost-targets/{targetKey}/adopt | Resolve an unconfirmed update by adopting the target’s current cost (optional variantId) |
POST /purchase-order-cost-updates/{opId}/cancel | Cancel a proposed update that was never picked up and is more than an hour old |
GET /purchase-order-cost-targets/{targetKey}/history | One cost target’s history and live state, including whether adopt or cancel is possible (?variantId=) |
URL-encode the targetKey in the path (it contains colons, for example
supplier%3A…).
Stock takes
Section titled “Stock takes”Read-only.
| Path | Returns |
|---|---|
GET /stock-takes | List (filters: status, locationId, search, limit, cursor) |
GET /stock-takes/reasons | Configured stock-take reasons |
GET /stock-takes/{id} | Full detail: header + line items |
GET /stock-takes/{id}/line-items | Line items |
Stock adjustments
Section titled “Stock adjustments”Read-only.
| Path | Returns |
|---|---|
GET /stock-adjustments | List (filters: status, locationId, reason, createdBy, search, limit, cursor) |
GET /stock-adjustments/{id} | Full detail: header + line items |
GET /stock-adjustments/{id}/line-items | Line items |
Adjustments are the delta-only sibling of stock takes: a line carries a signed delta (and the resulting value change), never a counted quantity. The header carries the operator (createdBy), the live netQuantityChange, and the revertOf / revertedBy links when the document is part of a revert pair. Reasons are shared with stock takes; read them from GET /stock-takes/reasons.
Transfer orders
Section titled “Transfer orders”Read-only. A commitment can create a linked transfer order through
POST /inventory-commitments/{id}/transfer-orders.
| Path | Returns |
|---|---|
GET /transfer-orders | List (filters: status, search, dateField, dateFrom, dateTo, fromLocationId, toLocationId, variantId, sku, limit, cursor) |
GET /transfer-orders/{id} | Full detail: header (incl. line items), addresses, log |
GET /transfer-orders/{id}/line-items | Line items |
GET /transfer-orders/{id}/shipment | Shipment |
GET /transfer-orders/{id}/documents | Document metadata |
GET /transfer-orders/{id}/addresses | From + to addresses |
GET /transfer-orders/{id}/log | Activity log |
Manufacturing orders
Section titled “Manufacturing orders”Read-only.
| Path | Returns |
|---|---|
GET /manufacturing-orders | List (filters: status (repeatable), executionMode, productionLocationId (repeatable), search, dateField, dateFrom, dateTo, includeMeasures, limit, cursor) |
GET /manufacturing-orders/{id} | Full detail: items to build, materials, and the linked purchase orders / transfers / stock releases, plus computed progress when includeMeasures was requested |
GET /manufacturing-orders/{id}/log | Activity log |
Repeat a repeatable filter instead of joining values with commas:
?status=DRAFT&status=IN_PROGRESS.
Forecast views
Section titled “Forecast views”Read-only. A forecast view is a saved forecast scope you configure in the app (locations, filters, columns, sort). The rows endpoint returns what the view shows: the response carries a columns[] descriptor (id, displayName (the column header in the app), type (string / number / boolean / date), optional unit (currency marks a money column; its currencyColumn names the row key holding that row’s currency code, null meaning the response’s currencyCode) and, for supply-mode views, period) and every row is an object keyed by those ids, plus variantId and productId on every row. Values are the table’s display values as JSON (dates as YYYY-MM-DD, blanks as null). Read columns[] on every page; the view’s columns may change whenever someone edits the view in the app.
| Path | Returns |
|---|---|
GET /forecast-views | List of saved views: viewId, viewName, isStarred, isAutogenerated. Autogenerated (dashboard) views are hidden unless includeAutogenerated=true |
GET /forecast-views/{id}/rows | The view’s rows, view-shaped: currencyCode, columns[], rows[], totalCount, cursor (params: limit (up to 1000, default 50), cursor, variantIds CSV) |
Inventory planning
Section titled “Inventory planning”Three plan collections (inventory commitments, new product plans, sales plans), promotional events with their holiday catalogue, and the planning options. For a worked example of each, see the inventory planning walkthrough.
The three plan collections share these routes and query parameters:
- List (
GET /{collection}):inventoryPlans[]summary headers,totalCount,cursor. Filters:statusesandlocationIds(comma-separated),search,variantId,createdFrom/createdTo, a type-specific date range (below),sort(name,number,status,target,window,launch,created,updated),dir(asc,desc; defaultdesc),limit(up to 50) andcursor. - Detail (
GET /{collection}/{id}):inventoryPlan(the header with summary counts). The header carries no money, so there is nocurrencyCode; items (with prices and theircurrencyCode) are never included, page them separately. - Items (
GET /{collection}/{id}/items):items[],totalCount,cursor,currencyCode. OptionallocationIdandvariantIdfilters;includeCurves=trueadds the daily curves.limitdefaults to and allows at most 250, or 50 withincludeCurves=true. - Status (
POST /{collection}/{id}/status):{ "status": "Confirmed" }, one ofDraft,Confirmed,Locked,Completed,Cancelled. ReturnsinventoryPlanandtransition(from,to). Changing a status never moves stock. - Delete (
DELETE /{collection}/{id}): deletes the plan and its items. ReturnsdeletedandinventoryPlanId. - Bulk item delete (
DELETE /{collection}/{id}/items?itemIds=a,b): 1–500 item ids in the query; the body is ignored. ReturnsdeletedCountanddeletedItemIds.
An id from another plan collection, a deleted plan or an item of another plan all return the same
404 NOT_FOUND.
Inventory commitments
Section titled “Inventory commitments”Known or possible future sales. List date filter: targetDateFrom / targetDateTo (the end date,
falling back to the target date, then the start date).
| Method + path | Does |
|---|---|
GET /inventory-commitments | List |
GET /inventory-commitments/{id} | Header with counts, probability, dates, recipient, linked orders (purchaseOrderIds, linkedOrders, transferOrderId) |
GET /inventory-commitments/{id}/items | Item page |
POST /inventory-commitments | Create a Draft. Header fields plus optional lineItems[] (variantId, plannedUnits, locationId; up to 500). 201 + Location. Returns inventoryPlanId, planNumber, skipped |
PATCH /inventory-commitments/{id} | Edit header fields, including includedInForecast. null clears a date or the recipient. Returns inventoryPlan |
POST /inventory-commitments/{id}/status | Change status |
DELETE /inventory-commitments/{id} | Delete the plan |
POST /inventory-commitments/{id}/items | Add items[] (variantId, plannedUnits, locationId; 1–500). 201. Returns addedCount, skipped |
PATCH /inventory-commitments/{id}/items/{inventoryPlanItemId} | Edit one item: plannedUnits, probability, locationId, targetDate / startDate / endDate, notes. null on probability restores the header value; null on a date clears it, and the item takes the header dates once none of its own remain. Returns item, currencyCode |
DELETE /inventory-commitments/{id}/items?itemIds=a,b | Bulk item delete |
POST /inventory-commitments/{id}/forecast-feed | { "includedInForecast": false } pauses the plan’s demand in the forecast, true resumes it. Works while Locked. Returns inventoryPlanId, includedInForecast |
POST /inventory-commitments/{id}/purchase-orders | Create one draft purchase order per supplier: locationId (receiving), quantityBasis (planned or expected), optional supplierIds. Returns purchaseOrders[], failed[], linkFailures[], unassignedVariantIds; can be a partial 200 |
POST /inventory-commitments/{id}/transfer-orders | Create one linked draft transfer order: fromLocationId, toLocationId, quantityBasis. Returns transferOrderId, transferOrderNumber, optional linkFailure |
- Header fields:
name,demandType,reasonCode,source,notes,probability,justification,targetDate,startDate,endDate,allocationMethod(single,even),recipient. - Timing: a commitment has either a
targetDateor astartDate+endDaterange, not both. A PATCH that changestargetDateclears the range, and one that changes the range clearstargetDate. Confirming needs a header date (PS_HEADER_DATE_REQUIRED) and at least one item (EMPTY_PLAN). - Quantities:
expectedUnitsisplannedUnits×probability(the item’s own, or the header’s).quantityBasis: "expected"orders those units;plannedordersplannedUnits. Each variant’s units are summed across its locations into one order line. - Orders: both order actions work in every status. Suppliers come from each variant’s primary
supplier; variants without one are listed in
unassignedVariantIds. A plan has one linked transfer order: a second call while it exists is refused withTRANSFER_ORDER_ALREADY_LINKED.
New product plans
Section titled “New product plans”Launch demand built from similar products. List date filter: launchDateFrom / launchDateTo.
| Method + path | Does |
|---|---|
GET /new-product-plans | List |
GET /new-product-plans/{id} | Header with counts, launchDate, horizonDays, volume, feedsForecast, includedInForecast, locations[], linked orders and sizeGroups[] |
GET /new-product-plans/{id}/items | Item page |
GET /new-product-plans/{id}/plan-vs-actual | Daily plan against actual sales: asOf, aggregate, items[], offPlan[] (not with locationId), warnings. Optional locationId; collapse=variant combines a variant’s locations and adds cells[] and perLocation[] |
GET /new-product-plans/{id}/order-quantity | Order-quantity preview, nothing created: lines[] (one per item and location) and totalQuantity. Query: coverageDays, coverFrom (launch, today), safetyFactor, moq, packSize, minOnePerSize |
GET /new-product-plans/{id}/size-groups/{groupId}/actual-mix | Actual sales shares of a size group’s sizes since launch, with the gate it must pass (gateMinDays, gateMinUnits). includeFamily=true adds the group’s other locations (siblings[]) and an all-locations comparison |
POST /new-product-plans | Create a Draft: launchDate, horizonDays, items[] (1–200); optional name, taxonomy, notes, locationIds (or "all"), volume, feedsForecast, autoStopOnFirstSale, sizeGroups[]. 201 + Location. Returns inventoryPlanId, planNumber, warnings, skipped |
PATCH /new-product-plans/{id} | Edit name, taxonomy, notes, launchDate, horizonDays, volume, feedsForecast, includedInForecast, autoStopOnFirstSale. Returns inventoryPlan |
POST /new-product-plans/{id}/status | Change status |
DELETE /new-product-plans/{id} | Delete the plan |
POST /new-product-plans/{id}/items | Add items[] (1–200) and optional sizeGroups[]. A plan with locations adds each variant at every location. 201. Returns addedCount, skipped, warnings, historyWarnings, evenShareItemIds |
PATCH /new-product-plans/{id}/items/{inventoryPlanItemId} | Edit one item: locationId, launchDate, sharePercent, volume, similarProducts, curve. Returns item, currencyCode |
DELETE /new-product-plans/{id}/items?itemIds=a,b | Bulk item delete |
POST /new-product-plans/{id}/forecast-feed | Set includedInForecast (pause or resume). Works while Locked. Returns inventoryPlanId, includedInForecast |
POST /new-product-plans/{id}/size-groups | Create a size group: similarProducts (required), optional name, productId, volume, horizonDays, members[] (variantId, sharePercent), keepEdited. Creates one copy per plan location. 201. Returns groupIds, familyId, skipped, keptEdited, overwritten |
PATCH /new-product-plans/{id}/size-groups/{groupId} | Edit that one location’s copy of the group. Omitted similarProducts / members keep their stored values |
DELETE /new-product-plans/{id}/size-groups/{groupId} | Delete the group’s whole family at every location, with its sizes. Returns removedGroupIds |
POST /new-product-plans/{id}/size-groups/{groupId}/apply-mix | Re-split the group’s sizes from UTC today on: source (actual, prelaunch, explicit), mix (explicit: item id → share), allLocations, keepEdited, dryRun. Returns asOf, applied[], skipped[], previousMix[] |
POST /new-product-plans/{id}/rebuild | Recalculate every curve from the saved similar products, shares, volume and launch dates; hand-edited curves are replaced. Returns rebuilt (row count) |
POST /new-product-plans/{id}/purchase-orders | Create linked draft purchase orders: coverageDays, coverFrom, safetyFactor, moq, packSize, minOnePerSize, onHand, incoming, supplierId, poName, splitByLocation, locationId, locationIds. Returns purchaseOrders[], failed[], linkFailures[]; can be a partial 200 |
POST /new-product-plans/{id}/locations | Add locationId: copies the plan’s items and size groups there, built from that location’s history. 201. Returns locationId, itemsCreated, groupsCreated, warnings, historyWarnings |
DELETE /new-product-plans/{id}/locations/{locationId} | Remove a location’s items and groups. The last location can’t be removed (LAST_LOCATION). Returns locationId, itemsRemoved, groupsRemoved, convertedFromAllLocations |
POST /new-product-plans/{id}/locations/sync | For a plan created with locationIds: "all": add active locations it doesn’t have yet. Returns added[], skippedLocations, skipped |
- Items: each item is a
variantIdwith its ownsimilarProducts(up to 10:variantId, optionalweight,historyFrom,historyStartDate) and optionalvolume,launchDate, explicitcurve, orsizeGroupKey+sharePercentto make it a size of asizeGroups[]entry.volumeis a multiplier on the similar products’ sales (1 = the same); the headervolumeis the default for items without their own. - Locations: with
locationIds, every item gets one row per location, each built from that location’s own history. An item’s ownlocationIdis then ignored (a warning says so). - Curves: an explicit
curveholds 1–180 daily units starting on the row’s launch date, rounded to 2 decimals. A size takes acurveor asharePercentin one call, not both (SIZE_CURVE_AND_SHARE). - Forecast: a plan adds launch demand only when the header
feedsForecastistrue(off by default, editable in Draft and Confirmed),includedInForecastistrue(on by default, switchable via/forecast-feedeven while Locked) and the plan is Confirmed or Locked. - After launch: generated size curves, share and volume changes, rebuilds and mix changes keep
the days before UTC today as they are. An explicit
curveand a moved launch date are applied as sent.apply-mixwithsource: "actual"needs 14 days and 30 units of sales (MIX_GATE_NOT_MET);previousMixholds the old shares so you can send them back as anexplicitmix. - Statuses: header, item, size-group, mix and rebuild changes work in Draft and Confirmed. Purchase orders can be created in Draft, Confirmed and Locked.
- Ordering: a plan with locations gets one order per location by default;
splitByLocation: falsecreates one combined order received atlocationId, applying MOQ, pack size and rounding once to each variant’s total (once per size family), so it can order less than the per-location orders together.coverFrom: "today"covers from today’s curve day and subtracts each line’s stock at its location;onHand/incomingreplace that stock for the whole plan. - Order-quantity preview: each line carries
suggestedQuantity; withcoverFrom=todayalsocoverFrom,coverageFromDay,stockOnHandandstockIncoming. The preview takes no stock override.
Sales plans
Section titled “Sales plans”Unit and revenue targets per location. Sales plans never add demand to the forecast, so they have no
forecast-feed and no order routes. List date filter: targetDateFrom / targetDateTo (the window
end).
| Method + path | Does |
|---|---|
GET /sales-plans | List |
GET /sales-plans/{id} | Header with counts, startDate, endDate, allLocations, locations[] |
GET /sales-plans/{id}/items | Item page |
GET /sales-plans/{id}/plan-vs-actual | Daily plan against actual units and revenue: asOf, currencyCode, aggregate, items[], offPlan[] (not with locationId), warnings. Optional locationId; collapse=variant adds cells[] and perLocation[] |
POST /sales-plans | Create a Draft: locationIds (or "all"), startDate, endDate; optional name, taxonomy, notes, seed (variantIds, growthFactor, baselineStart). 201 + Location. Returns inventoryPlanId, planNumber, locationIds, itemsCreated, warnings, historyWarnings |
PATCH /sales-plans/{id} | Edit name, taxonomy, notes, startDate, endDate, reseedTargets. Returns inventoryPlan, plus reseeded, warnings, historyWarnings when targets were re-seeded |
POST /sales-plans/{id}/status | Change status |
DELETE /sales-plans/{id} | Delete the plan |
POST /sales-plans/{id}/items | Add variantIds (1–500) with an optional growthFactor, seeded at every plan location from last year. 201. Returns addedCount, skipped, warnings, historyWarnings |
PATCH /sales-plans/{id}/items/{inventoryPlanItemId} | Edit one item: plannedUnits, notes, curve, revenueCurve. Returns item, currencyCode |
DELETE /sales-plans/{id}/items?itemIds=a,b | Bulk item delete |
POST /sales-plans/{id}/growth | Set growthFactor (0–10), optionally only for variantIds and / or one locationId. Returns updated, reseeded, warnings, historyWarnings |
POST /sales-plans/{id}/locations | Add locationId, seeded from that location’s last year with the saved growth factors. 201. Returns locationId, itemsCreated, warnings, historyWarnings |
DELETE /sales-plans/{id}/locations/{locationId} | Remove a location and its rows. The last location can’t be removed. Returns locationId, itemsRemoved, convertedFromAllLocations |
POST /sales-plans/{id}/locations/sync | For a plan created with locationIds: "all": add active locations it doesn’t have yet. Returns added[], skippedLocations, skipped |
- Seeding: each row starts from its own location’s sales of the same days last year ×
growthFactor(1 = unchanged, 1.2 = +20%). A location never borrows another location’s history; a location without history seeds zeros and is named inhistoryWarnings. - Unknown variants refuse the whole batch (
UNKNOWN_VARIANTS, withvariantIds). - Growth:
/growthrescales each matching row’s current curve, so hand edits keep their proportions. A row at factor 0, or whose curve sums to 0, is re-seeded from history instead (hand edits on it are replaced). - Window: changing
startDate/endDatewhile the plan has rows needsreseedTargets: true, which re-seeds every row and replaces hand edits and revenue overrides. The window can’t be cleared. - Item edits: a curve holds one value per day of the plan window.
revenueCurve: nullrestores revenue as units × price. Changing an item’s location, dates or probability is refused (SALES_PLAN_LOCATION_FIXED,SALES_PLAN_WINDOW_FIXED,SALES_PLAN_FIELD_FIXED).
Promotional events
Section titled “Promotional events”Holidays and sales events that lift the forecast once switched on. Create your own event (name,
category, optional dateRule, durationDays, occurrences) or one from the catalogue
(catalogueHolidayId plus optional name, durationDays, uplift and notes; the catalogue supplies
the category and date rule, so category, dateRule and occurrences are refused).
| Method + path | Does |
|---|---|
GET /promotional-events | List: events[] (each with nextOccurrence), totalCount, cursor. Filters: search, categories (comma-separated), limit (up to 50, default 20), cursor |
GET /promotional-events/{id} | event, stored occurrences[], rule-based projectedOccurrences[], nextOccurrence, the window they cover and today |
POST /promotional-events | Create an event, switched off. 201 + Location. Returns the event detail |
PATCH /promotional-events/{id} | Edit settings, archived or feedsForecast. Returns the event detail |
DELETE /promotional-events/{id} | Delete the event. Returns deleted, eventId |
POST /promotional-events/{id}/occurrences | Store one year’s dates: startDate, endDate (both required), optional uplift, isSkipped. 201. Returns occurrence |
PATCH /promotional-events/{id}/occurrences/{occurrenceId} | Edit only the fields you send; omitted dates keep their stored values. Returns occurrence |
DELETE /promotional-events/{id}/occurrences/{occurrenceId} | Delete a stored occurrence. Returns deleted, occurrenceId |
POST /promotional-events/{id}/occurrences/{occurrenceId}/analyze | Measure an ended occurrence’s uplift against the days before it and save the result as the event’s measured uplift (optional baselineDays 7–365, saveBaselineDays). Returns analysis, occurrence, materialized, event |
POST /promotional-events/{id}/analyze | The same for a startDate / endDate window, storing it as an occurrence. Returns analysis, occurrence, materialized, event |
POST /promotional-events/{id}/analyze-past-years | Measure up to three past occurrences, newest first (optional baselineDays). Returns years[], range, applies, event |
- Switched off at first: every new event has
feedsForecast: false. Turn it on withPATCH /promotional-events/{id}and{ "feedsForecast": true }.archivedis a separate switch. A forecast view can opt out of event effects on its own. - Uplifts are fractions from 0 to 10:
0.35means +35%.defaultUpliftapplies to every year; an occurrence’supliftoverrides it for that year (nullfalls back to the event’s). - Ids are created for you:
eventIdandoccurrenceIdin a create body are refused. - Analysis: results leave out the daily chart series. In
analyze-past-years, a year that couldn’t be measured carrieserror(code,message) inside a200; send the same request with the sameIdempotency-Keyto get that answer again without re-measuring the other years.
Promotional event catalogue
Section titled “Promotional event catalogue”| Method + path | Does |
|---|---|
GET /promotional-event-catalogue | Search the holiday catalogue by name, alias or region code (query; empty lists everything). Returns hits[], each with entry, group and matchedBy |
Each entry carries its catalogueHolidayId, name, category, durationDays, aliases,
regions and dateRule. Send the catalogueHolidayId to POST /promotional-events.
Inventory planning options
Section titled “Inventory planning options”The demand types, reasons and sources plans are tagged with.
| Method + path | Does |
|---|---|
GET /inventory-plan-options | options[], optionally only one type (demandType, reasonCode, source) |
POST /inventory-plan-options | Create: type, name, optional description, color, sortOrder. 201. Returns option |
PATCH /inventory-plan-options/{optionId} | Edit name, description, color, sortOrder or active (not isActive); at least one. Returns option |
DELETE /inventory-plan-options/{optionId} | Delete the option. Returns deleted, optionId |
A name already used within the same type is refused with 400 and error.data.code: "DUPLICATE_NAME", carrying the existing optionId. Plans store the option’s name in demandType,
reasonCode or source, so renaming or deleting an option doesn’t change existing plans.
Planning conventions
Section titled “Planning conventions”Bodies
- Request bodies are strict and belong to one collection: a field from another plan type, an
unknown field, a string where a number or boolean is expected, or a system-owned field
(
planType,eventId,occurrenceId) returns400. - Ids in the path win. A matching id in the body is accepted; a different one returns
400. - Bulk item delete reads only the path and the
itemIdsquery. - Creates return the ids, numbers, counts and warnings the write produced, not the full resource. Read the plan or its items when you need the current state.
Dates and units
- Every planning date is a
YYYY-MM-DDUTC day, including curve days, analytics, event windows and “today” after a launch. Timestamps such ascreatedAtare UTC instants. - Prices and revenue are in the shop currency, given by
currencyCodeon the response. - Share fields (
sharePercent,prelaunchSharePercent) run from 0 to 100.attainmentPercentandrevenueAttainmentPercentare actual ÷ planned × 100: above 100 when sales beat the plan,nullwhen nothing is planned yet.probabilityis a fraction from 0 to 1. Event uplifts are fractions (0.35= +35%).growthFactorandvolumeare multipliers (1.2= +20%). coverageFromDayis a zero-based day index into the curve, not a date.- Query booleans (
includeCurves,includeFamily,minOnePerSize) are on only for the literaltrue.
Idempotency and partial results
- Send an
Idempotency-Keyon every create and every order action. - An order action that created some orders answers
200: keep the created ids, then readfailedandlinkFailures(linkFailurefor a transfer order). Replay the same key to get that answer again; retry only the failedsupplierIdsorlocationIdswith a new key. Planning create and order retries has the full rules.
Not exposed over REST
- Previews and calculators that don’t save anything (curve generation, mix previews, history lookups, sales-plan seed previews).
- Plan documents, PDFs, exports and the activity log; restoring products at a location.
- Creating a Shopify draft (sales) order from a commitment.
- A separate single-item delete or curve route for new product plans: use the bulk item delete and
the item
PATCHwithcurve. - Plan-vs-actual for commitments, and forecast-feed or order routes for sales plans.