Updated June 15, 2026
The Recruitsome API uses standard HTTP response codes to indicate the success or failure of requests. This guide helps you understand and handle the 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"]
}
}The errors object is only present on validation errors (422). Some endpoints also include a machine-readable error code — see Structured error codes below.
HTTP Status Codes
Success Codes (2xx)
| Code | Description |
|---|---|
| 200 | OK - Request succeeded |
| 201 | Created - Resource created successfully |
| 202 | Accepted - Request queued for background processing |
Client Error Codes (4xx)
| Code | Description |
|---|---|
| 400 | Bad Request - A business rule failed (e.g., vacancy no longer accepting applications) |
| 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 |
Common Error Scenarios
Authentication Errors
Missing or Invalid API Key (401)
{
"message": "Unauthenticated."
}You get the same response whether the key is missing, mistyped, or revoked.
Resolution: Include a valid API key in the Authorization header:
Authorization: Bearer YOUR_API_KEYIf the header is set, verify the key is correct and hasn't been revoked under Settings → API Keys.
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 under Settings → API Keys, or ask your administrator to.
Available Scopes:
| Scope | Access |
|---|---|
vacancies:read | View published vacancies and facets |
vacancies:write | Report canonical vacancy URLs back to Recruitsome |
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.
Validation Errors
Invalid Query Parameters (422)
{
"message": "The given data was invalid.",
"errors": {
"per_page": ["The per page field must not be greater than 100."],
"language": ["The language field must be 2 characters."]
}
}Resolution: Check the errors object for specific field issues.
Invalid Filter Values (422)
{
"message": "The given data was invalid.",
"errors": {
"location_id": ["The selected location id is invalid."]
}
}Canonical URL Host Not Allowed (422)
POST /vacancies/{slug}/canonical-url only accepts URLs on your own career website domain:
{
"message": "The given data was invalid.",
"errors": {
"url": ["The URL host must match your configured career website domain."]
}
}Resolution: Report the URL exactly as it appears on your career website. The host must match the career website URL configured in Recruitsome (or one of your own domains).
Resource Errors
Resource Not Found (404)
{
"message": "Resource not found."
}Possible Causes:
- Invalid slug
- Vacancy is unpublished
- Vacancy is not available through the API channel
- Vacancy has expired
Rate Limiting
Rate Limit Exceeded (429)
{
"message": "Too Many Attempts."
}Response Headers:
Retry-After: 42
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705765200Resolution: Wait the number of seconds in Retry-After (or until the X-RateLimit-Reset timestamp), or implement exponential backoff.
Structured error codes
Some write endpoints return a machine-readable error code alongside the message, so your integration can branch on the cause instead of parsing text:
Vacancy Closed (400)
POST /applications when the vacancy is no longer accepting applications:
{
"message": "This vacancy is no longer accepting applications",
"error": "VACANCY_CLOSED"
}Vacancy Not Found (404)
POST /applications when the vacancy doesn't exist or isn't published:
{
"message": "Vacancy not found",
"error": "VACANCY_NOT_FOUND"
}Processing Failed (500)
POST /candidates when the resume couldn't be processed:
{
"message": "An unexpected error occurred while processing the resume.",
"error": "PROCESSING_FAILED"
}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();
}Debugging Tips
- Validate JSON: Ensure request bodies are valid JSON
- Test with cURL: Isolate issues by testing with simple cURL commands
- Check the headers: The rate limit headers tell you exactly how much room you have left
Getting Help
If you encounter persistent errors, contact [email protected] with:
- Your API key name (not the key itself)
- Request details (endpoint, parameters)
- The full error response and status code