Updated April 22, 2026
Error Handling
The RecruitSome API uses standard HTTP response codes to indicate the success or failure of requests. This guide helps you understand and handle different error scenarios.
Error Response Format
All error responses follow a consistent JSON structure:
{
"message": "Human-readable error description",
"errors": {
"field_name": ["Specific validation error for this field"]
}
}
HTTP Status Codes
Success Codes (2xx)
| Code | Description |
|---|---|
| 200 | OK - Request succeeded |
| 201 | Created - Resource created successfully |
| 204 | No Content - Request succeeded with no response body |
Client Error Codes (4xx)
| Code | Description |
|---|---|
| 401 | Unauthorized - Invalid or missing API key |
| 403 | Forbidden - Valid API key but insufficient permissions |
| 404 | Not Found - Resource doesn't exist |
| 422 | Unprocessable Entity - Validation errors |
| 429 | Too Many Requests - Rate limit exceeded |
Server Error Codes (5xx)
| Code | Description |
|---|---|
| 500 | Internal Server Error - Something went wrong on our end |
| 502 | Bad Gateway - Temporary server issue |
| 503 | Service Unavailable - API is temporarily offline |
Common Error Scenarios
Authentication Errors
Missing API Key
{
"message": "Unauthenticated."
}
Resolution: Include your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Invalid API Key
{
"message": "Invalid authentication credentials."
}
Resolution: Verify your API key is correct and hasn't been revoked.
Authorization Errors
API Access Disabled
{
"message": "API access is not enabled for this tenant."
}
Resolution: Contact your administrator to enable API access in Settings → Integrations.
Validation Errors
Invalid Query Parameters
{
"message": "The given data was invalid.",
"errors": {
"per_page": ["The per page must not be greater than 100."],
"language": ["The language must be 2 characters."]
}
}
Resolution: Check the errors object for specific field issues.
Invalid Filter Values
{
"message": "The given data was invalid.",
"errors": {
"location_id": ["The selected location id is invalid."],
"job_types.0": ["The job_types.0 must be an integer."]
}
}
Insufficient Scope
Missing API Permission (403)
{
"message": "This API key does not have the required permission: candidates:read",
"error": "INSUFFICIENT_SCOPE",
"required_scope": "candidates:read"
}
Resolution: Create a new API key with the required scope in Settings → Integrations → API Keys, or contact your administrator.
Available Scopes:
| Scope | Access |
|---|---|
vacancies:read | View published vacancies and facets |
applications:write | Submit job applications |
candidates:read | View candidate list and profiles |
candidates:write | Create candidates via resume upload |
team:read | View team members |
locations:read | View office locations |
articles:read | Read published articles |
API keys created before the scoping system was introduced have full access (*) and are not affected by scope restrictions.
Resource Errors
Vacancy Not Found
{
"message": "The requested resource was not found."
}
Possible Causes:
- Invalid slug
- Vacancy is unpublished
- Vacancy is not available through API channel
- Vacancy has expired
Rate Limiting
Rate Limit Exceeded
{
"message": "Too many requests. Please wait before trying again."
}
Response Headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705765200
Resolution: Wait until the reset time or implement exponential backoff.
Error Handling Best Practices
1. Implement Retry Logic
async function apiRequestWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
// Rate limited - wait before retry
const resetTime = response.headers.get('X-RateLimit-Reset');
const waitTime = resetTime
? (parseInt(resetTime) * 1000) - Date.now()
: Math.pow(2, i) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
if (response.status >= 500) {
// Server error - retry with exponential backoff
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, i) * 1000)
);
continue;
}
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
}
}
}
2. Handle Validation Errors
async function createResource(data) {
const response = await fetch('/api/v1/resource', {
method: 'POST',
headers: {
'Authorization': Bearer ${API_KEY},
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.status === 422) {
const error = await response.json();
// Display field-specific errors to user
Object.entries(error.errors).forEach(([field, messages]) => {
console.error(${field}: ${messages.join(', ')});
});
return null;
}
return response.json();
}
3. Log Errors Appropriately
function logApiError(error, context) {
const errorLog = {
timestamp: new Date().toISOString(),
context: context,
status: error.status,
message: error.message,
errors: error.errors,
requestId: error.headers?.get('X-Request-ID')
};
// Send to your logging service
console.error('API Error:', errorLog);
}
Debugging Tips
- Check Response Headers: Look for
X-Request-IDto reference when contacting support - Validate JSON: Ensure request bodies are valid JSON
- Check API Status: Visit https://status.recruitsome.com for service status
- Test with cURL: Isolate issues by testing with simple cURL commands
- Enable Debug Mode: Add
?debug=trueto get more detailed error messages (development only)
Getting Help
If you encounter persistent errors:
- Note the error message and status code
- Record the
X-Request-IDfrom response headers - Contact [email protected] with:
- Request details (endpoint, parameters)
- Error response
- Request ID