Skip to content

Commerce models and channels

The models an order can belong to, the channels it can arrive on, buy-side and sell-side pricing, and the optional contact, fulfillment and external id fields.

An order has a model (what kind of commerce it is) and a channel (where it came in). Both are part of the order input and both are checked when the order starts. The model also decides which flow a new flow starts from and how lines are priced.

Models: b2b, b2c, d2c, marketplace, subscription, procurement, replenishment.

ModelPricingStarts fromBuilt-in flows
b2b (B2B)Sell-side, price chaintpl-b2b-ordertpl-b2b-order
b2c (B2C retail)Sell-side, price chaintpl-storefront-ordertpl-storefront-order, tpl-pos-sale
d2c (Direct to consumer)Sell-side, price chaintpl-omnichannel-ordertpl-omnichannel-order
marketplace (Marketplace)Sell-side, price chaintpl-marketplace-ordertpl-marketplace-order
subscription (Subscription)Sell-side, price chaintpl-subscriptiontpl-subscription
procurement (Procurement)Buy-side, at costtpl-purchase-requesttpl-purchase-request
replenishment (Replenishment)Buy-side, at costtpl-reordertpl-reorder

input.model is required. A flow has one model and a list of channels it is meant for. Inbound routing and the UI use the channels; they do not restrict which orders run on the flow.

Channels: web, mobile, pos, marketplace, email, edi, api, manual, schedule. input.channel defaults to api. The dashboard starts orders as manual, email intake as email, and the daily stock review as schedule. Storefronts, marketplaces and POS systems send orders with a signed webhook; see Inbound orders, and Shopify webhooks and EDI X12 850 purchase orders (channel edi, label EDI, b2b) arrive through Channel adapters. Orders on pos run the point-of-sale flow, tpl-pos-sale, for the b2c and d2c models. GET /api/v1/orders filters on model and channel (see REST API).

Procurement and replenishment orders are buy-side: the business is the buyer, so lines price at the product’s cost. Every other model is sell-side and runs the pricing chain (price book, contract, volume, list).

The Price node’s basis field makes that explicit:

basis Lines are priced
auto (default) At cost for buy-side models, through the chain otherwise
chain Through the pricing chain, whatever the model
cost At the product’s cost

A line with its own unitPrice keeps it under every basis.

Besides customerId, currency, lines and meta, the input takes:

Field Meaning
externalId The order’s id in its channel (storefront, marketplace, POS). Searchable with q
contact { email, name?, phone? } for a buyer without a customer account, such as guest checkout or a POS receipt. email is searchable with q
fulfillment { method, locationId? }. method is one of ship, pickup, carry_out, digital; locationId is the store to fulfil from or hand over at. See Fulfillment
lines[].sellerId The marketplace seller for a line; otherwise the product’s seller, or first party
lines[].locationId Set by route fulfillment on a split shipment: the store a line ships from. Unset means fulfillment.locationId, or central stock

All of these are on the run context’s order (see Expressions), so a condition can branch on order.model, order.channel or order.fulfillment.method. The order list filters on model and channel and searches externalId and the contact email, and the outbound webhook order summary carries model, channel and externalId.

Customers have a kind: business, consumer or internal.

An order with a contact and no customerId is a guest order. The dashboard’s New order form sends it from the Guest email and Guest name fields, and the Guest checkout demo scenario (where the demo data is loaded) starts one. The order page shows Guest · <email> in place of a customer.

  • Credit check: a guest, or a customer whose kind is not business, has no credit account. The node takes the branch set by noAccount (over_limit by default, ok to let them through) and reports “Guest checkout (no credit account)” or “No credit account (consumer)”.
  • Generate invoice: only an invoice to a business customer that is not yet paid in full is added to their balance, and its summary ends “· on account”. Set onAccount to false to never add it. terms defaults to due_on_receipt.
  • Notify with to: customer falls back to contact.email.
  • Risk score: the offline heuristic adds 15 for a guest (“Guest checkout”) and 30 for an order with neither customer nor contact (“Unknown customer”).
  • The back office customers table shows each customer’s kind; a consumer or internal customer reads “Pays at checkout” in place of payment terms.

New flow on /flows takes a model. With the Template start it copies that model’s default flow from the table above into a new flow of its own, so editing the copy never changes the built-in one (see Building flows). b2c starts from the storefront flow, tpl-storefront-order, and d2c from tpl-omnichannel-order, which routes each order to shipping, store pickup or digital delivery (see Fulfillment); marketplace has its own, tpl-marketplace-order (see Marketplace).