Troubleshooting Common API Errors
400 – Bad Request
Your request is malformed or contains invalid data.
Common causes:
- Missing required fields in request body
- Invalid JSON syntax
- Wrong data types (string instead of integer)
- Sending body with GET request
- Invalid query parameters
Example error response:
{
"error": "Bad Request",
"message": "The issue_id field is required.",
"status": 400
}
How to fix:
// ❌ Bad: Missing required field
POST /api/user/collection
{
"condition": "NM"
// Missing issue_id!
}
// ✅ Good: All required fields present
POST /api/user/collection
{
"issue_id": 12345,
"condition": "NM"
}
Debugging checklist:
- Validate JSON syntax with a linter
- Check API docs for required fields
- Ensure data types match (numbers as numbers, not strings)
- Don't send request body with GET requests
401 – Unauthorized
You are not authenticated, or your token is invalid/expired.
Common causes:
- Missing
Authorizationheader - Invalid or expired token
- Token was revoked
- Typo in Bearer token
Example error response:
{
"error": "Unauthorized",
"message": "Unauthenticated.",
"status": 401
}
How to fix:
// ❌ Bad: Missing Authorization header
fetch('https://versedb.com/api/user/collection')
// ✅ Good: Proper authentication
fetch('https://versedb.com/api/user/collection', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN_HERE'
}
})
Troubleshooting steps:
- Verify token exists and is copied correctly
- Check for extra spaces or characters in token
- Ensure using
Bearerprefix (notTokenorBasic) - Generate new token at: https://versedb.com/user/api-tokens
- Test token with a simple endpoint first (e.g.,
GET /api/user)
Example: Testing your token
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://versedb.com/api/user
402 – Payment Required
You're trying to access a PRO-only feature without a PRO subscription.
Common causes:
- Accessing relationship endpoints (
/api/series/{id}/issues) - Accessing market data endpoints
- PRO-only features with free account
Example error response:
{
"error": "Payment Required",
"message": "This endpoint requires a PRO subscription.",
"status": 402
}
How to fix:
- Upgrade to PRO at https://versedb.com/subscription
- Or use alternative endpoints available to free users
403 – Forbidden
You are authenticated but lack permission to perform this action.
Common causes:
- Token lacks required scope/permission
- Attempting to access another user's private data
- Attempting admin operations without admin role
- Resource privacy settings prevent access
Example error response:
{
"error": "Forbidden",
"message": "This action is unauthorized.",
"status": 403
}
How to fix:
-
Check token permissions:
- Go to https://versedb.com/user/api-tokens
- Verify token has required abilities
- Create new token with correct permissions if needed
-
Verify resource access:
- Ensure you're accessing your own data, not someone else's
- Check if user profile is public if accessing public endpoints
Token abilities:
read:public– Read public comic dataread:user– Read your personal datawrite:lists– Manage collections, wishlists, pull listswrite:reviews– Write reviewswrite:favorites– Manage favorites
404 – Not Found
The requested resource doesn't exist.
Common causes:
- Incorrect or non-existent ID
- Typo in endpoint path
- Using slug instead of numeric ID
- Resource was deleted
Example error response:
{
"error": "Not Found",
"message": "No query results for model [Series] 99999",
"status": 404
}
How to fix:
// ❌ Bad: Using slug
GET /api/series/amazing-spider-man-2018
// ✅ Good: Using numeric ID
GET /api/series/123
// ❌ Bad: Wrong path
GET /api/serie/123 // Typo: "serie" instead of "series"
// ✅ Good: Correct path
GET /api/series/123
Debugging:
- Verify ID exists by searching first
- Check endpoint path against API docs
- Use numeric IDs, not slugs
405 – Method Not Allowed
You're using the wrong HTTP method for this endpoint.
Common causes:
- Using POST instead of GET
- Using GET instead of POST
- Using PUT instead of PATCH (or vice versa)
- Endpoint doesn't support that method
Example error response:
{
"error": "Method Not Allowed",
"message": "The GET method is not supported for this route.",
"status": 405
}
How to fix:
// ❌ Bad: Using GET for write operation
GET /api/user/collection
// ✅ Good: Use POST to add to collection
POST /api/user/collection
// ❌ Bad: Using POST to fetch data
POST /api/series/123
// ✅ Good: Use GET to read data
GET /api/series/123
HTTP method reference:
- GET – Read/retrieve data
- POST – Create new resources
- PUT/PATCH – Update existing resources
- DELETE – Remove resources
422 – Unprocessable Entity
Request is well-formed but contains semantic errors or validation failures.
Common causes:
- Validation rules failed
- Invalid data values
- Foreign key constraints violated
- Business logic rules not met
Example error response:
{
"error": "Unprocessable Entity",
"message": "The given data was invalid.",
"errors": {
"issue_id": ["The selected issue id is invalid."],
"condition": ["The condition must be one of: M, NM, VF, F, VG, G, FR, PR"]
},
"status": 422
}
How to fix:
- Read the
errorsobject for specific field issues - Validate data before sending
- Check allowed values for enum fields
- Ensure foreign keys reference existing records
429 – Too Many Requests
You've exceeded your rate limit.
Example error response:
{
"error": "Too Many Requests",
"message": "API rate limit exceeded. Please try again later.",
"retry_after": 3600,
"limit": 300,
"reset_at": "2025-04-12T15:00:00Z",
"status": 429
}
Response headers:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1712869200
Retry-After: 3600
How to handle:
async function fetchWithRateLimit(url, options) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
console.log(`Rate limited. Waiting ${retryAfter}s...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return fetchWithRateLimit(url, options); // Retry
}
return response;
}
Prevention:
- Monitor
X-RateLimit-Remainingheader - Implement request throttling in your client
- Cache frequently accessed data
- Upgrade to PRO for higher limits (1000/hour vs 300/hour)
500 – Internal Server Error
Something went wrong on the VerseDB server.
Example error response:
{
"error": "Internal Server Error",
"message": "An unexpected error occurred.",
"status": 500
}
What to do:
- Retry with exponential backoff:
async function retryOnServerError(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url);
if (response.status === 500) {
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
continue;
}
return response;
}
throw new Error('Server error persists after retries');
}
- If error persists:
- Check VerseDB status page (if available)
- Report issue to support with request details
- Include timestamp, endpoint, and request body
Note: 500 errors are usually temporary. If consistent, contact support.
503 – Service Unavailable
The server is temporarily unavailable (maintenance, overload, etc.)
Example error response:
{
"error": "Service Unavailable",
"message": "The service is temporarily unavailable.",
"status": 503
}
What to do:
- Wait a few minutes and retry
- Check for scheduled maintenance announcements
- Implement graceful degradation in your app
Quick Reference Table
| Code | Error | Common Fix |
|---|---|---|
| 400 | Bad Request | Check JSON syntax and required fields |
| 401 | Unauthorized | Add/update Bearer token |
| 402 | Payment Required | Upgrade to PRO subscription |
| 403 | Forbidden | Check token permissions/abilities |
| 404 | Not Found | Verify resource ID exists |
| 405 | Method Not Allowed | Use correct HTTP method (GET/POST/PUT/DELETE) |
| 422 | Unprocessable Entity | Fix validation errors in request data |
| 429 | Too Many Requests | Wait and retry, respect rate limits |
| 500 | Server Error | Retry with exponential backoff |
| 503 | Service Unavailable | Wait and retry later |
Debugging Tips
Log Full Error Response
fetch(url, {
headers: { 'Authorization': 'Bearer TOKEN' }
})
.then(response => {
if (!response.ok) {
return response.json().then(error => {
console.error('API Error:', {
status: response.status,
statusText: response.statusText,
error: error,
url: url
});
throw new Error(error.message || 'API request failed');
});
}
return response.json();
});
Check Request Headers
Use browser DevTools Network tab or curl with -v flag:
curl -v -H "Authorization: Bearer TOKEN" \
https://versedb.com/api/user/collection
Test in Isolation
Isolate the failing request and test with minimal data to identify the issue.
For more help: Visit the full API documentation at https://versedb.com/api/docs
Was this article helpful?
Please login to provide feedback