## HTTP Status Codes

| Code | Meaning |
| --- | --- |
| **200** | Successful request. |
| **400** | Request validation failed (missing params, malformed WKT, etc.). |
| **401** | Token is missing, expired, or invalid. |
| **404** | Survey, tile, or mosaic id not found. |
| **422** | Parameters are well-formed but can't be satisfied (e.g., zoom outside range). |
| **429** | Rate limit exceeded. Back off and retry after a delay. |
| **500** | Internal server error. Retry with exponential backoff. |
| **503** | Service temporarily unavailable. Retry with exponential backoff. |

## Error Payload Structure

All `4xx` and `5xx` responses return a consistent JSON body:

```json
{
  "error": "<Error code>",
  "message": "<Error message>",
  "status_code": "<Status code>",
  "x-correlation-id": "<GUID>"
}
```

tip

Persist the `x-correlation-id` when filing support tickets—we can trace requests instantly.

## Common Error Scenarios

### 401 Unauthorized

Your token is expired or missing. Refresh your token and retry:

```python
# Proactively refresh at ~55 minutes to avoid 401s
import time

token_expiry = time.time() + 3600  # 60 min from issuance

def ensure_valid_token():
    global auth_token, token_expiry
    if time.time() > token_expiry - 300:  # 5 min buffer
        auth_token = get_auth_token()
        token_expiry = time.time() + 3600
    return auth_token
```

### 400 Bad Request

Check that:

- WKT polygons are valid and in EPSG:4326
- Required query parameters are present
- Zoom levels are within the 14–21 range

### 422 Unprocessable Entity

The request is well-formed but the server can't satisfy it. Common causes:

- Zoom level outside the supported range
- Survey ID exists but has no coverage for the requested area
