Error Reference
API error codes and troubleshooting
Error Response Format
All errors return JSON with this structure:
{
"error": "ErrorType",
"message": "Human-readable description of the error"
}HTTP Status Codes
| Code | Meaning |
|---|---|
| 400 | Bad Request - Invalid request body or parameters |
| 401 | Unauthorized - Invalid or missing API key |
| 402 | Payment Required - Insufficient balance |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error - Something went wrong on our end |
Authentication Errors (401)
Invalid API Key
{
"error": "Unauthorized",
"message": "Invalid API key"
}Causes:
- API key is malformed
- API key doesn't exist
Solutions:
- Verify you're using the complete key
- Generate a new key from the dashboard
Missing API Key
{
"error": "Unauthorized",
"message": "Missing Authorization header"
}Solution: Include the Authorization: Bearer YOUR_KEY header.
Revoked Key
{
"error": "Unauthorized",
"message": "API key has been revoked"
}Solution: Generate a new API key from the dashboard.
Wrong Service
{
"error": "Unauthorized",
"message": "API key not authorized for this service"
}Cause: Using a key for a different service (e.g., using a future "translate" key with verify).
Solution: Create a key specifically for the service you're calling.
Payment Errors (402)
Insufficient Balance
{
"error": "Payment Required",
"message": "Insufficient balance"
}Solution: Add funds to your app from the dashboard.
Prevention: Check your balance before making requests:
- Monitor the
tokenUsagein responses - Set up balance alerts (coming soon)
Rate Limit Errors (429)
Per-Minute Limit
{
"error": "Rate Limit Exceeded",
"message": "Too many requests per minute"
}Headers included:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1699999999
Retry-After: 45Per-Day Limit
{
"error": "Rate Limit Exceeded",
"message": "Daily request limit exceeded"
}Solutions:
- Wait for the rate limit to reset
- Implement exponential backoff
- Cache results when possible
See Rate Limits for detailed handling strategies.
Validation Errors (400)
Missing Required Field
{
"error": "Bad Request",
"message": "fact is required"
}Invalid Field Value
{
"error": "Bad Request",
"message": "minRequired must be 2 or 3"
}Invalid JSON
{
"error": "Bad Request",
"message": "Invalid JSON in request body"
}Solution: Ensure your request body is valid JSON and includes the required fields.
Server Errors (500)
Internal Error
{
"error": "Internal Server Error",
"message": "An unexpected error occurred"
}What to do:
- Retry the request after a short delay
- If it persists, contact support
- Check our status page for known issues
Handling Errors in Code
JavaScript/TypeScript
async function verifyFact(fact: string) {
const response = await fetch('https://console.mira.network/verify/v1/stream', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MIRA_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ fact }),
});
if (!response.ok) {
const error = await response.json();
switch (response.status) {
case 401:
throw new Error(`Authentication failed: ${error.message}`);
case 402:
throw new Error('Insufficient balance - please add funds');
case 429:
const retryAfter = response.headers.get('Retry-After');
throw new Error(`Rate limited - retry after ${retryAfter}s`);
default:
throw new Error(`API error: ${error.message}`);
}
}
// Process successful response...
}Retry with Exponential Backoff
async function fetchWithRetry(
fn: () => Promise<Response>,
maxRetries = 3
): Promise<Response> {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fn();
if (response.status === 429) {
const retryAfter = parseInt(
response.headers.get('Retry-After') || '60'
);
await sleep(retryAfter * 1000);
continue;
}
if (response.status >= 500) {
await sleep(Math.pow(2, i) * 1000); // Exponential backoff
continue;
}
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
throw new Error('Max retries exceeded');
}
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}