Errors
Understanding and properly handling errors is crucial for building robust integrations with LoomAPI. This guide covers our error response format, common error codes, and best practices for error handling.
Error Response Format
All errors follow a consistent JSON structure:
{
"request_id": "req_1234567890abcdef",
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {
"field": "additional_context",
"value": "specific_information"
}
}
}
Response Fields
request_id: Unique identifier for the request (use this when contacting support)error.code: Machine-readable error codeerror.message: Human-readable descriptionerror.details: Additional context (optional)
HTTP Status Codes
We use standard HTTP status codes:
400 Bad Request: Invalid request parameters401 Unauthorized: Authentication failed403 Forbidden: Insufficient permissions404 Not Found: Resource not found429 Too Many Requests: Rate limit exceeded500 Internal Server Error: Server error503 Service Unavailable: Service temporarily unavailable
Common Error Codes
Authentication Errors
AUTH_INVALID_KEY
Status: 401 Description: The provided API key is invalid, expired, or malformed.
{
"request_id": "req_1234567890",
"error": {
"code": "AUTH_INVALID_KEY",
"message": "The provided API key is invalid or expired"
}
}
Solutions:
- Verify your API key in the dashboard
- Check for typos in the Authorization header
- Ensure the key hasn't expired
AUTH_MISSING
Status: 401 Description: No authentication provided.
{
"request_id": "req_1234567890",
"error": {
"code": "AUTH_MISSING",
"message": "Authentication required"
}
}
Document Errors
DOCUMENT_INVALID_FORMAT
Status: 400 Description: The document format is not supported.
{
"request_id": "req_1234567890",
"error": {
"code": "DOCUMENT_INVALID_FORMAT",
"message": "Unsupported document format. Supported: jpeg, png, pdf",
"details": {
"provided_format": "gif",
"supported_formats": ["jpeg", "png", "pdf"]
}
}
}
DOCUMENT_TOO_LARGE
Status: 400 Description: Document file size exceeds limits.
{
"request_id": "req_1234567890",
"error": {
"code": "DOCUMENT_TOO_LARGE",
"message": "Document size exceeds 10MB limit",
"details": {
"max_size_mb": 10,
"provided_size_mb": 15.2
}
}
}
DOCUMENT_QUALITY_LOW
Status: 400 Description: Document image quality is insufficient for processing.
{
"request_id": "req_1234567890",
"error": {
"code": "DOCUMENT_QUALITY_LOW",
"message": "Document quality too low for accurate processing",
"details": {
"issues": ["blurry", "low_resolution"],
"min_resolution": "300x300"
}
}
}
Processing Errors
PROCESSING_TIMEOUT
Status: 500 Description: Document processing took too long.
{
"request_id": "req_1234567890",
"error": {
"code": "PROCESSING_TIMEOUT",
"message": "Document processing timed out",
"details": {
"timeout_seconds": 30
}
}
}
VERIFICATION_FAILED
Status: 400 Description: Document verification failed.
{
"request_id": "req_1234567890",
"error": {
"code": "VERIFICATION_FAILED",
"message": "Document verification failed",
"details": {
"reason": "document_expired",
"confidence_score": 0.15
}
}
}
Rate Limiting
RATE_LIMIT_EXCEEDED
Status: 429 Description: Rate limit exceeded.
{
"request_id": "req_1234567890",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"details": {
"retry_after_seconds": 30,
"limit": 100,
"window_seconds": 60
}
}
}
Error Handling Best Practices
Implement Retry Logic
async function makeRequestWithRetry(url, options, maxRetries = 3) {
let lastError
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url, options)
if (response.ok) {
return response
}
const errorData = await response.json()
// Don't retry on client errors (4xx)
if (response.status >= 400 && response.status < 500) {
throw new Error(`Client error: ${errorData.error.message}`)
}
// Retry on server errors (5xx) and rate limits
if (response.status >= 500 || response.status === 429) {
lastError = new Error(`Server error: ${errorData.error.message}`)
if (attempt < maxRetries) {
const delay = calculateDelay(attempt, response.headers.get('X-RateLimit-Retry-After'))
await new Promise(resolve => setTimeout(resolve, delay))
continue
}
}
throw new Error(`HTTP ${response.status}: ${errorData.error.message}`)
} catch (error) {
lastError = error
if (attempt < maxRetries) {
const delay = calculateDelay(attempt)
await new Promise(resolve => setTimeout(resolve, delay))
continue
}
}
}
throw lastError
}
function calculateDelay(attempt, retryAfter = null) {
if (retryAfter) {
return parseInt(retryAfter) * 1000
}
// Exponential backoff: 1s, 2s, 4s, etc.
return Math.pow(2, attempt - 1) * 1000
}
Log Errors Appropriately
async function handleApiCall() {
try {
const response = await fetch('/api/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(documentData)
})
if (!response.ok) {
const errorData = await response.json()
// Log structured error for monitoring
console.error('API Error', {
requestId: errorData.request_id,
code: errorData.error.code,
message: errorData.error.message,
status: response.status,
timestamp: new Date().toISOString()
})
// Handle specific error types
switch (errorData.error.code) {
case 'RATE_LIMIT_EXCEEDED':
// Show user-friendly message and retry
showRateLimitMessage(errorData.error.details.retry_after_seconds)
break
case 'DOCUMENT_QUALITY_LOW':
// Prompt user to retake photo
showQualityError()
break
default:
// Generic error handling
showGenericError(errorData.error.message)
}
return
}
const result = await response.json()
handleSuccess(result)
} catch (networkError) {
console.error('Network Error', networkError)
showNetworkError()
}
}
User-Friendly Error Messages
Map technical errors to user-friendly messages:
const errorMessages = {
'AUTH_INVALID_KEY': 'Your session has expired. Please sign in again.',
'DOCUMENT_QUALITY_LOW': 'Please take a clearer photo of your document.',
'DOCUMENT_TOO_LARGE': 'Please choose a smaller file (max 10MB).',
'RATE_LIMIT_EXCEEDED': 'Too many requests. Please wait a moment and try again.',
'PROCESSING_TIMEOUT': 'Verification is taking longer than expected. Please try again.',
'VERIFICATION_FAILED': 'We couldn\'t verify this document. Please try with a different one.'
}
function getUserFriendlyMessage(errorCode) {
return errorMessages[errorCode] || 'Something went wrong. Please try again.'
}
Monitoring and Debugging
Use Request IDs
Always include the request_id when contacting support:
Subject: Issue with request req_1234567890abcdef
Hi Support Team,
I'm getting a VERIFICATION_FAILED error for request req_1234567890abcdef.
The document appears valid but verification keeps failing.
Request details:
- Time: 2024-01-15 14:30:00 UTC
- Document type: passport
- Error: VERIFICATION_FAILED
Can you help investigate?
Thanks,
[Your Name]
Test with Different Documents
- Try different document types
- Test with high-quality images
- Use our test mode for debugging
Check Your Integration
- Verify authentication headers
- Ensure correct Content-Type
- Validate base64 encoding
- Check file size limits
Getting Help
If you're still having issues:
- Check this documentation for common solutions
- Review your code against our examples
- Test with our API using different documents
- Contact support with your request ID
Email: support@loomapi.com Include your request ID and error details for faster resolution.