Skip to Content
Dutchie Inventory Intake via Backoffice API

Dutchie Inventory Intake via Backoffice API

Mint stores receive physical inventory every day. The canonical source of truth for what's on the shelf is Dutchie.

This course walks through the Backoffice REST intake flow end-to-end against the AZ sandbox (LocId 1989) — the same path production uses, with zero risk to real stock.

Learning objectives

  • Authenticate against the Dutchie Backoffice REST API and reuse a cached session.
  • Identify which of the three sandboxes to use for AZ-dispensary testing.
  • Fetch the prerequisite IDs — vendor, room, product — that a receive call needs.
  • POST an inventory receive with the correct field shape and explain why each field is required.
  • Verify a receive materialized using the right read endpoints (and the subtle parameter gotcha).
  • Diagnose the three most common failures: orphaned receives, empty reads, SQL errors.

Prerequisites: Familiarity with HTTP/REST and JSON. Access to Dutchie Backoffice credentials. Clone of letsgomint-us repo.

Source: docs/elearning/dutchie-inventory-intake-course.md

Responsible Juan Palomino
Last Update 04/18/2026
Completion Time 50 minutes
Members 2
Dutchie Inventory Intake via Backoffice API

Module 3 — Prerequisite IDs

Vendor, room, product

A receive call needs three IDs you cannot guess. Pull them first.

3.1 Vendor

const vendors = await client.post('vendor/get-vendors', { LocId: 1989 });
// [{ VendorId: 39195, VendorName: 'PALOMINO PRINTING', ... }]

Note the path has no v2/ prefix. Common misguess: v2/vendor/get-vendors returns 404.

3.2 Room

const rooms = await client.post('v2/room/get-rooms', { LocId: 1989 });
// [{ RoomId: 24772, RoomName: 'Sales Floor', PosRoom: 'yes', InventoryRoom: 'yes' }]

At the AZ sandbox there are 4 rooms. Pick one whose InventoryRoom === yes.

3.3 Product

const lite = await client.post('product-master/get-products-lite', { LspId: 575 });
// [{ ProductId: 11484902, Sku: '3B4791', Name: 'Tommy Chong Joint (H)', ... }]

get-products-lite is LSP-scoped (~17k products). For richer detail use get-product-master.

Dutchie Inventory Intake via Backoffice API
Module 3 — Prerequisite IDs

Vendor, room, product

A receive call needs three IDs you cannot guess. Pull them first.

3.1 Vendor

const vendors = await client.post('vendor/get-vendors', { LocId: 1989 });
// [{ VendorId: 39195, VendorName: 'PALOMINO PRINTING', ... }]

Note the path has no v2/ prefix. Common misguess: v2/vendor/get-vendors returns 404.

3.2 Room

const rooms = await client.post('v2/room/get-rooms', { LocId: 1989 });
// [{ RoomId: 24772, RoomName: 'Sales Floor', PosRoom: 'yes', InventoryRoom: 'yes' }]

At the AZ sandbox there are 4 rooms. Pick one whose InventoryRoom === yes.

3.3 Product

const lite = await client.post('product-master/get-products-lite', { LspId: 575 });
// [{ ProductId: 11484902, Sku: '3B4791', Name: 'Tommy Chong Joint (H)', ... }]

get-products-lite is LSP-scoped (~17k products). For richer detail use get-product-master.

Dutchie Inventory Intake via Backoffice API
Module 6 — Common misdiagnoses & final assessment

When it breaks

SymptomRoot causeFix
Cannot insert the value NULL into column 'Status'Missing header StatusAdd Status: "Received" at top level
Receive returns true, preorder/inventory unchangedMissing RoomId per productAdd RoomId to every Products[] item
get-packages-from-receive returns []Used Id instead of ReceiveInventoryHistoryIdRename the param
User is not permittedEndpoint needs elevated permissionsNot fatal for intake — use scope-appropriate endpoints
Receive succeeds but location has no roomsUsing IL (2862) or OH (2869) sandboxSwitch to AZ sandbox (1989)

Final assessment

Work through these against the AZ sandbox (LocId 1989). Use scripts/_probe/sandbox-az-retry.cjs as reference.

  1. Authenticate and confirm your session sees at least 18 locations.
  2. Pick a vendor, a room (InventoryRoom === "yes"), and two cannabis products.
  3. POST a receive for quantity 3 of each. Capture the returned ReceiveInventoryHistoryId.
  4. Verify: two new packages, history row with Products: 2, both SKUs in preorder/inventory at Qty 3.
  5. Summarize what you'd do if step 4c failed but 4a and 4b passed.

Grading rubric

  • Steps 1-3 complete with Result: true — basic pass.
  • Step 4 all green — working knowledge.
  • Step 5 identifies that packages exist but are in a non-sellable room, and points to checking RoomName on package records — mastery.
Dutchie Inventory Intake via Backoffice API
Module 5 — Verification (the subtle gotcha)

Not done until you've read it back

5.1 Packages

POST api/v2/inventory/get-packages-from-receive
{ "LocId": 1989, "ReceiveInventoryHistoryId": 1379127 }

Use ReceiveInventoryHistoryId — not Id. Passing Id silently returns [] with no error.

Healthy response: one package per product line, each with a PackageId, matching SKU, and Quantity equal to what you sent.

5.2 Receive history

POST api/v2/inventory/get-receive-history
{ "LocId": 1989, "StartDate": "<ISO>", "EndDate": "<ISO>" }

Your new row has Status: "Received", your VendorName, OrderTitle, and Products count.

5.3 Sellable inventory

POST api/preorder/inventory
{ "LocId": 1989 }

Your SKUs appear with Quantity equal to what you received. If not — the packages exist but are in a non-sellable room.