Skip to content
Docs menu

Reference

REST API

Errors

The error shape, every error code and how to retry safely.

Errors use normal HTTP status codes and a JSON body with a stable code you can check in your code, and a message written for people.

json
{
  "error": {
    "code": "validation_error",
    "message": "Some fields are invalid.",
    "issues": [
      {
        "path": "products.0.listPrice",
        "message": "Too small: expected number to be >=0"
      }
    ]
  }
}

issues is only there for validation_error. Each issue’s path points at the field, with list positions counted from 0.

Error codesLink to this section#

StatusCodeWhat happenedWhat to do
400validation_errorA query parameter or body field is missing or invalid.Fix the fields listed in issues.
400invalid_jsonThe body isn’t valid JSON.Send JSON with Content-Type: application/json.
400invalid_requestThe request is valid but not allowed right now, e.g. marking a new order as completed.Read message; don’t retry unchanged.
401unauthorizedMissing, unknown or revoked API key.Check the Authorization: Bearer header and that the key is still live.
401key_owner_removedThe person who made the key has left the workspace.Make a new key from someone who still has access.
403insufficient_scopeA read-only key tried to write.Use a Read & write key.
403read_onlyAPI writes are unavailable on the workspace’s current Free entitlement.The owner manages the plan on the website. Existing keys still read.
403forbiddenThe person who made the key isn’t allowed to do that.Ask a workspace owner, or make a key from someone with that permission.
403workspace_suspendedTradeCatalog has suspended the workspace. The owner has been emailed why.Keys work again when the suspension is lifted.
404not_foundNo such endpoint, or no such product, customer, order or price change in this workspace.Check the id, SKU or account code.
405method_not_allowedThe path exists but not with this method.Use a method from the Allow header.
429rate_limitedMore than 120 requests a minute with this key.Wait for Retry-After seconds (60), then retry.
500internal_errorSomething went wrong on our side.Retry with backoff. If it keeps happening, contact support.

Ids from another workspace always give 404 not_found, never someone else’s data.

RetryingLink to this section#

Retry 429 and 5xx responses with backoff. Don’t retry other 4xx responses: they’ll fail the same way.

All API writes are safe to repeat: PUT matches rows by SKU or account code, and PATCH /orders/{id} fails with invalid_request if the order has already moved on. So a retry after a network timeout won’t duplicate anything.

js
async function api(path, init = {}, attempt = 0) {
  const res = await fetch(`https://tradecatalog.app/api/v1${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}`,
      'Content-Type': 'application/json',
      ...init.headers,
    },
  })
  if ((res.status === 429 || res.status >= 500) && attempt < 5) {
    const wait = Number(res.headers.get('Retry-After')) || 2 ** attempt
    await new Promise((resolve) => setTimeout(resolve, wait * 1000))
    return api(path, init, attempt + 1)
  }
  const body = await res.json()
  if (!res.ok) {
    const error = new Error(`${body.error.code}: ${body.error.message}`)
    error.status = res.status
    error.code = body.error.code
    error.issues = body.error.issues
    throw error
  }
  return body
}

Common messagesLink to this section#

RequestStatus and message
GET /prices with an unknown SKU404 “No product with SKU HX-9999”
Any endpoint with an unknown customer404 “Customer OAK99 not found”
PATCH /orders/{id} new → completed400 “An order that is received can’t be marked completed”
PATCH /orders/{id} to canceled with no note400 “Give a reason for canceling”
PUT /products with the same SKU twice400 validation error “Duplicate SKU hx-8510”