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 2 — Authentication & the client

Don't write your own auth

All Backoffice endpoints are POST, JSON in and out, and session-authenticated via a cookie named LLSession.

POST https://themint.backoffice.dutchie.com/api/posv3/user/EmployeeLogin
Content-Type: application/json
appname: Backoffice

{ "UserName": "<employee email>", "Password": "<password>" }

The response contains Data.SessionGId. Use it as Cookie: LLSession=<SessionGId> on every subsequent call. Sessions expire at ~60 min.

Use the production client at packages/inventory-service/api/dutchieBackoffice.js:

const Client = require('./packages/inventory-service/api/dutchieBackoffice.js');
const client = new Client();
await client.getSession();   // cached + auto-refreshes at 50 min
const result = await client.post('v2/inventory/get-inventory', { LocId: 1989 });

Env vars: DUTCHIE_BACKOFFICE_USERNAME, DUTCHIE_BACKOFFICE_PASSWORD.

Dutchie Inventory Intake via Backoffice API
Module 1 — The three sandboxes

Know where you're writing to

Before writing a line of code, know where you're writing to. Our Dutchie session (UserId=60672) sees three locations named "Sandbox":

LocIdStateCompanyWhen to use
1989AZDispensaryDefault for intake work. Mirrors Tempe's retail setup — rooms, registers, vendors already configured.
2862ILManufacturingOnly for IL-specific manufacturing flows. Has no rooms — intake writes orphan.
2869OHDispensaryOnly for OH-specific flows.

Why this matters

The first version of our memory doc listed LocId 2862 as "the sandbox" because a naïve filter (GetLspLocationsBackend with LspId=575) only returned IL locations. The AZ sandbox wasn't visible under that filter. Always call GetLspLocationsBackend with an empty body {} to see all 18 locations across LSPs.

Check for understanding

  1. A teammate asks you to "test against the sandbox." What's your first question?
  2. If v2/inventory/receive returns Result: true but no packages appear, which LocId did they probably send it to?