Skip to content

Error Codes

The SellerCockpit API uses standard HTTP status codes and returns detailed error information in a consistent JSON format. This guide covers all error codes, their meanings, and how to handle them in your application.

Error Response Format

All error responses follow this structure:

{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error description",
"details": [
{
"field": "field_name",
"message": "Specific error for this field",
"code": "VALIDATION_CODE"
}
]
}
}
  • code: Machine-readable error identifier (see table below)
  • message: Human-readable description of the error
  • details (optional): Array of specific error details, typically for validation errors

Error Codes Reference

Authentication Errors (401)

CodeHTTP StatusDescriptionSolution
UNAUTHORIZED401No API key providedInclude Authorization: Bearer YOUR_API_KEY header
INVALID_API_KEY401API key is malformed or doesn’t existVerify your API key is correct
API_KEY_REVOKED401API key has been revokedGenerate a new API key in settings
API_KEY_EXPIRED401API key has expiredGenerate a new API key in settings

Permission Errors (403)

CodeHTTP StatusDescriptionSolution
INSUFFICIENT_PERMISSIONS403API key doesn’t have required scopesCheck your API key scopes in settings
FEATURE_NOT_ENABLED403Feature requires an add-on or plan upgradeEnable the required add-on or upgrade your plan

Rate Limiting Errors (429)

CodeHTTP StatusDescriptionSolution
RATE_LIMIT_EXCEEDED429Too many requests in a short timeWait for the time specified in Retry-After header
DAILY_LIMIT_EXCEEDED429Daily API quota exhaustedWait until midnight UTC or upgrade your plan

Rate Limit Headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1702934400
Retry-After: 3600

Validation Errors (400)

CodeHTTP StatusDescriptionSolution
VALIDATION_ERROR400Request data failed validationCheck error.details for specific field errors
INVALID_REQUEST400Request is malformed or missing required dataVerify request format and required fields
MISSING_REQUIRED_FIELD400Required field is missingCheck API documentation for required fields

Example validation error:

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{
"field": "email",
"message": "Invalid email format",
"code": "INVALID_FORMAT"
},
{
"field": "name",
"message": "Name is required",
"code": "REQUIRED"
}
]
}
}

Resource Errors (404, 409)

CodeHTTP StatusDescriptionSolution
NOT_FOUND404Resource doesn’t exist or was deletedVerify the resource ID
ALREADY_EXISTS409Resource already exists (e.g., duplicate email)Use a different unique identifier
CONFLICT409Request conflicts with current stateCheck resource state and retry
PLAN_LIMIT_EXCEEDED403Plan limits reached (e.g., max contacts)Upgrade your plan or delete unused resources

Server Errors (500, 503)

CodeHTTP StatusDescriptionSolution
INTERNAL_ERROR500Unexpected server errorRetry the request; contact support if it persists
SERVICE_UNAVAILABLE503Service temporarily unavailableRetry with exponential backoff

Error Handling Best Practices

1. Check HTTP Status First

const response = await fetch('https://api.sellercockpit.com/v1/contacts', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
if (!response.ok) {
const error = await response.json();
console.error('API Error:', error.error.code, error.error.message);
// Handle specific errors
switch (error.error.code) {
case 'RATE_LIMIT_EXCEEDED':
// Wait and retry
break;
case 'VALIDATION_ERROR':
// Show validation errors to user
break;
default:
// Generic error handling
}
}

2. Handle Rate Limits Gracefully

async function apiRequestWithRetry(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. Retrying after ${retryAfter} seconds`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
return apiRequestWithRetry(url, options);
}
return response;
}

3. Implement Exponential Backoff for Server Errors

async function apiRequestWithBackoff(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
// Success
if (response.ok) {
return response;
}
// Don't retry client errors (4xx)
if (response.status < 500) {
return response;
}
// Exponential backoff for server errors (5xx)
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
console.log(`Server error. Retrying in ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
throw new Error('Max retries exceeded');
}

4. Parse Validation Errors

function parseValidationErrors(error) {
if (error.error.code === 'VALIDATION_ERROR' && error.error.details) {
return error.error.details.reduce((acc, detail) => {
acc[detail.field] = detail.message;
return acc;
}, {});
}
return {};
}
// Usage in a form
const response = await fetch('/v1/contacts', { /* ... */ });
if (!response.ok) {
const error = await response.json();
const fieldErrors = parseValidationErrors(error);
// Show errors next to form fields
Object.entries(fieldErrors).forEach(([field, message]) => {
showFieldError(field, message);
});
}

5. Log Errors for Debugging

async function apiRequest(url, options) {
try {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
// Log error details
console.error('API Error:', {
url,
status: response.status,
code: error.error.code,
message: error.error.message,
details: error.error.details,
timestamp: new Date().toISOString(),
});
// Send to error tracking service (Sentry, etc.)
trackError(error);
}
return response;
} catch (err) {
console.error('Network error:', err);
throw err;
}
}

Common Error Scenarios

Scenario 1: Creating a Contact with Invalid Email

Request:

Terminal window
POST /v1/contacts
{
"first_name": "John",
"last_name": "Doe",
"emails": [{ "email": "invalid-email", "is_primary": true }]
}

Response (400):

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{
"field": "emails[0].email",
"message": "Invalid email format",
"code": "INVALID_FORMAT"
}
]
}
}

Scenario 2: Rate Limit Exceeded

Response (429):

{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please wait before making more requests."
}
}

Headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1702935000
Retry-After: 60

Scenario 3: Resource Not Found

Request:

Terminal window
GET /v1/contacts/00000000-0000-0000-0000-000000000000

Response (404):

{
"error": {
"code": "NOT_FOUND",
"message": "Contact not found"
}
}

Retry Strategies

When to Retry

HTTP StatusShould Retry?Strategy
429 (Rate Limit)YesUse Retry-After header
500 (Server Error)YesExponential backoff
503 (Service Unavailable)YesExponential backoff
401 (Unauthorized)NoFix authentication
400 (Validation Error)NoFix request data
404 (Not Found)NoResource doesn’t exist
const RETRYABLE_CODES = ['INTERNAL_ERROR', 'SERVICE_UNAVAILABLE'];
const MAX_RETRIES = 3;
const BASE_DELAY = 1000; // 1 second
async function apiRequestWithRetry(url, options) {
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
const response = await fetch(url, options);
// Success
if (response.ok) {
return response;
}
// Rate limit - use Retry-After header
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
await sleep(retryAfter * 1000);
continue;
}
// Server error - exponential backoff
if (response.status >= 500) {
if (attempt < MAX_RETRIES) {
const delay = BASE_DELAY * Math.pow(2, attempt);
console.log(`Retry attempt ${attempt + 1}/${MAX_RETRIES} after ${delay}ms`);
await sleep(delay);
continue;
}
}
// Don't retry client errors
return response;
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

Testing Error Handling

Test Invalid API Key

Terminal window
curl -X GET "https://api.sellercockpit.com/v1/contacts" \
-H "Authorization: Bearer invalid_key"

Test Validation Errors

Terminal window
curl -X POST "https://api.sellercockpit.com/v1/contacts" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "",
"emails": [{ "email": "invalid" }]
}'

Test Rate Limiting

Terminal window
# Make 101 requests rapidly to trigger rate limit
for i in {1..101}; do
curl -X GET "https://api.sellercockpit.com/v1/contacts" \
-H "Authorization: Bearer YOUR_API_KEY"
done

Need Help?

If you encounter errors not covered in this guide:

Include the error code, full error response, and request details when reporting issues.