Error Handling
The HeadshotPro API uses conventional HTTP status codes and returns consistent error objects.
Error Response Format
All errors return a JSON object with the following structure:
{
"success": false,
"error": "Human-readable error message",
"code": "MACHINE_READABLE_CODE"
}
HTTP Status Codes
| Status | Description |
|---|---|
200 | Success |
400 | Bad Request - Invalid parameters or request body |
401 | Unauthorized - Invalid or missing API key |
402 | Payment Required - Insufficient credits |
403 | Forbidden - Feature not enabled or permission denied |
404 | Not Found - Resource doesn't exist |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error - Something went wrong on our end |
Error Codes
Authentication Errors
| Code | HTTP Status | Description |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid API key |
FORBIDDEN | 403 | API key valid but lacks permission |
Validation Errors
| Code | HTTP Status | Description |
|---|---|---|
INVALID_REQUEST | 400 | Missing required field or invalid format |
INVALID_EMAIL | 400 | Email address format is invalid |
Resource Errors
| Code | HTTP Status | Description |
|---|---|---|
NOT_FOUND | 404 | Requested resource doesn't exist |
ALREADY_EXISTS | 400 | Resource already exists (duplicate) |
Business Logic Errors
| Code | HTTP Status | Description |
|---|---|---|
INSUFFICIENT_CREDITS | 402 | Organization has insufficient credits |
ALREADY_DELETED | 400 | Resource was already deleted |
Rate Limiting
| Code | HTTP Status | Description |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Too many requests in time window |
INVITE_LIMIT_EXCEEDED | 429 | Too many pending invites (see Invite Limits) |
Common Error Scenarios
Invalid API Key
{
"success": false,
"error": "Invalid API key",
"code": "UNAUTHORIZED"
}
Solution: Check that your API key is correct and included in the Authorization header.
Insufficient Credits
{
"success": false,
"error": "Insufficient credits",
"code": "INSUFFICIENT_CREDITS"
}
Solution: Purchase more credits or check your current balance with GET /organization/credits.
User Already Exists
{
"success": false,
"error": "A user with this email already exists. You can solve this by appending a + to the email address, i.e. user+1@example.com",
"code": "INVALID_REQUEST"
}
Solution: Use email aliasing (e.g., user+timestamp@example.com) or check if the user already has a model.
Team Not Found
{
"success": false,
"error": "Team not found",
"code": "NOT_FOUND"
}
Solution: Verify the team ID by calling GET /organization/teams.
Whitelabel Not Enabled
{
"success": false,
"error": "Whitelabel feature not enabled",
"code": "FORBIDDEN"
}
Solution: Contact sales@headshotpro.com to enable whitelabel for your organization.
Error Handling Best Practices
1. Always Check success Field
const response = await fetch(url, options);
const data = await response.json();
if (!data.success) {
console.error(`API Error: ${data.code} - ${data.error}`);
// Handle error appropriately
return;
}
// Process successful response
2. Handle Specific Error Codes
if (!data.success) {
switch (data.code) {
case 'INSUFFICIENT_CREDITS':
notifyAdmin('Credits running low');
break;
case 'RATE_LIMIT_EXCEEDED':
await delay(60000); // Wait 1 minute
return retry(request);
case 'NOT_FOUND':
return null; // Resource doesn't exist
default:
throw new Error(data.error);
}
}
3. Implement Retry Logic
async function apiRequest(url, options, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('X-RateLimit-Reset');
const waitTime = new Date(retryAfter) - new Date();
await delay(waitTime);
continue;
}
if (response.status >= 500) {
await delay(1000 * attempt); // Exponential backoff
continue;
}
return response.json();
}
throw new Error('Max retries exceeded');
}
4. Log Errors for Debugging
if (!data.success) {
console.error({
timestamp: new Date().toISOString(),
endpoint: url,
method: options.method,
status: response.status,
code: data.code,
error: data.error
});
}