Inventory

DayZero's inventory module covers products, variants, purchase orders, shipments, warehouse locations, transfers, cycle counts, and production. This feature requires the Commerce add-on.

Most inventory routes live under /api/v1/inventory/…; purchase orders are at /api/v1/purchase-orders and customer order forms at /api/v1/orders.

Products

Create a Product

bash
curl -X POST "https://api.ondayzero.com/api/v1/inventory/products" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Widget Pro",
    "type": "manual",
    "category": "Hardware"
  }'

type is the product's source: manual (created here) or shopify (synced from a connected store — don't create these yourself). Set tracks_expiration: true for perishable goods so cost lots carry expiry dates.

List Products

bash
curl "https://api.ondayzero.com/api/v1/inventory/products?type=manual&include_variants=true&archived=false" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"
Parameter Type Description
type string manual or shopify
category string Filter by category
search string Match on product name
include_variants boolean Embed variant data in each product
archived boolean true only archived, false only live, omit for all

Plus the standard pagination parameters.

Variants

Products can have multiple variants (sizes, colors, etc.). Variants are what you stock, price and put on invoices:

bash
curl -X POST "https://api.ondayzero.com/api/v1/inventory/products/variants" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": "PRODUCT_UUID",
    "name": "Widget Pro - Large",
    "sku": "WP-LG-001",
    "barcode": "0123456789012",
    "unit_price": 2999,
    "unit_cost": 1250,
    "uom": "EA",
    "initial_inventory_quantity": 100
  }'

unit_price (sale price) and unit_cost are in cents: 2999 = $29.99. For sub-cent costs (ingredients priced per gram) use unit_cost_precise in dollars, e.g. 0.0478.

GET /api/v1/inventory/products/variants?product_id=… lists variants; GET /api/v1/inventory/products/lookup?sku=WP-LG-001 (or ?barcode=…) finds one for scanning workflows. PUT /api/v1/inventory/products/variants/{id}/location-quantities sets opening quantities per warehouse.

Purchase Orders

Purchase orders to vendors — and the shipments, receipts and bills that follow them — live under /api/v1/purchase-orders:

bash
curl "https://api.ondayzero.com/api/v1/purchase-orders?status=submitted&vendor_id=VENDOR_UUID" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Statuses run draft → submitted → in_production → ready → shipped → partially_received / received → completed, or canceled. POST /api/v1/purchase-orders creates one. Receiving against a PO updates on-hand quantities, and GET /api/v1/inventory/accounts-payable lists the vendor bills generated from POs with their three-way-match status (PO ↔ receipt ↔ bill). Customer-facing order forms are separate: GET / POST /api/v1/orders.

Locations

Warehouse and storage locations:

bash
curl "https://api.ondayzero.com/api/v1/inventory/locations" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

POST /api/v1/inventory/locations creates one; POST …/locations/{location_id}/set-default chooses where unlocated stock movements land; GET …/locations/{location_id}/inventory shows what is on hand there and GET …/locations/summaries compares all locations at once.

Shipments

Track inbound and outbound shipments tied to orders:

bash
curl "https://api.ondayzero.com/api/v1/inventory/shipments" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

Transfers

Move inventory between locations:

bash
curl -X POST "https://api.ondayzero.com/api/v1/inventory/transfers" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "from_location_id": "LOCATION_UUID_1",
    "to_location_id": "LOCATION_UUID_2",
    "items": [
      {"variant_id": "VARIANT_UUID", "quantity": 10}
    ]
  }'

A transfer is created pending; POST …/transfers/{transfer_id}/ship moves the stock in transit and POST …/transfers/{transfer_id}/receive lands it at the destination (/cancel abandons it). Optional fields: carrier, tracking_number, expected_arrival_date, shipping_cost (cents). GET /api/v1/inventory/transfer-suggestions/suggestions proposes site-to-site rebalancing.

Adjustments

Record a manual inventory adjustment (shrinkage, corrections, etc.) — one variant per call:

bash
curl -X POST "https://api.ondayzero.com/api/v1/inventory/adjustments" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "variant_id": "VARIANT_UUID",
    "location_id": "LOCATION_UUID",
    "quantity_change": -5,
    "reason": "Damaged in transit",
    "reason_code": "damage"
  }'

quantity_change is signed (negative removes stock). If location_id is omitted the default location is used. For a full stock take, use cycle counts instead: POST /api/v1/inventory/counts starts one, POST …/counts/{count_id}/lines and PUT …/counts/{count_id}/lines/{line_id} record counted quantities, and POST …/counts/{count_id}/post books the variances. GET /api/v1/inventory/reports/adjustment-reasons summarises adjustments by reason.

Production

Manage recipes (bills of materials) and production runs for manufactured goods:

bash
curl "https://api.ondayzero.com/api/v1/inventory/production/recipes" \
  -H "Authorization: Bearer dz_your_token_here" \
  -H "x-business-id: YOUR_BUSINESS_ID"

POST /api/v1/inventory/production/runs schedules a run from a recipe, POST …/runs/{run_id}/calculate previews component consumption and cost, and POST …/runs/{run_id}/complete consumes the components and adds the finished goods.

Reports and planning

  • GET /api/v1/inventory/reports/valuation — current inventory value; …/reports/aging and …/reports/margin-by-sku for slow movers and margins.
  • GET /api/v1/inventory/cost-history — landed COGS over time; GET /api/v1/inventory/lots/expiring — cost lots approaching expiry.
  • GET /api/v1/inventory/reorder/suggestions — what to reorder based on reorder points; POST /api/v1/inventory/reorder/draft turns suggestions into draft purchase orders and POST …/reorder/cash-impact previews the cash effect.
  • GET /api/v1/inventory/forecast/skus — per-SKU demand forecasts (POST …/forecast/recompute to refresh).
  • GET /api/v1/inventory/activity — a unified movement log across receipts, sales, transfers, adjustments and production.

Import

Bulk import products, variants, locations and stock levels from a spreadsheet using a 3-phase AI-assisted flow:

  1. Analyze — POST /api/v1/inventory/import/analyze (multipart file) returns a task_id; poll GET /api/v1/inventory/import/analyze/{task_id} until the AI has mapped the sheets and columns.
  2. Preview — POST /api/v1/inventory/import/preview with the file_id, selected_sheets and (optionally corrected) sheet_mappings returns exactly what would be created or updated.
  3. Apply — POST /api/v1/inventory/import/apply with the file_id and the reviewed products, locations and levels decisions.

The same pattern under /api/v1/inventory/po-import/… turns a manufacturer's order spreadsheet into a purchase order with SKU matching.