Skip to main content

Order Validation Functions

An order_validation function runs at both cart verification and order placement. It fires during cart verification (with step: 'cart') so your rules can surface in the cart/checkout preview, and again as the final gate at order placement (with step: 'review'). Return one or more errors and the order is rejected with a 400 Bad Request. Return nothing and the order proceeds. Use it for purchase limits, geographic blocks, age/compliance gates, required-accessory rules, or anything that needs to block the order itself — not just hide a payment method or warn the customer in the cart.

How It Works

This function runs at cart verification (step: 'cart') and at the order-place endpoint (step: 'review'), so your rules can be reflected in the cart/checkout preview as well as enforced as the final gate when the customer presses “Place order”.

Function Manifest

Input Schema

The input is intentionally minimal. There is no paymentMethod, no shop, no tags/productType/vendor on items, and customer carries only id and email. If you need richer data, fetch it from your own backend keyed on the customer/order ids you receive here.

Output Schema

The backend treats errors.length > 0 as invalid. There is no valid: true|false boolean — an empty errors array (or an absent field) means the order is allowed. When multiple errors are returned, the first message becomes the HTTP 400 headline. The full list is attached to the response as data.errors so the frontend can render per-line/per-field callouts.
The platform automatically stamps each error with the originating appId so the frontend can attribute blame.

Examples

Per-line quantity cap

Geographic block

Guest checkout limit

Required-accessory check

How errors render in the UI

The checkout converts the 400 into an inline error banner above the place-order button. When target='line' and lineId matches a cart line, the checkout can additionally highlight that specific line (subject to theme support).

Multiple apps

All installed validation functions run in install order. Errors from every function are concatenated, and the order is blocked if any function returns at least one error.

Best Practices

A cart-transform or storefront-side check that prevents the bad state at all is a better customer experience than a 400 after they pressed “Place order”. Use order_validation as the server-side gate, not the primary signal.
“Reduce quantity from 15 to 10” beats “Quantity invalid”. Tell the customer exactly what to change.
Themes that support per-line error rendering rely on these fields. Plain string messages still work, but lose the inline-highlight UX.
Guest checkouts arrive with customer === undefined. Don’t crash — return { errors: [] } if your rule doesn’t apply.
The order-place flow blocks on this dispatch. A slow validator means a slow checkout. If you need to call an external API, cache aggressively and short-circuit on identical inputs.

See Also