Errors & status codes
Branch on errors[].code, not on the HTTP status. One status covers several causes — a 403 can be a missing scope, an IP restriction, the wrong market or a suspended credential — and only the code tells them apart. message is for people and may change.
| CODE | HTTP | MEANING & NEXT STEP |
|---|---|---|
VALIDATION_UNKNOWN_PARAMETERformerly R002 | 400 | Unknown parameter A query parameter, or body field, the endpoint does not accept. Every unknown query parameter is reported, each with its field. Nothing is silently ignored. |
VALIDATION_MALFORMED_BODYformerly R002 | 400 | Body is not JSON A write body that is not JSON, or is JSON but neither an object nor an array — such as a bare string or number. An empty body, or [], counts as {}. Send an object: an array’s items are read as unknown fields. |
VALIDATION_REQUIRED_FIELDformerly R002 | 422 | Missing field A required parameter or body field is missing — including reference on a partner credential’s write. field names it. |
VALIDATION_INVALID_VALUEformerly R002 | 422 | Invalid value Wrong type, out of range or badly formed — a limit above the endpoint’s maximum, a decimal min_price, a bad LWIN18. field names it. |
VALIDATION_UNSUPPORTED_VALUEformerly R002 | 422 | Value not allowed A value outside the field’s fixed set. The message lists the values it accepts. |
AUTH_INVALID_CREDENTIALSformerly A001 | 401 | Bad credentials A missing or unknown key, a wrong secret, or a bearer token that is unknown, expired, revoked or issued for another resource. Check both headers. |
AUTH_CLIENT_SUSPENDEDformerly A002 | 403 | Credential not usable The credential is suspended or expired, or API access is switched off for the account it belongs to. Contact Cru. |
AUTH_INSUFFICIENT_SCOPEformerly A003 | 403 | Missing scope details.required_scope names the scope, or scopes, needed. A partner asks Cru; a connected app asks the customer to connect it again. |
AUTH_IP_NOT_ALLOWEDformerly A005 | 403 | Address not allowed The calling IP address is not on the credential’s allowlist. |
AUTH_HTTPS_REQUIREDformerly A007 | 403 | HTTPS required The request was plain HTTP. Use an https:// base URL. |
AUTH_STORE_NOT_ALLOWEDformerly A009 | 403 | Wrong market The credential or token may not use the market you called. Compare details.store with details.allowed_stores and change the hostname, not the permissions. |
AUTH_ACCOUNT_ON_HOLDformerly A010 | 403 | Account on hold Connected apps only: the customer’s Cru account is on hold, so none of its apps can act. The customer should contact Cru. |
NOT_FOUNDformerly R003 | 404 | No such resource An unknown path, an unknown warehouse or wine, or webhooks, which are not built yet. |
BID_NOT_FOUNDformerly R003 | 404 | No such bid The code is unknown, malformed, not yours, or the bid has gone. A wine with no bids is not this: its bids are an empty list. |
OFFER_NOT_FOUNDformerly R003 | 404 | No such offer The offer code is unknown, malformed or from another market; or the portfolio_id or listing code is not one of yours, has sold or gone, or is out of date — a repriced line has a new portfolio_id. |
CONFIRMATION_NOT_FOUNDformerly R003 | 404 | No such confirmation No pending instruction with that code is available to this connection: it is unknown, or was staged by another app, customer or market. |
METHOD_NOT_ALLOWEDformerly R004 | 405 | Wrong method The Allow header and details.allowed_methods list the methods the URL accepts. |
API_VERSION_UNSUPPORTEDformerly R005 | 404 | Unsupported version Only /api/v1 exists. |
REQUEST_IN_PROGRESSformerly R006 | 409 | Still running An earlier request with this reference, or a confirmation of this code, is still running. Wait details.retry_after seconds and send the identical request again. |
PRICE_CHANGEDformerly R008 | 409 | Price moved The price is not what the request allows, so nothing was done: a min_price or max_price it misses, checked as soon as the request arrives, or something that moved between the preview and execution. message says what; read the market again before retrying. |
CONFIRMATION_LIMIT_REACHEDformerly R010 | 409 | Too many pending The customer already has 10 instructions waiting for confirmation. Confirm or discard some first. |
CONFIRMATION_EXPIREDformerly R009 | 410 | Confirmation gone The code expired, was discarded, or — when discarding — is no longer pending. Stage the instruction again. |
TRADE_REFUSEDformerly R007 | 422 | Trade refused Cru declined the instruction: an untraded wine, the bidding allowance, too few units, your own bid, an account not set up to sell wine held outside Cru, too many suggested warehouses waiting, a change to BPO stock. message gives the reason in words a customer can read. |
RATE_LIMIT_EXCEEDEDformerly A006 | 429 | Too many requests Reserved. Not raised by the API today, but handle it: back off and retry. |
INTERNAL_ERRORformerly R000 | 500 | Server error Cru’s to fix. Quote meta.request_id when contacting Cru. |
SERVICE_UNAVAILABLEformerly A008 | 503 | Temporarily unavailable Reserved. Not raised by the API today, but handle it: back off and retry. |
What to do when a call fails
8 STEPSYour server
Read errors[0].code, not the HTTP status
The status tells you the category; the code tells you the cause. AUTH_INSUFFICIENT_SCOPE, AUTH_IP_NOT_ALLOWED and AUTH_STORE_NOT_ALLOWED are all 403 and need different fixes.
KEEP
errors[0].code, meta.request_idYour server
401 AUTH_INVALID_CREDENTIALS — the credentials themselves
Both headers are checked together. Confirm CLIENT-KEY and CLIENT-SECRET are the pair Cru issued, and that neither picked up whitespace or a line break when copied. For a connected app, refresh the token.
Your server
403 — permitted, but not for this
AUTH_INSUFFICIENT_SCOPE names what is missing in details.required_scope. AUTH_STORE_NOT_ALLOWED means the hostname is a market you may not use — compare details.store with details.allowed_stores. AUTH_IP_NOT_ALLOWED is the allowlist; AUTH_CLIENT_SUSPENDED is the credential itself.
Your server
400 and 422 VALIDATION_* — the request
An unknown parameter is refused rather than ignored, and field names the culprit. Fix it and send again: a request refused on validation has not used up its reference.
Your server
404 BID_NOT_FOUND, OFFER_NOT_FOUND — gone, or not yours
Missing, expired, filled and malformed all give the same answer. Treat it as “no longer available” and go back to the book or your list.
Your server
422 TRADE_REFUSED and 409 PRICE_CHANGED — Cru declined
errors[0].message says why, in words a customer can read. Nothing happened. Read the market again, and send a new request with a new reference.
Your server
409 REQUEST_IN_PROGRESS — wait, then repeat exactly
The first request with this reference is still running. Wait details.retry_after seconds and send the identical request; never a new one.
Your server
500 INTERNAL_ERROR — Cru’s to fix
Quote meta.request_id, which is also the X-Request-Id header. Retry a write only with the same reference.
KEEP
meta.request_id
When Cru declines a trade
TRADE_REFUSED and PRICE_CHANGED are not mistakes in your request: Cru looked at the instruction and would not carry it out, and nothing happened. errors[0].message says why in words you can show a customer — the bidding allowance, a wine Cru does not trade, a bid that has moved. A partner credential’s reference may or may not be spent, depending on whether the refusal came before the trade ran or during it, so send a new request with a new reference once you have read the market again. What a repeat gets back →
Numbered codes
Earlier drafts of this reference used numbered codes such as A003 and R002 in an internal_error_code field. Responses no longer carry them: they survive only as the key Cru’s own logs are written under, which the table shows beside each code that has one.
Include the request ID, endpoint, HTTP status and error code. Do not include your client secret, an access token or a confirmation code.