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

# REST API Errors

> HTTP error codes and responses in the Meter API

# REST API Errors

The Meter API uses standard HTTP status codes and returns JSON error messages.

## HTTP status codes

| Code  | Meaning               | Description                              |
| ----- | --------------------- | ---------------------------------------- |
| `200` | OK                    | Request succeeded                        |
| `201` | Created               | Resource created successfully            |
| `400` | Bad Request           | Invalid request parameters               |
| `401` | Unauthorized          | Invalid or missing API key               |
| `403` | Forbidden             | Valid key but insufficient permissions   |
| `404` | Not Found             | Resource doesn't exist                   |
| `422` | Unprocessable Entity  | Request valid but semantically incorrect |
| `429` | Too Many Requests     | Rate limit exceeded                      |
| `500` | Internal Server Error | Server-side error                        |
| `503` | Service Unavailable   | Temporary service issue                  |

## Error response format

All errors return JSON with a `detail` field:

```json theme={null}
{
  "detail": "Error message describing what went wrong"
}
```

## Common errors

### 401 Unauthorized

**Cause:** Invalid or missing API key

```json theme={null}
{
  "detail": "Invalid or missing API key"
}
```

**Solutions:**

* Verify `Authorization` header is included
* Check API key is correct
* Ensure key hasn't been deleted

### 400 Bad Request

**Cause:** Invalid request parameters

```json theme={null}
{
  "detail": "Invalid URL format"
}
```

Common causes:

* Missing required fields
* Invalid field types
* Malformed JSON
* Invalid UUIDs

**Solutions:**

* Check request body matches expected format
* Verify all required fields are present
* Ensure JSON is valid

### 404 Not Found

**Cause:** Resource doesn't exist

```json theme={null}
{
  "detail": "Strategy not found"
}
```

**Solutions:**

* Verify the UUID is correct
* Check the resource hasn't been deleted
* Ensure you have permission to access it

### 422 Unprocessable Entity

**Cause:** Request is valid but contains semantic errors

```json theme={null}
{
  "detail": "Invalid URL format"
}
```

**Solutions:**

* Check field values meet semantic requirements (e.g., valid URL format)
* Verify data relationships are valid

### 500 Internal Server Error

**Cause:** Server-side error

```json theme={null}
{
  "detail": "Internal server error"
}
```

**Solutions:**

* Retry the request after a delay
* If persistent, contact support
* Check API status page

## Handling errors

### JavaScript

```javascript theme={null}
const response = await fetch('https://api.meter.sh/api/strategies', {
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  }
});

if (!response.ok) {
  const error = await response.json();
  console.error(`API error (${response.status}): ${error.detail}`);

  if (response.status === 401) {
    // Handle authentication error
  } else if (response.status === 404) {
    // Handle not found
  } else if (response.status === 429) {
    // Handle rate limit - check Retry-After header
    const retryAfter = response.headers.get('Retry-After') || '60';
    console.log(`Rate limited. Retry after ${retryAfter} seconds.`);
  }
}

const data = await response.json();
```

### Python

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

response = requests.get(
    'https://api.meter.sh/api/strategies',
    headers={'Authorization': f'Bearer {api_key}'}
)

if not response.ok:
    error = response.json()
    print(f"API error ({response.status_code}): {error['detail']}")

    if response.status_code == 401:
        # Handle authentication error
        pass
    elif response.status_code == 404:
        # Handle not found
        pass
    elif response.status_code == 429:
        # Handle rate limit - check Retry-After header
        retry_after = int(response.headers.get('Retry-After', 60))
        print(f"Rate limited. Retry after {retry_after} seconds.")
        time.sleep(retry_after)

data = response.json()
```

### curl

```bash theme={null}
response=$(curl -s -w "\n%{http_code}" https://api.meter.sh/api/strategies \
  -H "Authorization: Bearer sk_live_...")

http_code=$(echo "$response" | tail -n 1)
body=$(echo "$response" | sed '$d')

if [ "$http_code" != "200" ]; then
  echo "Error ($http_code): $body"
fi
```

## Best practices

<AccordionGroup>
  <Accordion title="Implement retry logic">
    For 429, 500, and 503 errors, retry with appropriate backoff:

    ```javascript theme={null}
    async function fetchWithRetry(url, options, maxRetries = 3) {
      for (let i = 0; i < maxRetries; i++) {
        try {
          const response = await fetch(url, options);

          // Rate limited - respect Retry-After header
          if (response.status === 429) {
            const retryAfter = response.headers.get('Retry-After') || '60';
            await new Promise(r => setTimeout(r, parseInt(retryAfter) * 1000));
            continue;
          }

          // Server errors - exponential backoff
          if ((response.status === 500 || response.status === 503) && i < maxRetries - 1) {
            await new Promise(r => setTimeout(r, 2 ** i * 1000));
            continue;
          }

          return response;
        } catch (error) {
          if (i === maxRetries - 1) throw error;
          await new Promise(r => setTimeout(r, 2 ** i * 1000));
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Check status codes">
    Always check HTTP status codes before parsing responses:

    ```javascript theme={null}
    const response = await fetch(url, options);

    // Check before parsing JSON
    if (!response.ok) {
      const error = await response.json();
      throw new Error(error.detail);
    }

    const data = await response.json();
    ```
  </Accordion>

  <Accordion title="Log errors with context">
    Include request details when logging errors:

    ```javascript theme={null}
    if (!response.ok) {
      const error = await response.json();
      console.error('API request failed', {
        status: response.status,
        detail: error.detail,
        url: response.url,
        method: options.method
      });
    }
    ```
  </Accordion>
</AccordionGroup>

## Rate limiting

Strategy generation endpoints (`/api/strategies/generate`, `/api/watch`) are rate limited to prevent overloading the underlying LLM service.

### 429 Too Many Requests

When you hit rate limits, the API returns:

```
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json

{
  "detail": "Please slow down - limits on strategy generation"
}
```

The `Retry-After` header tells you how many seconds to wait before retrying.

### Handling rate limits

**JavaScript:**

```javascript theme={null}
const response = await fetch(url, options);

if (response.status === 429) {
  const retryAfter = response.headers.get('Retry-After') || '60';
  const waitSeconds = parseInt(retryAfter, 10);

  console.log(`Rate limited. Waiting ${waitSeconds} seconds...`);
  await new Promise(r => setTimeout(r, waitSeconds * 1000));

  // Retry the request
  return fetch(url, options);
}
```

**Python:**

```python theme={null}
response = requests.post(url, headers=headers, json=data)

if response.status_code == 429:
    retry_after = int(response.headers.get('Retry-After', 60))
    print(f"Rate limited. Waiting {retry_after} seconds...")
    time.sleep(retry_after)

    # Retry the request
    response = requests.post(url, headers=headers, json=data)
```

### 503 Service Unavailable

If the LLM service is temporarily unavailable:

```json theme={null}
{
  "detail": "Service temporarily unavailable. Please try again later."
}
```

## Next steps

<CardGroup cols={2}>
  <Card title="Python SDK Errors" icon="python" href="/api-reference/python/errors">
    Error handling in the Python SDK
  </Card>

  <Card title="REST API Overview" icon="book" href="/api-reference/rest/overview">
    Learn about the REST API
  </Card>

  <Card title="Authentication" icon="key" href="/api-reference/rest/authentication">
    Understand authentication errors
  </Card>
</CardGroup>

## Need help?

Email me at [mckinnon@meter.sh](mailto:mckinnon@meter.sh)
