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.
403insufficient_scopeA read-only key tried to write.Use a Read & write key.
403read_onlyThe workspace’s free trial or subscription has ended, so it’s read-only.The owner subscribes in Settings. Reads still work.
403forbiddenNot allowed for this key.Contact support if you think this is wrong.
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 cancelled with no note400 “Give a reason for cancelling”
PUT /products with the same SKU twice400 validation error “Duplicate SKU hx-8510”