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

# Error Handling

> Standard error responses and how to handle them.

# Error Handling

The Power Signals API uses standard HTTP status codes and returns structured error responses.

## Error Response Format

All errors follow a consistent structure:

```json theme={null}
{
  "error": "error_code",
  "detail": "Human-readable description of what went wrong."
}
```

## Status Codes

| Code  | Meaning               | When                                                               |
| ----- | --------------------- | ------------------------------------------------------------------ |
| `200` | Success               | Request processed successfully                                     |
| `400` | Bad Request           | Invalid parameters (missing/malformed dates, unsupported interval) |
| `401` | Unauthorized          | Missing or invalid API key                                         |
| `403` | Forbidden             | Key doesn't have access to this resource                           |
| `404` | Not Found             | Endpoint doesn't exist                                             |
| `429` | Too Many Requests     | Rate limit exceeded                                                |
| `500` | Internal Server Error | Something went wrong on our side                                   |

## Common Errors

### Missing Parameters

```json theme={null}
{
  "error": "missing_params",
  "detail": "start and end datetime are required ISO-8601"
}
```

**Fix:** Include both `start` and `end` query parameters in ISO-8601 format.

### Invalid DateTime

```json theme={null}
{
  "error": "invalid_datetime",
  "detail": "start/end datetimes must be ISO-8601 datetimes"
}
```

**Fix:** Use a valid ISO-8601 format like `2026-01-01T00:00:00Z` or `2026-01-01T00:00:00+02:00`.

### Unsupported Interval

```json theme={null}
{
  "error": "unsupported_interval",
  "detail": "interval=5m not supported. Supported: ['1d', '1h']"
}
```

**Fix:** Use one of the supported intervals listed in the error detail.

### Bad Time Range

```json theme={null}
{
  "error": "bad_request",
  "detail": "start datetime must be < end datetime"
}
```

**Fix:** Ensure your `start` parameter is before your `end` parameter.

### Authentication Failure

```json theme={null}
{
  "detail": "Authentication credentials were not provided."
}
```

**Fix:** Include a valid `X-API-KEY` header in your request.

## Data Delay Responses

If upstream data feeds (Eskom, SAPP) are delayed, the API will not return stale data. Instead, you'll receive a response indicating the delay:

```json theme={null}
{
  "meta": {
    "dataset": "grid.system_state",
    "data_delay": true,
    "last_available": "2026-01-01T14:00:00Z",
    "expected_by": "2026-01-01T15:30:00Z"
  },
  "data": []
}
```

This is not an error — it indicates that the most recent data hasn't been published yet by the upstream source.

## Handling Errors in Code

<CodeGroup>
  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.powersignals.co.za/api/v1/grid/system-state",
      headers={"X-API-KEY": "your_key"},
      params={"start": "2026-01-01T00:00:00Z", "end": "2026-01-02T00:00:00Z"},
  )

  if response.status_code == 200:
      data = response.json()
  elif response.status_code == 429:
      retry_after = int(response.headers.get("Retry-After", 60))
      print(f"Rate limited. Retry in {retry_after}s")
  elif response.status_code == 400:
      error = response.json()
      print(f"Bad request: {error['detail']}")
  elif response.status_code == 401:
      print("Check your API key")
  else:
      print(f"Unexpected error: {response.status_code}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.powersignals.co.za/api/v1/grid/system-state?start=2026-01-01T00:00:00Z&end=2026-01-02T00:00:00Z",
    { headers: { "X-API-KEY": "your_key" } }
  );

  if (response.ok) {
    const { meta, data } = await response.json();
  } else if (response.status === 429) {
    const retryAfter = response.headers.get("Retry-After") || 60;
    console.log(`Rate limited. Retry in ${retryAfter}s`);
  } else if (response.status === 400) {
    const { error, detail } = await response.json();
    console.error(`Bad request: ${detail}`);
  } else if (response.status === 401) {
    console.error("Check your API key");
  }
  ```
</CodeGroup>
