Skip to main content
Documentation

Guide

Errors

Success is an envelope and so is failure. Switch on `error.code`; the messages are written for people and may change.
Success
{
  "data": "…",
  "meta": {
    "next_cursor": null
  }
}

Failure
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or revoked API key."
  }
}

Switch on error.code rather than parsing error.message: the codes are stable, the messages are written for humans and may change.

StatusCodeMeaning
400invalid_requestThe request body was not valid JSON.
401unauthorizedMissing, invalid, revoked, or expired API key.
403insufficient_scopeA read-only key was used on an endpoint that writes.
403org_suspendedThe account behind the key is suspended.
402plan_lapsedThe account behind the key has no active subscription (trial ended, canceled, or payment failed).
403plan_requiredThe shop's plan does not include this feature.
404not_foundNo such resource in this shop.
409conflictA duplicate already exists, or a per-shop limit is reached. The message names the id or the limit.
422validation_errorA field failed validation. The message names the field.
429rate_limitedOver the per-key rate limit.
500internal_errorOur fault. Safe to retry.
501not_implementedThe endpoint exists but is deliberately not offered. The message says what to do instead.

`404 not_found` on a capability you can see documented here means the feature is not enabled for that account. It is deliberately the same answer an unknown id gets — a distinguishable answer would leak the existence, the name and the price of something the account could not have at any price.

`422 validation_error` names the field, not the constraint. A message that reads "Too big: expected array to have <=6 items" names none of the fourteen arrays a request might hold; ours names the one you got wrong.

Every refusal is in the ledger

A refused call is audited exactly like a successful one — who, which surface, which capability, the outcome and the duration, never the argument values themselves. "What did this key TRY to do" is the more interesting question, and a ledger that only records successes cannot answer it.