ShopEazydevelopers
Concepts

Errors

The error envelope, request ids, every error code and which ones are safe to retry.

Both APIs answer success and failure the same way.

Envelope

Success is { "data": ... }. Failure is:

{
  "error": {
    "code": "validation_error",
    "message": "A name is required.",
    "requestId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
  }
}
FieldMeaning
codeA stable, machine-readable code. Branch on this
messageWritten for a person. It may be reworded, so do not branch on it. On the Merchant API it is safe to show to the merchant
requestIdThe id of this request. Always present. The same as the X-Request-Id response header
detailsOptional machine-readable context. For example retryAfter on rate_limited, or action and methods on step_up_required

Each code has exactly one HTTP status. The list of codes can grow within v1, so treat a code you do not know as its status class: a 4xx you do not know is your request's fault, a 5xx is ours.

Unexpected failures are 500 internal_error. They never carry a stack trace or any internals.

Request ids

Every response, success or error, carries an X-Request-Id header. Send your own, 8 to 128 letters, digits, ., _ or -, and it is echoed back. Otherwise ShopEazy makes one.

It is the id in ShopEazy's logs and error reports. When you ask for help at shopeazy.co/help, quote it. A browser site on the Storefront API may send and read the header.

Retrying

The clients never retry on their own.

  • A network failure or timeout. Retry. For a write, send the same Idempotency-Key again, so the work happens once. See Idempotency.
  • 429 rate_limited. Wait for Retry-After seconds, then send the same call again. A refused call did nothing and used nothing. See Rate limits.
  • 409 in_flight and 503 idempotency_unavailable. Retry with the same key after a moment. Nothing was processed.
  • 500 internal_error. Retry with backoff. A read is always safe. A write is safe only with an Idempotency-Key.
  • generation_failed, send_failed and lookup_failed. Retry. They are 502 answers where an outside service did not answer.
  • Any other 4xx. Do not send it again unchanged. The request, the credential, the plan or the state has to change first.

The last column of each table says which codes are safe to retry.

Codes

The same catalogue serves both APIs. The API column says which can return a code.

Credentials and access

CodeStatusAPIMeaningRetry
missing_token401BothNo credential was sent. Send a Bearer token (a person’s token on the Merchant API, a store key on the Storefront API).No, fix the cause first
invalid_token401BothThe credential did not verify: unknown, expired or malformed. Sign in again, or check the key.No, fix the cause first
revoked_token401StorefrontThe store key was revoked in the console. Issue a new one.No, fix the cause first
insufficient_scope403StorefrontThe store key does not carry the scope this call needs. Scopes are fixed when a key is issued: reissue it.No, fix the cause first
origin_not_allowed403StorefrontA publishable key was used from a website the store does not allow. The store owner adds it under Allowed websites.No, fix the cause first
step_up_required403MerchantA risky change (new bank details, payment keys, a sign-in email, an admin, closing the account) needs a fresh check by the person. details carries action and the allowed methods. Start one with POST /v1/merchant/step-up, verify it, and send the proof in Step-Up-Proof.After a fresh check
cashier_required403MerchantThe store uses till PINs, so a register, a void or a Scan to pay needs the cashier at the till. Take over with POST /v1/merchant/stores/{storeId}/till/cashier and send the ticket as cashierTicket.No, fix the cause first
forbidden403MerchantThe credential, scope or the person’s role does not allow this call, or only the ShopEazy app may do it.No, fix the cause first
shopper_required401StorefrontThis call needs a signed-in shopper (X-Shopper-Session or X-Shopper-Token) and none was sent.No, fix the cause first
invalid_shopper_token401StorefrontThe shopper’s token or session is not valid or has expired. Sign the shopper in again.No, fix the cause first
order_access_required401StorefrontNeither X-Order-Token nor a shopper credential was sent for this order.No, fix the cause first
email_unverified403BothThe email address has not been verified yet.No, fix the cause first
not_a_member403StorefrontA members-only store, and this shopper is not an active member.No, fix the cause first
verification_required422StorefrontThe application needs a verified selfie and ID document before it is accepted.No, fix the cause first

Store and plan

CodeStatusAPIMeaningRetry
store_not_found404BothThe store does not exist, or (Merchant API) the person cannot reach it. Never a 403, so it does not confirm the id.No, fix the cause first
no_account404MerchantThis login has no business on ShopEazy yet.No, fix the cause first
store_suspended403StorefrontThe store is suspended. Show "shop closed".No, fix the cause first
store_closed403StorefrontThe store has closed. Show "shop closed".No, fix the cause first
store_inactive403StorefrontThe store’s plan is not active. Show "shop closed".No, fix the cause first
api_channel_off403StorefrontThe merchant switched the API channel off for this store.No, fix the cause first
plan_limit403BothThe plan does not include this, or its cap is reached. The message names the plan to move to. Nothing is lost: upgrading restores access.No, fix the cause first
subscription_locked403MerchantThe plan is not active, so the store is read-only. Reads still work; pay or reactivate to write.No, fix the cause first
rate_limited429BothToo many calls, or a daily cap reached. Wait, then retry. details.retryAfter says how long when known.Yes, after the wait

Requests

CodeStatusAPIMeaningRetry
bad_request400MerchantThe request is malformed: a missing, mistyped or out-of-range field. The message names it.No, fix the cause first
invalid_parameter400StorefrontA query parameter is malformed or not one of its allowed values. The message names it.No, fix the cause first
validation_error422BothWell-formed, but it breaks a rule. The message says which, and is safe to show.No, fix the cause first
not_found404BothThe thing asked for does not exist (in this store).No, fix the cause first
in_flight409BothThe same Idempotency-Key is still being processed. Wait a moment and retry with the same key.Yes, same key, after a moment
idempotency_key_reused409BothThis Idempotency-Key was already used for a different request (another method, path or body). A retry must send exactly the same request; a new request needs a new key.No, fix the cause first
idempotency_unavailable503BothThe Idempotency-Key could not be checked, so nothing was processed. Retry with the same key in a moment.Yes, same key, after a moment
internal_error500BothOurs. Never carries internals. Quote the requestId when you ask for help.Reads yes. Writes only with the same Idempotency-Key
not_available501MerchantNot available here (for example photo upload links). The message says what to do instead.No
not_configured503MerchantThis deployment is not set up for it. The message says what is missing.No
unknown_action400MerchantThe action asked for is not one the call offers.No, fix the cause first

Uploads

CodeStatusAPIMeaningRetry
file_too_large413StorefrontThe file is over the size limit.No, fix the cause first
too_large413MerchantThe upload is over the size limit.No, fix the cause first
bad_image415MerchantThe file is not an image of a type we accept.No, fix the cause first
bad_source400MerchantThe photo source could not be read: send a link, base64 data or an upload id.No, fix the cause first

Orders and payments

CodeStatusAPIMeaningRetry
already_paid409StorefrontThe order is already paid.No, fix the cause first
payment_unavailable409StorefrontNo chargeable payment provider is connected, or the provider refused to open a checkout. The message says which.No, fix the cause first
delivery_changed422StorefrontThe delivery choice or price changed since the quote. Quote again and confirm the new delivery.After you quote again
no_payment422StorefrontNo payment was started for this order, so there is nothing to confirm.No, fix the cause first
needs_browser422MerchantThis needs the merchant in a browser or the app (for example entering payment credentials), not a connected AI app.No, fix the cause first
no_card400MerchantNo card on file. Add one first.No, fix the cause first
payment_failed400MerchantThe card did not go through.No, fix the cause first
change_failed400MerchantThe plan, add-on or extra change did not go through. The message says why.No, fix the cause first
out_of_stock409MerchantNot enough stock to do that.No, fix the cause first
provider_error422MerchantA courier, payment provider or Meta refused. Their reason, said plainly.No, fix the cause first

Delivery

CodeStatusAPIMeaningRetry
no_quotes422MerchantNo courier could quote for this order.No, fix the cause first
booking_failed422MerchantThe courier would not take the booking.No, fix the cause first
no_shipment422MerchantNothing has been booked for this order yet.No, fix the cause first
quote_expired422MerchantThe courier quote has expired. Quote again.After you quote again
confirm_different409MerchantThe price changed since the quote. Confirm the new price to go ahead.No, fix the cause first
over_courier_limit403MerchantThe courier price is over what this connection may book without asking the merchant.No, fix the cause first
not_ready422MerchantThe order is not ready for that step.No, fix the cause first
not_tracked422MerchantStock is not tracked for this product.No, fix the cause first

Catalogue and shop

CodeStatusAPIMeaningRetry
kit_not_found404MerchantThe product group does not exist.No, fix the cause first
kit_archived409MerchantThe product group is archived.No, fix the cause first
barcode_not_found404MerchantNo product matched that barcode.No, fix the cause first
code_taken409MerchantThat discount code is already in use.No, fix the cause first
needs_category422MerchantChoose a business category before switching the storefront on.No, fix the cause first
needs_terms422MerchantAccept the current merchant agreement before switching the storefront on.No, fix the cause first
needs_whatsapp422MerchantConnect a WhatsApp number before switching that channel on.No, fix the cause first
facebook_not_connected409MerchantFacebook is not connected for this store.No, fix the cause first
facebook_connect_expired409MerchantThe Facebook connect this call continues is gone: nothing was started, or ten minutes passed. Start again with POST /v1/merchant/stores/{storeId}/social/facebook/connect.No, fix the cause first

Studio and AI

CodeStatusAPIMeaningRetry
insufficient_credits403MerchantNot enough ShopEazy credits. Buy more, or add them in the console.No, fix the cause first
ai_not_configured403MerchantAI is not set up for this store or deployment.No, fix the cause first
over_credit_limit403MerchantThis connection has used its monthly AI credit limit (the merchant sets it in Settings, AI apps). Nothing was spent. The business may still have credits; the merchant can raise the limit.No, fix the cause first
generation_failed502MerchantThe AI provider could not produce a result. Credits are only charged for a result.Yes

WhatsApp

CodeStatusAPIMeaningRetry
whatsapp_not_connected409MerchantNo WhatsApp number is connected.No, fix the cause first
whatsapp_reconnect_required409MerchantThe WhatsApp connection expired. Reconnect it.No, fix the cause first
whatsapp_not_configured503MerchantWhatsApp is not set up on this deployment.No, fix the cause first
service_window_closed409MerchantThe 24 hour customer-service window is closed: only a template message can be sent.No, fix the cause first
whatsapp_rejected502MerchantMeta refused the message. Its reason is in the message.No, fix the cause first

Sign-up and account

CodeStatusAPIMeaningRetry
already_onboarded409MerchantThis person already has a business on ShopEazy.No, fix the cause first
owns_business409MerchantClose the businesses this person owns before closing the account.No, fix the cause first
terms_required400MerchantThe merchant terms and fee schedule must be accepted.No, fix the cause first
bad_code400MerchantThe verification code is wrong or expired.No, fix the cause first
disposable_email422MerchantDisposable email addresses are not accepted.No, fix the cause first
send_failed502MerchantWe could not send the message (for example the verification code). Try again.Yes
lookup_failed502MerchantThe address lookup service did not answer. Try again.Yes

Codes on every operation

These can come back from any operation: missing_token, invalid_token, store_not_found, plan_limit, rate_limited, internal_error, and on the Merchant API subscription_locked and forbidden. A write can also return in_flight, idempotency_key_reused and idempotency_unavailable.

On this page