01.software Docs

Commerce Operations

Prepare catalog, customer, order, fulfillment, shipping, and support ownership.

Commerce Operations

Use this page when the workspace will sell products, manage customers, or support orders after launch.

Commerce Setup

Prepare catalog

Create real products, options, categories, and images before inviting teams to operate the workspace.

Assign order ownership

Name who handles order review, fulfillment, returns, refunds, and customer support.

Confirm shipping and discounts

Review shipping policy ownership and decide who can create or retire discounts.

Connect support habits

Make sure customer account, order, and return questions have a clear support path.

Operating Ownership

WorkflowOwnerBefore launch
catalogmerchandising ownerproducts and sellable options exist
ordersoperations ownerorder review and fulfillment path is assigned
shippinglogistics ownerdefault shipping policy is confirmed
discountscommerce ownerpromotion approval is clear
customerssupport owneraccount recovery and service expectations are assigned

Shipping and Non-Shipping Products

Physical variants should keep requiresShipping enabled so paid orders create carrier fulfillment work. Digital goods, remote classes, services, and other non-shipping variants can disable shipping; those lines do not require a shipping address or shipping fee, do not appear in carrier file export/import, and are skipped by shipment item selection.

Storefront cart responses include each line's shipping requirement so checkout can stay contextual. Non-shipping-only carts skip the shipping address step and shipping summary line; mixed carts still collect shipping for the physical lines.

Mixed orders keep the two paths separate: ship the physical lines through fulfillment orders and carrier tracking, then complete any non-shipping access or service lines through the manual completion flow. Refund and return handling should distinguish physical delivery from digital/service access so shipping refunds and return shipping fees are only used when outbound or return shipping actually applies.

Return Requests

In the Console Admin Panel, create return requests from an eligible delivered or confirmed order. Operators select the return lines explicitly, review ordered, already-returned, and remaining quantities, enter per-line restocking fees and a return shipping fee, then submit the net refund amount shown by the breakdown.

The return request records the selected line quantities, returnShippingFee, restockingFee, initialShippingRefundAmount, and refundAmount. initialShippingRefundAmount is the initial outbound shipping refunded to the customer. returnShippingFee is a return-shipping deduction charged to the customer. The net refund is:

refundAmount = sum(lineRefund) + initialShippingRefundAmount - sum(restockingFee) - returnShippingFee

The initial shipping refund suggestion uses the order-time return shipping refund policy snapshot. Across non-rejected returns, the cumulative initial shipping refund is capped by the order shipping amount. Legacy orders without that snapshot use the order shipping amount as a manual cap and require an audit note for any positive initial shipping refund.

Manual Orders (Draft Orders)

Sales that do not go through storefront checkout — phone orders, B2B or manual sales, support-assisted reorders, and quote-before-confirm — are handled as draft orders. In the Console an operator builds a draft with line items, a customer or customer snapshot, a shipping address, a discount code, a shipping fee, and operator/customer notes, and can freely edit or discard it until it is finalized.

A draft reserves no inventory and creates no order ledger rows (orders, transactions, inventory reservations, fulfillment) before finalization. POST /api/draft-orders/:id/calculate returns a server-derived totals preview (subtotal, discount, shipping, total) with no side effects and surfaces unavailable or out-of-stock variants and an invalid discount code before finalize.

POST /api/draft-orders/:id/finalize converts the draft into a real order. Pricing, discounts, tenant checks, idempotency, and lifecycle defaults reuse the same server-derived order-creation path as storefront orders, and the resulting order records source = manual. A zero-amount draft follows the existing free-order auto-paid path; otherwise a manual pending order is created for follow-up. If the customer email is missing or invalid, finalize is rejected with a clear error and the draft stays editable.

The v1 scope covers server-priced catalog items plus an existing discount code. There is no manual or custom line pricing, currency is fixed to KRW, and finalize does not send payment or invoice links (a later phase). Draft status moves draftfinalized (linked to the created order) or discarded; a finalized or discarded draft can no longer be edited.

Launch Checklist

  • ecommerce is effective on the current plan
  • at least one product is ready for sale
  • shipping and discount ownership are clear
  • customer support owns account and order questions
  • payment and webhook responsibilities are assigned before customer launch

Keep commerce launch small. A complete first product and order support path is better than a broad catalog with unclear ownership.

Commerce helpers (SDK)

The @01.software/sdk exposes shaped commerce helpers as the recommended path for common consumer flows. Helpers fold the underlying Payload queries, access policy, and response shaping into a single call.

Product media is ordered. The first product image is treated as the featured image for listing cards and the default product detail state.

HelperUse case
createServerClient().commerce.product.detail({ slug | id, market })Trusted server product detail: returns { found: true, product } with variants, options, brand, categories, tags, images, videos, Shopify-shaped Product fields, and operational inventory fields. Requires server credentials. Pass market to resolve variant prices into that market; each priced variant includes resolvedPrice with amount, compare-at price, currency, market id, and source (fixed or computed). Detail allows products with status: 'published' or status: 'unlisted'; 404s return { found: false, reason } for missing, unpublished, or feature disabled.
commerce.product.detail({ slug | id, market }) / commerce.product.detailCatalog({ slug | id, market }) / commerce.product.listingPage({ market }) / listingGroupsCatalog({ productIds, market })Publishable storefront reads: public-safe detail/card data without raw stock quantities. Pass market for market-resolved product ranges, group listings, and variant resolvedPrice; market listing pages reject base-currency price filters/sorts because those ranges no longer match the resolved market price. Only status: 'published' products appear in listings; use direct detail for status: 'unlisted' products.
commerce.product.stockCheck({ items })Pre-cart validation: point-in-time stock availability for variants.
commerce.cart.*Cart lifecycle: create / get / addItem / updateItem / removeItem / updateDiscountCodes / clear. updateDiscountCodes({ discountCodes }) replaces the full cart discount-code list; applyDiscount and removeDiscount remain compatibility helpers. create({ market }) or the first addItem({ market }) locks the cart to that market; later market mismatches fail closed and line prices are recalculated from the market-aware catalog price.
commerce.discounts.validate({ code, orderAmount, currency?, market?, items? })Pre-checkout discount validation. Pass currency or market whenever validating discounts that depend on absolute money amounts; fixed amounts, min-order thresholds, max caps, and fixed/tiered thresholds fail closed without an explicit matching currency or market context.
commerce.shipping.calculate({ postalCode, orderAmount })Pre-checkout shipping calculation.
commerce.orders.checkoutStart checkout from a cart and return a public checkout/order-compatible response (Client: customer JWT; ServerClient: API key). With checkout/order separation enabled, the response is backed by a Checkout until payment confirmation creates the Order; use checkoutToken as the stable payment and redirect key for new flows.

For React, createQueryHooks(client).useProductDetailBySlug(slug) and matching hooks expose the public-safe catalog detail shape with React Query caching and automatic invalidation on mutations to related collections.

The raw client.collections.from() query builder remains available as the escape hatch for cases the helpers do not cover (bulk reads, custom filter combinations, fields not in the helper response shape). See the SDK README's "Advanced: direct Payload queries" section.

Next Actions

On this page