Skip to content
API Reference

Error Handling

HTTP status codes, error response format, and how to handle failures gracefully.

On this page

Error Handling#

The API uses standard HTTP status codes and returns structured JSON error responses. Every error includes a machine-readable error code and a human-readable message.

Response Format#

Success Responses#

All successful responses include a meta object carrying request metadata.

{
  "data": {
    "id": "abc123",
    "name": "Premium Wireless Headphones",
    "description": "Noise-cancelling over-ear headphones",
    "price": 299.99,
    "currency": "USD",
    "category": "Electronics"
  },
  "meta": { "creditsConsumed": 2 }
}

Error Responses#

{
  "error": "not_found",
  "message": "Product not found",
  "statusCode": 404
}

Error Codes#

StatusErrorMeaning
400bad_requestInvalid request body or parameters — check the validation message
401unauthorizedMissing or invalid API key
402payment_requiredAccount balance exhausted — the request was not performed
403forbiddenAPI key lacks the required scope, or tier too low
404not_foundResource does not exist or belongs to another account
409conflictDuplicate resource — a product or FAQ with the same identifier exists
429too_many_requestsRate limited — wait for the Retry-After period and retry
500internal_errorAn unexpected server error — if persistent, contact support

Handling Errors in Code#

Always check the HTTP status code before parsing the response body:

const response = await fetch(url, {
  headers: { "X-API-Key": process.env.GYDR_API_KEY },
})

if (!response.ok) {
  const error = await response.json()
  console.error(`API error ${error.statusCode}: ${error.message}`)

  if (response.status === 429) {
    const retryAfter = response.headers.get("Retry-After")
    // Wait and retry
  }
  return
}

const { data } = await response.json()

Batch operations: per-row results#

Upsert, bulk delete and reconcile never fail a whole batch because one row is bad. The request returns 200 and each row carries an outcome; failures carry a stable code you can branch on. A failed row is not charged.

CodeMeaning
MISSING_MATCH_KEYThe row omitted the field named by matchBy.
DUPLICATE_IN_BATCHTwo rows in the same request share a key. Both are rejected rather than one silently overwriting the other.
AMBIGUOUS_MATCHMore than one stored row carries this key. Match on externalId or clean up the duplicates.
VALIDATION_FAILEDThe row failed schema or attribute validation. The offending field is named in validationErrors.
NOT_FOUNDDelete only — no live row carries this key.
LIMIT_EXCEEDEDWriting this row would push the knowledge base past its 10,000-item ceiling.
WRITE_CONFLICTThe row collided with a unique field held by a different row — usually an externalId already in use while matching on sku. Nothing was written and nothing was charged for this row.

Unknown fields#

A field name we do not recognise is rejected rather than quietly dropped, so a typo surfaces on your first request instead of looking like data loss weeks later. The offending field name is included in the message string.

{
  "error": "bad_request",
  "message": "Unrecognized field: warehouseCode",
  "statusCode": 400
}

We use cookies to run and improve Gydr.

Read our Cookie Policy