Appearance
Cart → COD checkout
Place a real order: create a cart, add lines, re-price it, then check out on the existing COD / credit-terms rails (the only checkout path in v1 - there are no online card payments yet). Orders placed through the Storefront API are tagged channel=ECOMMERCE, server-side - you never set the channel yourself.
What you need
- A secret key (
hk_test_sec_…) - this path is customer-scoped, so a publishable key is rejected403. - A shopper token for the signed-in customer (
X-Storefront-Shopper-Token). The key authenticates your integration; the token authenticates the customer. See Authentication & keys.
Secret keys are server-side only
hk_*_sec_… keys unlock checkout, customer reads, and webhooks. Never ship one to a browser. Run every step on this page from your backend.
1. Create a cart
A cart is scoped to the shopper carried by the token - you never pass a customer_id.
curl -s -X POST "https://api.harmon.example/v1/carts" \
-H "Authorization: Bearer hk_test_sec_your_key_here" \
-H "X-Storefront-Shopper-Token: <shopper jwt>"2. Add lines
Add each item by sku + quantity. (Products sold in alternate units can pass order_uom / order_quantity; everything settles in the product's base stock unit.)
curl -s -X POST "https://api.harmon.example/v1/carts/$CART_ID/lines" \
-H "Authorization: Bearer hk_test_sec_your_key_here" \
-H "X-Storefront-Shopper-Token: <shopper jwt>" \
-H "Content-Type: application/json" \
-d '{"sku":"SKU-123","quantity":2}'3. Re-price the cart
Pricing is computed server-side from the customer's contract prices plus tax/GCT. Always re-price before showing a total or checking out.
curl -s -X POST "https://api.harmon.example/v1/carts/$CART_ID/price" \
-H "Authorization: Bearer hk_test_sec_your_key_here" \
-H "X-Storefront-Shopper-Token: <shopper jwt>"4. Check out
Checkout converts the cart to an order on the COD / credit-terms rails. If the order would exceed the customer's credit limit, the API returns a structuredover_credit_limit state (with the shortfall) - handle it, don't treat it as a generic error.
curl -s -X POST "https://api.harmon.example/v1/checkout" \
-H "Authorization: Bearer hk_test_sec_your_key_here" \
-H "X-Storefront-Shopper-Token: <shopper jwt>" \
-H "Content-Type: application/json" \
-d '{"cart_id":"'$CART_ID'","notes":"Leave at front desk"}'Track the resulting order with GET /v1/orders/{order_id}, and reconcile against GET /v1/invoices once an invoice is issued.
Next steps
- Verify a webhook - react to
order.confirmedandinvoice.issuedevents instead of polling. - Customer-priced catalog with a shopper token - show the same contract pricing while the shopper browses.
- Errors - the status table and the
over_credit_limitstate.
In the API Reference
Open these operations in the interactive reference (with a Try it console):
POST /v1/carts- create a cartPOST /v1/carts/{cart_id}/lines- add a linePOST /v1/carts/{cart_id}/price- re-pricePOST /v1/checkout- place the order