The SDK says an explicit base URL is required
SetNEXT_PUBLIC_CRAVEUP_API_URL to the API origin and rebuild. Do not append /api/v1/storefront; the SDK owns that path.
Browser requests fail CORS
Add the exact storefront origin, including scheme and host, to the API service’sCORS_ALLOWED_ORIGINS. Avoid wildcard origins. Confirm the preflight allows the headers used by the failed request.
Published data returns 404
Public catalog routes deliberately hide unpublished, inactive, or cross-tenant resources as not found. Verify the merchant/location is published and that the location belongs to the requested merchant.Cart request returns 401
The cart capability is absent, invalid, or belongs to another cart/location. Start a new ordering session if the saved capability is stale. Never substitute a private API key.Cart request returns CART_CONFLICT
Another mutation changed the cart revision. Fetch the cart, update the saved revision from ETag, present the current state, and let the shopper retry. Do not silently replay the mutation.
Cart request returns CART_IMMUTABLE
The cart is locked, completed, or expired. Preserve terminal checkout handling when applicable; otherwise clear the stale session and create a new cart.
Customer request returns 401
Confirm Clerk is loaded and signed in,getAuthToken requests the current
crave-customer token from the active session, and getMerchantSlug returns
the merchant selected by the storefront. If the session is expired or revoked,
use Clerk’s recovery or sign-in flow. Never substitute a cached JWT or private
API key.
Checkout appears stuck
Pollcheckout.getOrderSubmissionOutcome with the original attempt ID and bounded backoff.
PROCESSING is neither failure nor success. Render online success only for PAID, preserve
ACCEPTED as pay-at-store authority, and surface ACTION_REQUIRED without manufacturing another order.
Receipt is unavailable
Receipt access requires either the authorized customer JWT or the receipt capability. For email/SMS links, capturereceiptToken from the fragment, remove the fragment immediately, and send the token through the SDK. A missing, wrong, or expired token intentionally looks like not found.
Order submission errors
Check the cart revision and accepted evidence first, then confirm the API service has matching Stripe credentials for the selected environment. The browser receives Stripe client fields only for aCUSTOMER_ACTION_REQUIRED outcome.
STRIPE_DIRECT_CHARGE_CUTOVER_INCOMPLETE means the current direct-charge activation lock rejected
ordinary Stripe payment admission. Show checkout as temporarily unavailable and do not retry or
attempt to bypass the lock; catalog, menu, and cart work can continue.
Useful error fields
StorefrontApiError provides status, code, message, requestId, details, method, and routeTemplate without retaining URLs, bodies, or credentials. Include requestId in support reports.
Share a request with merchant support
Open Business Manager → API activity and search by the responserequestId or the
X-Request-ID you supplied. The page shows the organization-scoped route, status, duration, API-key
scopes, safe error code, and a sanitized request/response summary. Credentials, authentication
data, payment details, and sensitive route bodies are omitted before storage. Exact route, source,
API application, location, and time filters are shareable in the page URL. New events stream while
the first page is open and visibly fall back to polling if the connection drops. Export CSV
downloads a rate-limited, bounded copy of the currently filtered sanitized result set.
Do not paste API keys, JWTs, Stripe client secrets, card data, or complete customer details into a
support ticket. Share the request ID, timestamp, route, location, and visible safe error code.