Rate Limits¶
Fair usage for everyone. Rate limits protect the API and ensure consistent performance. Limits vary by subscription tier.
Rate Limit Tiers¶
| Tier | Requests/min | Requests/day | Characters/day | Concurrent |
|---|---|---|---|---|
| Pauhu® | 60 | 1,000 | 100,000 | 5 |
| Pro | 600 | 100,000 | 10,000,000 | 50 |
| Max | 3,000 | 1,000,000 | 100,000,000 | 200 |
| Ops | Custom | Custom | Custom | Custom |
Rate Limit Headers¶
Every response includes rate limit headers:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-RateLimit-Reset: 1705312800
X-RateLimit-Resource: translate
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Requests remaining in window |
X-RateLimit-Reset | Unix timestamp when window resets |
X-RateLimit-Resource | Which resource this limit applies to |
Rate Limit Response¶
When rate limited, you receive a 429 Too Many Requests:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please retry after 60 seconds.",
"status": 429,
"details": {
"limit": 60,
"remaining": 0,
"reset_at": "2025-01-15T10:31:00Z",
"retry_after": 60
}
}
}
The response includes a Retry-After header:
Resource-Specific Limits¶
Different endpoints have different limits:
| Resource | Pauhu® | Pro | Max |
|---|---|---|---|
/translate | 60/min | 600/min | 3000/min |
/translate/batch | 10/min | 100/min | 500/min |
/documents | 10/hour | 100/hour | 500/hour |
/detect | 120/min | 1200/min | 6000/min |
/languages | No limit | No limit | No limit |
Handling Rate Limits¶
Python¶
import time
from pauhu import Pauhu
from pauhu.exceptions import RateLimitError
client = Pauhu()
def translate_with_backoff(text: str, target: str, max_retries: int = 3):
for attempt in range(max_retries):
try:
return client.translate(text, target=target)
except RateLimitError as e:
if attempt < max_retries - 1:
print(f"Rate limited. Waiting {e.retry_after}s...")
time.sleep(e.retry_after)
else:
raise
result = translate_with_backoff("Hello", "fi")
TypeScript¶
import { Pauhu, RateLimitError } from '@pauhu/sdk';
const client = new Pauhu({ apiKey: 'pk_...' });
async function translateWithBackoff(
text: string,
target: string,
maxRetries = 3
) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.translate({ text, target });
} catch (e) {
if (e instanceof RateLimitError && attempt < maxRetries - 1) {
console.log(`Rate limited. Waiting ${e.retryAfter}s...`);
await new Promise(r => setTimeout(r, e.retryAfter * 1000));
} else {
throw e;
}
}
}
}
Best Practices¶
1. Check Headers Before Retrying¶
response = client._last_response
remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
if remaining < 10:
print("Warning: Running low on rate limit")
2. Implement Exponential Backoff¶
import random
def backoff_delay(attempt: int, base: float = 1.0) -> float:
"""Calculate delay with exponential backoff and jitter."""
delay = base * (2 ** attempt)
jitter = random.uniform(0, delay * 0.1)
return delay + jitter
3. Use Batch Endpoints¶
Instead of:
Do:
4. Cache Results¶
from functools import lru_cache
@lru_cache(maxsize=1000)
def cached_translate(text: str, target: str) -> str:
result = client.translate(text, target=target)
return result.translation
5. Use Webhooks for Long Operations¶
# Instead of polling
result = client.translate_document(
file_path="large_doc.pdf",
target="fi",
webhook_url="https://yourapp.com/webhook"
)
# Don't poll - wait for webhook callback
Quota Management¶
Check Current Usage¶
usage = client.usage.current()
print(f"Characters used: {usage.characters_used:,}")
print(f"Characters limit: {usage.characters_limit:,}")
print(f"Requests today: {usage.requests_today:,}")
print(f"Reset at: {usage.reset_at}")
Set Usage Alerts¶
client.usage.set_alert(
threshold=0.8, # 80% of limit
webhook_url="https://yourapp.com/usage-alert"
)
Requesting Higher Limits¶
For higher limits, contact sales:
Include:
- Current tier
- Required limits
- Use case description
- Expected volume