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

# Rate limiting

> Understand API rate limits and how to handle them.

The Tibbie API enforces rate limits to ensure fair usage and platform stability.

## Limits

| Endpoint | Limit |
| - | - |
| All endpoints | 60 requests per minute |
| `POST /media` | 30 requests per minute |

Rate limits are applied per authenticated user. If you're not authenticated, limits are applied per IP address.

## Response headers

Every API response includes headers to help you track your current rate limit usage:

| Header | Description |
| - | - |
| `x-ratelimit-limit` | The maximum number of requests allowed per minute. |
| `x-ratelimit-remaining` | The number of requests remaining in the current window. |

```
x-ratelimit-limit: 60
x-ratelimit-remaining: 59
```

## Handling rate limits

When you exceed a rate limit, the API returns a `429 Too Many Requests` response.

### Response

```json theme={null}
{
  "message": "Too Many Attempts."
}
```

Check the `x-ratelimit-reset` header for when the limit resets, or simply wait and retry.

### Exponential backoff

Use exponential backoff to handle rate limits gracefully:

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

def make_request(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)
        
        if response.status_code == 429:
            # Check for reset header, default to increasing delay
            wait_time = 2 ** attempt
            time.sleep(wait_time)
            continue
            
        return response
    
    raise Exception("Max retries exceeded")
```

```javascript theme={null}
async function makeRequest(url, headers, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, { headers });
    
    if (response.status === 429) {
      const waitTime = Math.pow(2, attempt) * 1000;
      await new Promise(r => setTimeout(r, waitTime));
      continue;
    }
    
    return response;
  }
  throw new Error('Max retries exceeded');
}
```

```bash theme={null}
# In shell scripts, use a simple loop with sleep
for i in 1 2 3; do
  response=$(curl -s -o /dev/null -w "%{http_code}" \
    -H "Authorization: Bearer $TOKEN" \
    https://tibbie.co/api/v1/posts)
  
  if [ "$response" -eq 200 ]; then
    break
  fi
  
  sleep $i  # 1s, 2s, 3s
done
```

### Best practices

* **Space out requests** — Don't batch too many at once
* **Cache responses** — Reuse data when possible
* **Monitor headers** — Check `x-ratelimit-remaining` proactively
* **Queue requests** — For bulk operations, use a job queue with delays


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.