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

# Error Handling

> Handle API errors gracefully

## Error Response Format

All API errors follow a consistent format:

```json theme={null}
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message in English",
    "message_es": "Mensaje legible en español",
    "details": { },
    "requestId": "req_abc123xyz"
  }
}
```

## Error Categories

### Validation Errors (400)

Returned when request data fails validation.

```json theme={null}
{
  "success": false,
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Request validation failed",
    "details": {
      "errors": [
        {
          "field": "receiver.nationalId",
          "message": "National ID is required for Ecuador shipments"
        },
        {
          "field": "parcelDetails.weightLbs",
          "message": "Weight must be positive"
        }
      ]
    }
  }
}
```

**How to handle:**

1. Parse the `details.errors` array
2. Display field-specific errors to the user
3. Do NOT retry automatically

### Authentication Errors (401)

Returned when API key is invalid or missing.

```json theme={null}
{
  "success": false,
  "error": {
    "code": "AUTH_INVALID_API_KEY",
    "message": "The provided API key is invalid or has been revoked"
  }
}
```

**How to handle:**

1. Check that API key is configured correctly
2. Verify the key hasn't been revoked in dashboard
3. Contact support if issue persists

### Rate Limit Errors (429)

Returned when you exceed request limits.

```json theme={null}
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please wait before retrying.",
    "retryAfter": 30
  }
}
```

**How to handle:**

1. Wait for `retryAfter` seconds
2. Implement exponential backoff
3. Consider request batching

### Conflict Errors (409)

Returned when a resource conflict occurs.

```json theme={null}
{
  "success": false,
  "error": {
    "code": "PARCEL_DUPLICATE_TRACKING",
    "message": "A parcel with this tracking number already exists"
  }
}
```

**How to handle:**

1. For duplicates, use the existing resource
2. For locked resources, wait and retry
3. Check idempotency key for accidental duplicates

### Server Errors (500)

Returned when an unexpected error occurs.

```json theme={null}
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An unexpected error occurred. Please try again.",
    "requestId": "req_abc123xyz"
  }
}
```

**How to handle:**

1. Retry with exponential backoff (up to 3 times)
2. If persists, contact support with `requestId`
3. Log the error for debugging

## Error Code Reference

### Order Errors

| Code                        | HTTP | Description                      |
| --------------------------- | ---- | -------------------------------- |
| `PARCEL_NOT_FOUND`          | 404  | Tracking number doesn't exist    |
| `PARCEL_DUPLICATE_TRACKING` | 409  | Tracking number already in use   |
| `PARCEL_ALREADY_VOIDED`     | 409  | Order has already been cancelled |
| `PARCEL_IN_TRANSIT`         | 409  | Cannot modify order in transit   |
| `PARCEL_DELIVERED`          | 409  | Cannot modify delivered order    |

### Manifest Errors

| Code                         | HTTP | Description                |
| ---------------------------- | ---- | -------------------------- |
| `MANIFEST_LOCKED`            | 409  | Manifest already submitted |
| `MANIFEST_AWB_DUPLICATE`     | 409  | AWB number already exists  |
| `MANIFEST_VALIDATION_FAILED` | 400  | Country validation failed  |

### Validation Errors

| Code                     | HTTP | Description                                   |
| ------------------------ | ---- | --------------------------------------------- |
| `VALIDATION_FAILED`      | 400  | One or more fields failed validation          |
| `VALIDATION_NATIONAL_ID` | 400  | Invalid national ID format                    |
| `VALIDATION_PHONE`       | 400  | Invalid phone number                          |
| `VALIDATION_ADDRESS`     | 400  | Invalid address format                        |
| `VALIDATION_CHECKSUM`    | 400  | Product checksum doesn't match declared value |

### Auth Errors

| Code                       | HTTP | Description                         |
| -------------------------- | ---- | ----------------------------------- |
| `AUTH_MISSING_API_KEY`     | 401  | No API key provided                 |
| `AUTH_INVALID_API_KEY`     | 401  | API key is invalid or revoked       |
| `AUTH_COUNTRY_NOT_ALLOWED` | 403  | Key not authorized for this country |
| `AUTH_IP_NOT_ALLOWED`      | 403  | Request IP not in whitelist         |

## Retry Strategy

Implement exponential backoff for retryable errors:

```javascript theme={null}
async function apiCallWithRetry(fn, maxRetries = 3) {
  let lastError;
  
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;
      
      // Don't retry validation or auth errors
      if (error.status === 400 || error.status === 401) {
        throw error;
      }
      
      // Don't retry conflict errors (409) except for rate limits
      if (error.status === 409 && error.code !== 'RATE_LIMIT_EXCEEDED') {
        throw error;
      }
      
      // Calculate delay with exponential backoff
      const delay = error.retryAfter 
        ? error.retryAfter * 1000 
        : Math.min(1000 * Math.pow(2, attempt), 30000);
      
      console.log(`Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
      await sleep(delay);
    }
  }
  
  throw lastError;
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
```

## Localization

Error messages are provided in both English (`message`) and Spanish (`message_es`).

To request errors in Spanish, add the `Accept-Language` header:

```bash theme={null}
curl -H "Accept-Language: es" ...
```

<Tip>
  Always save the `requestId` from error responses. Support can use this to investigate issues quickly.
</Tip>
