Order Validation Functions
Anorder_validation function runs at order placement time
(order placement). 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 does not run at cart verification. It only fires on the order-place endpoint, so customers see the error after pressing “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
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.
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. Whentarget='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
Validate early when possible
Validate early when possible
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.
Write actionable messages
Write actionable messages
“Reduce quantity from 15 to 10” beats “Quantity invalid”. Tell
the customer exactly what to change.
Use `target` + `lineId`
Use `target` + `lineId`
Themes that support per-line error rendering rely on these
fields. Plain string messages still work, but lose the
inline-highlight UX.
Handle missing customer
Handle missing customer
Guest checkouts arrive with
customer === undefined. Don’t
crash — return { errors: [] } if your rule doesn’t apply.Keep functions fast
Keep functions fast
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
- Cart Transform Functions — modify or remove lines instead of blocking the order.
- Payment Customization Functions — hide a payment method rather than reject the whole order.
- Discount Functions — apply or withhold a discount based on cart state.