Error Handling
HTTP Status Codes
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request successful |
| 400 | Bad Request | Missing required fields or invalid parameters |
| 401 | Unauthorized | Invalid or missing API key |
| 402 | Payment Required | Insufficient credits |
| 404 | Not Found | Resource not found (ex. no data for the requested date, or unknown sign/id) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side failure |
Error Response Format
Les réponses d'erreur suivent cette structure de base, enrichie du contexte selon le cas :
{
"error": "Courte description de l'erreur",
"message": "Message détaillé (présent sur les erreurs métier les plus expliquées)",
"code": "CODE_NORMALISE (parfois présent, ex. MONTHLY_QUOTA_EXCEEDED)",
"required": 1,
"available": 0
}
- Toutes les erreurs contiennent au minimum le champ
error. - Les champs
required/available(402) indiquent le coût attendu et le solde disponible. - Le champ
codeest optionnel et sert à distinguer programmatiquement certains cas (ex. quota dépassé).
Common Errors
400 - Bad Request
{
"error": "Missing required fields: birthDate, birthTime"
}
Location invalide : le code renvoie Missing location information (un identifiant de lieu n'a pas pu être résolu).
Dates/heures : les messages de lib/validation/birthInputs.ts utilisent "Use YYYY-MM-DD format (e.g., 1990-12-25)" et "Use HH:MM 24-hour format".
401 - Unauthorized
Le middleware (lib/middleware/apiAuth.ts) émet deux cas :
- Clé absente :
API key required - Clé invalide ou inactive :
Invalid or inactive API key
Il n'existe pas de message distinct « revoked » — une clé révoquée est traitée comme
Invalid or inactive API key.
402 - Payment Required
{
"error": "Insufficient credits",
"message": "Transit analysis costs 3 credits. Please purchase more credits.",
"required": 3,
"available": 1
}
Quota Cosmo dépassé (cosmo/chat) :
{
"error": "Monthly quota exceeded",
"code": "MONTHLY_QUOTA_EXCEEDED",
"message": "Monthly quota exceeded. Upgrade your plan or purchase credits to continue."
}
404 - Not Found
Ex. aucune donnée pour la date demandée, signe ou identifiant inconnu :
{
"error": "No transit data available",
"message": "Cosmic data for today is being prepared. Please try again later."
}
429 - Too Many Requests
{
"success": false,
"error": "Rate limit exceeded",
"message": "Too many requests. Please try again in 30 seconds.",
"retryAfter": 30,
"limit": 60,
"reset": 1640995200
}
500 - Internal Server Error
{
"error": "Blueprint generation failed"
}
Rate Limit Headers
Chaque réponse (hors streaming Cosmo, voir rate-limits.md) inclut X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
Error Handling Best Practices
JavaScript Example
try {
const response = await fetch('https://mycosmicadvisor.com/api/v1/generate-blueprint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer bgapi_your_key_here'
},
body: JSON.stringify({
birthDate: '1990-12-25',
birthTime: '14:30',
city: 'New York',
country: 'USA',
fullName: 'John Doe'
})
});
const data = await response.json();
if (!response.ok) {
// Handle HTTP errors
switch (response.status) {
case 400:
console.error('Invalid request:', data.error);
break;
case 401:
console.error('Authentication failed:', data.error);
break;
case 402:
console.error('Insufficient credits:', data.error);
break;
case 500:
console.error('Server error:', data.error);
break;
default:
console.error('Unexpected error:', data.error);
}
return;
}
// Success
console.log('Blueprint generated:', data);
} catch (error) {
console.error('Network error:', error);
}
Python Example
import requests
try:
response = requests.post(
'https://mycosmicadvisor.com/api/v1/generate-blueprint',
headers={
'Content-Type': 'application/json',
'Authorization': 'Bearer bgapi_your_key_here'
},
json={
'birthDate': '1990-12-25',
'birthTime': '14:30',
'city': 'New York',
'country': 'USA',
'fullName': 'John Doe'
}
)
data = response.json()
if response.status_code == 200:
print('Blueprint generated:', data)
elif response.status_code == 400:
print('Invalid request:', data['error'])
elif response.status_code == 401:
print('Authentication failed:', data['error'])
elif response.status_code == 402:
print('Insufficient credits:', data['error'])
elif response.status_code == 500:
print('Server error:', data['error'])
else:
print('Unexpected error:', data['error'])
except requests.exceptions.RequestException as e:
print('Network error:', e)
Retry Logic
For transient errors (500), implement exponential backoff:
async function generateWithRetry(requestData, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch('https://mycosmicadvisor.com/api/v1/generate-blueprint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer bgapi_your_key_here'
},
body: JSON.stringify(requestData)
});
const data = await response.json();
if (response.status === 500 && attempt < maxRetries) {
// Wait before retrying (exponential backoff)
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return data;
} catch (error) {
if (attempt === maxRetries) throw error;
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}