Error response format
All error responses follow this structure:| Field | Type | Description |
|---|---|---|
error | string | Machine-readable error code |
message | string | Human-readable description |
statusCode | number | HTTP status code |
Handling errors with the SDK
The SDK throws anApiError for any non-2xx response:
HTTP status codes
400 — Bad Request
The request body or query parameters are invalid.| Error | Message | Resolution |
|---|---|---|
VALIDATION_ERROR | Field-specific validation message | Check the message for which field failed. Ensure required fields are present and types match. |
INVALID_PRODUCT | Product ID not found or unavailable | Verify the productId exists and is available in the current menu. |
INVALID_MODIFIER_SELECTION | Modifier selection violates group rules | Check the modifier group’s min/max rules. Ensure the number of selected options is within range. |
CART_LOCKED | Cart is locked for payment processing | The cart cannot be modified while payment is in progress. Wait for completion or create a new session. |
INVALID_DISCOUNT_CODE | Discount code is invalid or expired | Show the user that the promo code could not be applied. Verify the code and try again. |
MINIMUM_ORDER_NOT_MET | Order does not meet the minimum amount | Display the minimum order requirement and prompt the user to add more items. |
401 — Unauthorized
Authentication failed.| Error | Message | Resolution |
|---|---|---|
MISSING_API_KEY | No API key provided | Include the X-API-Key header in your request. |
INVALID_API_KEY | API key is invalid or revoked | Generate a new API key from the Dashboard. |
INVALID_AUTH_TOKEN | Customer auth token is invalid or expired | Refresh the customer’s JWT or redirect to login. |
403 — Forbidden
The API key doesn’t have permission for this operation.| Error | Message | Resolution |
|---|---|---|
LOCATION_MISMATCH | API key is not authorized for this location | Use the API key scoped to the target location. Each key is location-specific. |
OPERATION_NOT_ALLOWED | This operation is not permitted | Check that the endpoint is available for storefront API keys (vs. admin keys). |
404 — Not Found
The requested resource doesn’t exist.| Error | Message | Resolution |
|---|---|---|
LOCATION_NOT_FOUND | Location ID does not exist | Verify the locationId parameter. Check the Dashboard for valid IDs. |
CART_NOT_FOUND | Cart ID does not exist or has expired | Create a new ordering session to get a fresh cart. Carts expire after inactivity. |
PRODUCT_NOT_FOUND | Product not available in current menu | The product may be time-restricted. Check the active menu for the current time. |
MERCHANT_NOT_FOUND | Merchant slug does not match any account | Verify the slug used in merchant.getBySlug(). |
409 — Conflict
The request conflicts with the current state.| Error | Message | Resolution |
|---|---|---|
DISCOUNT_ALREADY_APPLIED | A discount is already applied to this cart | Remove the existing discount before applying a new one. |
SESSION_ALREADY_EXISTS | An ordering session already exists for this cart | Reuse the existing session instead of creating a new one. |
422 — Unprocessable Entity
The request was well-formed but the data cannot be processed.| Error | Message | Resolution |
|---|---|---|
LOCATION_CLOSED | Location is not accepting orders at this time | Check the order times endpoint and display operating hours to the user. |
DELIVERY_OUT_OF_RANGE | Delivery address is outside the delivery zone | Show the user that their address is too far. Use locations.getDistance() to check distance before setting delivery. |
FULFILLMENT_NOT_AVAILABLE | The selected fulfillment method is not enabled | Check location.methodsStatus and only show available methods. |
INVALID_ORDER_TIME | The requested order time is not available | Fetch fresh order times and let the user pick a valid slot. |
429 — Too Many Requests
You’ve exceeded the rate limit.| Error | Message | Resolution |
|---|---|---|
RATE_LIMIT_EXCEEDED | Too many requests | Back off and retry. Check the Retry-After or X-RateLimit-Reset header for when to retry. |
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
500 — Internal Server Error
An unexpected error on the Crave server.| Error | Message | Resolution |
|---|---|---|
INTERNAL_ERROR | An unexpected error occurred | Retry with exponential backoff. If the error persists, contact support. |
502 / 503 — Service Unavailable
The API or an upstream service is temporarily unavailable.| Error | Message | Resolution |
|---|---|---|
SERVICE_UNAVAILABLE | The service is temporarily unavailable | Retry after a few seconds. Check the Crave status page for outages. |