Errors
Predictable error handling. Consistent error format across all endpoints with actionable error codes.
All errors follow this structure:
{
"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"
}
},
"meta": {
"request_id": "req_abc123"
}
}
HTTP Status Codes
| Status | Category | Description |
200 | Success | Request succeeded |
201 | Success | Resource created |
400 | Client Error | Invalid request |
401 | Client Error | Authentication failed |
403 | Client Error | Forbidden |
404 | Client Error | Not found |
409 | Client Error | Conflict |
422 | Client Error | Validation error |
429 | Client Error | Rate limit exceeded |
500 | Server Error | Internal error |
502 | Server Error | Bad gateway |
503 | Server Error | Service unavailable |
Error Codes
Authentication Errors (401)
| Code | Message | Solution |
invalid_api_key | The API key provided is invalid | Check API key format |
expired_api_key | The API key has expired | Generate new key |
missing_api_key | No API key provided | Add Authorization header |
revoked_api_key | The API key has been revoked | Contact support |
Authorization Errors (403)
| Code | Message | Solution |
insufficient_scope | Key lacks required scope | Use key with correct scopes |
ip_not_allowed | Request IP not in allowlist | Add IP to allowlist |
organization_suspended | Organization suspended | Contact support |
Validation Errors (400/422)
| Code | Message | Solution |
invalid_request | Request body is malformed | Check JSON syntax |
invalid_language | Language code not supported | Use ISO 639-1 code |
text_too_long | Text exceeds maximum length | Split into smaller chunks |
missing_required_field | Required field missing | Add required parameter |
invalid_file_format | File format not supported | Use supported format |
file_too_large | File exceeds size limit | Reduce file size |
Rate Limit Errors (429)
| Code | Message | Solution |
rate_limit_exceeded | Too many requests | Wait and retry |
quota_exceeded | Character quota exhausted | Upgrade plan or wait |
concurrent_limit | Too many concurrent requests | Reduce parallelism |
Resource Errors (404/410)
| Code | Message | Solution |
not_found | Resource not found | Check ID/path |
document_expired | Document download expired | Re-upload document |
glossary_not_found | Glossary does not exist | Create glossary first |
Server Errors (5xx)
| Code | Message | Solution |
internal_error | Internal server error | Retry with backoff |
service_unavailable | Service temporarily unavailable | Retry later |
model_unavailable | Translation model unavailable | Try different model |
Error Handling
Python
from pauhu import Pauhu
from pauhu.exceptions import (
PauhuError,
AuthenticationError,
RateLimitError,
ValidationError,
NotFoundError,
ServerError
)
client = Pauhu()
try:
result = client.translate("Hello", target="fi")
except AuthenticationError as e:
# Invalid or missing API key
print(f"Auth error: {e.message}")
print(f"Code: {e.code}")
except RateLimitError as e:
# Rate limit exceeded
print(f"Rate limited. Retry after {e.retry_after}s")
time.sleep(e.retry_after)
# Retry...
except ValidationError as e:
# Invalid request parameters
print(f"Validation error: {e.message}")
for field, errors in e.details.items():
print(f" {field}: {errors}")
except NotFoundError as e:
# Resource not found
print(f"Not found: {e.message}")
except ServerError as e:
# Server-side error, retry with backoff
print(f"Server error: {e.message}")
except PauhuError as e:
# Catch-all for any Pauhu error
print(f"Error: {e.code} - {e.message}")
TypeScript
import { Pauhu, PauhuError, RateLimitError } from '@pauhu/sdk';
const client = new Pauhu({ apiKey: 'pk_...' });
try {
const result = await client.translate({ text: 'Hello', target: 'fi' });
} catch (error) {
if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter}s`);
await sleep(error.retryAfter * 1000);
// Retry...
} else if (error instanceof PauhuError) {
console.log(`Error: ${error.code} - ${error.message}`);
}
}
cURL
response=$(curl -s -w "\n%{http_code}" \
-X POST https://api.pauhu.ai/v1/translate \
-H "Authorization: Bearer pk_..." \
-H "Content-Type: application/json" \
-d '{"text": "Hello", "target": "fi"}')
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" -ge 400 ]; then
error_code=$(echo "$body" | jq -r '.error.code')
echo "Error: $error_code"
fi
Retry Strategy
Recommended Backoff
import time
import random
from pauhu import Pauhu
from pauhu.exceptions import RateLimitError, ServerError
def translate_with_retry(client, text, target, max_retries=3):
for attempt in range(max_retries):
try:
return client.translate(text, target=target)
except RateLimitError as e:
if attempt < max_retries - 1:
time.sleep(e.retry_after)
else:
raise
except ServerError:
if attempt < max_retries - 1:
# Exponential backoff with jitter
delay = (2 ** attempt) + random.random()
time.sleep(delay)
else:
raise
Rate limit responses include retry information:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312860
Retry-After: 60
Debugging
Request ID
Every response includes a request ID:
{
"meta": {
"request_id": "req_abc123def456"
}
}
Include this when contacting support.
Verbose Logging