Skip to main content
Raptor Comply returns standard HTTP status codes with JSON error bodies. Learn how to handle 4xx and 5xx responses and retry safely in your integration.
The Raptor Comply API uses standard HTTP status codes to signal success and failure. Every error response includes a JSON body with two fields: error, a short code that identifies the error class, and message, a human-readable description of what went wrong. Building reliable integrations means checking these responses on every request and handling them appropriately.

Error response format

All error responses follow the same structure:
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}
  • error - a short string identifying the error type. Use this for programmatic branching.
  • message - a plain-English description. Include this in logs and alerts to make debugging faster.

Common error codes

Statuserror valueCauseResolution
401UnauthorizedMissing or invalid X-API-KeyCheck that your API key is correct, active, and not expired
403ForbiddenKey lacks permission for this operationContact your organization admin to review key permissions
404Not FoundResource ID does not existVerify the ID is correct and belongs to your organization
422Unprocessable EntityInvalid request bodyCheck that all required fields are present and values match expected types
429Too Many RequestsRate limit exceededBack off and retry after a delay (see retry guidance below)
500Internal Server ErrorUnexpected server-side errorRetry with exponential backoff; contact support if the error persists

Retry strategy

Not all errors are worth retrying. Follow this rule:
  • Retryable: 429 Too Many Requests and 5xx server errors. These are transient conditions - the request itself is valid, and retrying after a delay will often succeed.
  • Not retryable: 4xx errors (except 429). These indicate a problem with the request - a missing header, a wrong ID, a malformed body. Retrying without fixing the underlying issue will not help.
For retryable errors, use exponential backoff with jitter to avoid hammering the API and making rate-limit situations worse. A good starting point: wait 1 second before the first retry, double the wait on each subsequent attempt, add random jitter, and give up after 3–5 attempts. Here is a Node.js helper that wraps any API call with that pattern:
async function fetchWithRetry(url, options, maxRetries = 4) {
  const RETRYABLE_STATUSES = new Set([429, 500, 502, 503, 504]);
  let attempt = 0;

  while (attempt <= maxRetries) {
    const response = await fetch(url, options);

    if (response.ok) {
      return response;
    }

    const shouldRetry = RETRYABLE_STATUSES.has(response.status);

    if (!shouldRetry || attempt === maxRetries) {
      // Surface the error body for logging before throwing
      const errorBody = await response.json();
      const err = new Error(`${errorBody.error}: ${errorBody.message}`);
      err.status = response.status;
      err.body = errorBody;
      throw err;
    }

    // Exponential backoff with jitter: base * 2^attempt + random ms
    const baseDelay = 1000;
    const jitter = Math.random() * 500;
    const delay = baseDelay * Math.pow(2, attempt) + jitter;

    console.warn(
      `Request failed with ${response.status}. Retrying in ${Math.round(delay)}ms ` +
      `(attempt ${attempt + 1} of ${maxRetries})...`
    );

    await new Promise((resolve) => setTimeout(resolve, delay));
    attempt++;
  }
}

// Usage
const response = await fetchWithRetry(
  "https://api.raptormaps.com/cyber-assets",
  {
    headers: {
      "X-API-Key": process.env.RAPTOR_COMPLY_API_KEY,
    },
  }
);
const assets = await response.json();

Checking response status

Always check the response status before consuming the body. Here are patterns in Node.js and Python: Node.js - using fetch
const response = await fetch("https://api.raptormaps.com/cyber-assets", {
  headers: {
    "X-API-Key": process.env.RAPTOR_COMPLY_API_KEY,
  },
});

if (!response.ok) {
  // response.ok is true for 2xx status codes only
  const errorBody = await response.json();
  console.error("API error:", errorBody); // log the full body
  throw new Error(`${errorBody.error}: ${errorBody.message}`);
}

const assets = await response.json();
Python - using requests
import os
import requests

response = requests.get(
    "https://api.raptormaps.com/cyber-assets",
    headers={
        "X-API-Key": os.environ["RAPTOR_COMPLY_API_KEY"],
    },
)

# raise_for_status() raises requests.HTTPError for 4xx and 5xx responses
try:
    response.raise_for_status()
except requests.HTTPError as e:
    error_body = response.json()
    print(f"API error [{response.status_code}]: {error_body}")
    raise

assets = response.json()
response.raise_for_status() throws a requests.HTTPError for any 4xx or 5xx response, and does nothing for successful 2xx responses. Catch the exception and inspect response.json() to get the error and message fields.

Getting help

If you receive persistent 500 errors or encounter unexpected behavior not explained by the error codes above, contact the Raptor Comply support team at support@raptormaps.com. Include the full error response body, the endpoint you called, and the approximate time of the request to help the team diagnose the issue quickly.
Always log the full error response body - not just the HTTP status code. The error and message fields are what tell you (and your on-call team) what actually went wrong. A log line that says "API call failed: 401" is much less useful than one that says "API call failed: Unauthorized - API key has expired".