> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scrubbe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Scrubbe API Error Codes and Troubleshooting Guide

> Reference for all HTTP error codes returned by the Scrubbe API, with causes, example response payloads, and step-by-step remediation guidance.

When a request cannot be completed, the Scrubbe API returns a non-2xx HTTP status code alongside a JSON body that explains what went wrong. Every error response follows the same structure so you can handle failures consistently regardless of the endpoint.

## Error response format

<ResponseField name="success" type="boolean" required>
  Always `false` for error responses.
</ResponseField>

<ResponseField name="message" type="string" required>
  A human-readable summary of the error.
</ResponseField>

<ResponseField name="errors" type="string[]" required>
  An array of specific validation messages or detail strings. May be empty for server-side errors, but is always present.
</ResponseField>

```json theme={null}
{
  "success": false,
  "message": "Validation failed.",
  "errors": ["email is required", "password must be at least 8 characters"]
}
```

## HTTP status codes

### 400 Bad Request

The request was malformed or failed server-side validation. Inspect the `errors` array for field-level details.

```json theme={null}
{
  "success": false,
  "message": "Validation failed.",
  "errors": [
    "priority must be one of LOW, MEDIUM, HIGH, CRITICAL",
    "summary is required"
  ]
}
```

**Common causes:**

* Missing required fields in the request body
* Invalid enum values (e.g., wrong `priority` or `status`)
* Malformed JSON body
* Invalid date/time format

**Remediation:** Re-read the endpoint's parameter documentation, fix the offending fields, and resubmit.

***

### 401 Unauthorized

No valid credentials were supplied, or the access token has expired.

```json theme={null}
{
  "success": false,
  "message": "Authentication required.",
  "errors": []
}
```

**Common causes:**

* Missing `Authorization` or `X-API-Key` header
* Expired access token
* Invalid or malformed Bearer token format

<Tip>
  Access tokens are short-lived. Call `POST /auth/refresh-token` with your refresh token to obtain a new access token without prompting the user to log in again.
</Tip>

***

### 403 Forbidden

The credentials are valid but the caller lacks permission for the requested resource or action.

```json theme={null}
{
  "success": false,
  "message": "You do not have permission to perform this action.",
  "errors": []
}
```

**Common causes:**

* API key is missing a required scope (e.g., `incidents:write`)
* User role does not permit the operation
* Accessing a resource that belongs to a different workspace

**Remediation:** Check the required scopes listed on the endpoint's documentation page, then rotate your API key with the correct scopes or ask a workspace admin to update your role.

***

### 404 Not Found

The requested resource does not exist or has been deleted.

```json theme={null}
{
  "success": false,
  "message": "Incident not found.",
  "errors": []
}
```

**Common causes:**

* Incorrect or stale resource ID in the URL path
* Resource was deleted by another actor
* Typo in the endpoint URL

**Remediation:** Confirm the resource ID by listing the relevant collection before retrying with the correct value.

***

### 409 Conflict

The request conflicts with the current state of the resource on the server.

```json theme={null}
{
  "success": false,
  "message": "A user with this email address already exists.",
  "errors": []
}
```

**Common causes:**

* Duplicate registration using an email that is already in use
* Attempting to accept an invite that has already been used
* Re-rotating an API key that is already in a pending state

**Remediation:** Fetch the existing resource before creating a duplicate, or handle the `409` response and surface an appropriate message to the user.

***

### 429 Too Many Requests

The caller has exceeded the rate limit for the applicable scope. Wait until the window resets before retrying.

```json theme={null}
{
  "success": false,
  "message": "Too many requests. Please try again later.",
  "errors": []
}
```

| Scope     | Limit        | Window |
| --------- | ------------ | ------ |
| Global    | 200 requests | 15 min |
| Auth      | 10 requests  | 15 min |
| Email OTP | 3 requests   | 1 min  |
| API Key   | 100 requests | 1 min  |

<Warning>
  Do not retry immediately after a `429`. Read the `Retry-After` response header and wait the specified number of seconds. Implement exponential backoff to avoid repeated rejections.
</Warning>

***

### 500 Internal Server Error

An unexpected condition occurred on the server. These errors are not caused by client input.

```json theme={null}
{
  "success": false,
  "message": "An internal error occurred. Please try again.",
  "errors": []
}
```

**Remediation:** Retry the request after a short delay. If the error persists, check the Scrubbe status page or contact support with the request timestamp and any correlation ID from the response headers.

## Handling errors in code

The following examples show a consistent pattern for inspecting error responses across languages.

<CodeGroup>
  ```javascript Node.js theme={null}
  const response = await fetch('https://your-api-domain.com/api/v1/incident-ticket', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    const error = await response.json();
    console.error(`[${response.status}] ${error.message}`, error.errors);
  }
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://your-api-domain.com/api/v1/incident-ticket",
      headers={
          "Content-Type": "application/json",
          "Authorization": f"Bearer {token}"
      },
      json=payload
  )

  if not resp.ok:
      err = resp.json()
      print(f"[{resp.status_code}] {err['message']}", err.get("errors"))
  ```

  ```bash cURL theme={null}
  curl --silent --fail-with-body \
    --request POST \
    --url "https://your-api-domain.com/api/v1/incident-ticket" \
    --header "Content-Type: application/json" \
    --header "Authorization: Bearer $TOKEN" \
    --data '{"summary":"Payment service down","priority":"CRITICAL"}'
  ```
</CodeGroup>
