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 errordetails(optional): Array of specific error details, typically for validation errors
Error Codes Reference
Authentication Errors (401)
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
UNAUTHORIZED | 401 | No API key provided | Include Authorization: Bearer YOUR_API_KEY header |
INVALID_API_KEY | 401 | API key is malformed or doesn’t exist | Verify your API key is correct |
API_KEY_REVOKED | 401 | API key has been revoked | Generate a new API key in settings |
API_KEY_EXPIRED | 401 | API key has expired | Generate a new API key in settings |
Permission Errors (403)
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | 403 | API key doesn’t have required scopes | Check your API key scopes in settings |
FEATURE_NOT_ENABLED | 403 | Feature requires an add-on or plan upgrade | Enable the required add-on or upgrade your plan |
Rate Limiting Errors (429)
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Too many requests in a short time | Wait for the time specified in Retry-After header |
DAILY_LIMIT_EXCEEDED | 429 | Daily API quota exhausted | Wait until midnight UTC or upgrade your plan |
Rate Limit Headers:
X-RateLimit-Limit: 100X-RateLimit-Remaining: 42X-RateLimit-Reset: 1702934400Retry-After: 3600Validation Errors (400)
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
VALIDATION_ERROR | 400 | Request data failed validation | Check error.details for specific field errors |
INVALID_REQUEST | 400 | Request is malformed or missing required data | Verify request format and required fields |
MISSING_REQUIRED_FIELD | 400 | Required field is missing | Check 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)
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
NOT_FOUND | 404 | Resource doesn’t exist or was deleted | Verify the resource ID |
ALREADY_EXISTS | 409 | Resource already exists (e.g., duplicate email) | Use a different unique identifier |
CONFLICT | 409 | Request conflicts with current state | Check resource state and retry |
PLAN_LIMIT_EXCEEDED | 403 | Plan limits reached (e.g., max contacts) | Upgrade your plan or delete unused resources |
Server Errors (500, 503)
| Code | HTTP Status | Description | Solution |
|---|---|---|---|
INTERNAL_ERROR | 500 | Unexpected server error | Retry the request; contact support if it persists |
SERVICE_UNAVAILABLE | 503 | Service temporarily unavailable | Retry 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 formconst 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:
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: 100X-RateLimit-Remaining: 0X-RateLimit-Reset: 1702935000Retry-After: 60Scenario 3: Resource Not Found
Request:
GET /v1/contacts/00000000-0000-0000-0000-000000000000Response (404):
{ "error": { "code": "NOT_FOUND", "message": "Contact not found" }}Retry Strategies
When to Retry
| HTTP Status | Should Retry? | Strategy |
|---|---|---|
| 429 (Rate Limit) | Yes | Use Retry-After header |
| 500 (Server Error) | Yes | Exponential backoff |
| 503 (Service Unavailable) | Yes | Exponential backoff |
| 401 (Unauthorized) | No | Fix authentication |
| 400 (Validation Error) | No | Fix request data |
| 404 (Not Found) | No | Resource doesn’t exist |
Recommended Retry Logic
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
curl -X GET "https://api.sellercockpit.com/v1/contacts" \ -H "Authorization: Bearer invalid_key"Test Validation Errors
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
# Make 101 requests rapidly to trigger rate limitfor i in {1..101}; do curl -X GET "https://api.sellercockpit.com/v1/contacts" \ -H "Authorization: Bearer YOUR_API_KEY"doneNeed Help?
If you encounter errors not covered in this guide:
- Check API Status: status.sellercockpit.com
- Contact Support: support@sellercockpit.com
- Developer Forum: forum.sellercockpit.com
Include the error code, full error response, and request details when reporting issues.