Feed APIFeed API

REST API / Errors

Error handling

All errors use a consistent JSON envelope with a machine-readable code, a human-readable message, and the HTTP status. Validation errors include a details array with per-field messages.

Error shape

Standard error
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Product not found in your catalogue",
    "status": 404
  }
}
Validation error
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "status": 400,
    "details": [
      {
        "field": "ship_name",
        "message": "required"
      },
      {
        "field": "items[0].quantity",
        "message": "must be at least 1"
      }
    ]
  }
}

Error codes

MISSING_API_KEY401No x-api-key header was sent.
INVALID_API_KEY401Key format is wrong or does not exist.
KEY_REVOKED403Key has been manually revoked.
KEY_EXPIRED403Key has passed its expiry date.
ACCOUNT_INACTIVE403Reseller account is pending, suspended, or rejected.
INSUFFICIENT_SCOPE403Key is valid but does not carry the access right this endpoint needs. Enable it under Access rights on the API keys page.
RATE_LIMIT_EXCEEDED429More than 60 requests in one minute.
VALIDATION_ERROR400Request body or query parameters failed validation.
PAYMENT_REQUIRED402No payment card is on file. Add one under Settings → Payment before placing orders. Only POST /v1/orders returns this.
NOT_FOUND404Resource does not exist or is not in your catalogue.
CONFLICT409Action conflicts with current resource state.
FORBIDDEN403You do not have permission.
INTERNAL_ERROR500An unexpected server error occurred.
INTERNAL_ERROR503Rate limiting is temporarily unavailable, so the request was refused rather than served unmetered. Retryable — a Retry-After header says when.

Handling errors in code

JavaScript
const res = await fetch("https://api.feedapi.co.uk/v1/products", {
  headers: { "x-api-key": apiKey },
});

if (!res.ok) {
  const { error } = await res.json();

  switch (error.code) {
    case "RATE_LIMIT_EXCEEDED":
      const retryAfter = res.headers.get("Retry-After");
      await sleep(Number(retryAfter) * 1000);
      break;
    case "INVALID_API_KEY":
    case "KEY_REVOKED":
      // Redirect to key management
      break;
    case "VALIDATION_ERROR":
      error.details?.forEach(d => showFieldError(d.field, d.message));
      break;
    default:
      console.error(error.message);
  }
}