Documentation Index
Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
Use this file to discover all available pages before exploring further.
StateSet API uses standard HTTP response codes and provides detailed error information to help you handle issues gracefully.
All errors follow a consistent JSON structure to make error handling predictable:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"type": "error_type",
"details": {
// Additional context-specific information
},
"request_id": "req_1NXWPnCo6bFb1KQto6C8OWvE",
"timestamp": "2024-01-15T10:30:00Z",
"documentation_url": "https://docs.stateset.com/errors/ERROR_CODE"
}
}
HTTP Status Codes
| Status Code | Meaning | Common Causes |
|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource successfully created |
| 202 | Accepted | Request accepted for async processing |
| 204 | No Content | Request succeeded with no response body |
| 400 | Bad Request | Invalid request parameters or malformed syntax |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Valid auth but insufficient permissions |
| 404 | Not Found | Resource doesn’t exist |
| 409 | Conflict | Resource conflict or duplicate |
| 422 | Unprocessable Entity | Valid syntax but semantic errors |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error - retry with backoff |
| 502 | Bad Gateway | Upstream service error |
| 503 | Service Unavailable | Temporary service outage |
Error Types and Codes
Authentication Errors (401)
| Error Code | Description | Resolution |
|---|
INVALID_API_KEY | API key is invalid or revoked | Check key in dashboard |
EXPIRED_API_KEY | API key has expired | Generate new API key |
MISSING_AUTH_HEADER | No Authorization header provided | Include Bearer token |
INVALID_TOKEN_FORMAT | Token format is incorrect | Use Bearer sk_... format |
INACTIVE_ACCOUNT | Account is suspended or inactive | Contact support |
Authorization Errors (403)
| Error Code | Description | Resolution |
|---|
INSUFFICIENT_PERMISSIONS | API key lacks required permissions | Use key with proper scopes |
RESOURCE_ACCESS_DENIED | Cannot access this specific resource | Check resource ownership |
PLAN_LIMIT_EXCEEDED | Feature not available on current plan | Upgrade plan |
IP_NOT_ALLOWED | Request from unauthorized IP | Add IP to allowlist |
Validation Errors (400/422)
| Error Code | Description | Resolution |
|---|
VALIDATION_ERROR | Request validation failed | Check field requirements |
MISSING_REQUIRED_FIELD | Required field not provided | Include all required fields |
INVALID_FIELD_VALUE | Field value doesn’t meet requirements | Validate field format |
INVALID_ENUM_VALUE | Value not in allowed enum list | Use accepted values |
FIELD_TOO_LONG | Field exceeds maximum length | Truncate field value |
INVALID_DATE_FORMAT | Date format incorrect | Use ISO 8601 format |
Resource Errors (404/409)
| Error Code | Description | Resolution |
|---|
RESOURCE_NOT_FOUND | Requested resource doesn’t exist | Verify resource ID |
RESOURCE_ALREADY_EXISTS | Duplicate resource creation attempt | Use existing resource |
RESOURCE_LOCKED | Resource is locked for editing | Wait and retry |
RESOURCE_ARCHIVED | Resource has been archived | Unarchive or use different resource |
PARENT_NOT_FOUND | Parent resource doesn’t exist | Create parent first |
Business Logic Errors (422)
| Error Code | Description | Resolution |
|---|
INSUFFICIENT_INVENTORY | Not enough inventory available | Reduce quantity or check stock |
PAYMENT_FAILED | Payment processing failed | Verify payment details |
INVALID_STATE_TRANSITION | Invalid status change | Check allowed transitions |
OUTSIDE_RETURN_WINDOW | Return period expired | Check return policy |
DUPLICATE_REQUEST | Duplicate request detected | Use idempotency key |
Rate Limiting Errors (429)
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded",
"type": "rate_limit_error",
"details": {
"limit": 100,
"remaining": 0,
"reset_at": "2024-01-15T10:35:00Z",
"retry_after": 300
}
}
}
Error Handling Best Practices
1. Implement Exponential Backoff
class APIClient {
async requestWithRetry(url, options, maxRetries = 3) {
let lastError;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('X-RateLimit-Retry-After');
const delay = retryAfter
? parseInt(retryAfter) * 1000
: Math.min(1000 * Math.pow(2, attempt), 32000);
if (attempt < maxRetries) {
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
}
if (!response.ok) {
const error = await response.json();
throw new APIError(error);
}
return response.json();
} catch (error) {
lastError = error;
if (attempt < maxRetries && this.isRetryable(error)) {
const delay = Math.min(1000 * Math.pow(2, attempt), 32000);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
throw lastError;
}
isRetryable(error) {
const retryableCodes = [429, 500, 502, 503, 504];
return error.status && retryableCodes.includes(error.status);
}
}
2. Handle Specific Error Types
class ErrorHandler {
handle(error) {
switch (error.code) {
case 'INVALID_API_KEY':
// Refresh API key or prompt for new one
return this.refreshApiKey();
case 'INSUFFICIENT_PERMISSIONS':
// Inform user about permission requirements
return this.showPermissionError(error.details);
case 'VALIDATION_ERROR':
// Show field-specific errors
return this.showValidationErrors(error.details);
case 'RATE_LIMITED':
// Implement backoff and queue
return this.queueRequest(error.details.retry_after);
case 'INSUFFICIENT_INVENTORY':
// Update UI with available quantity
return this.updateInventory(error.details);
default:
// Generic error handling
return this.showGenericError(error.message);
}
}
}
3. Implement Circuit Breaker Pattern
class CircuitBreaker {
constructor(threshold = 5, timeout = 60000) {
this.failureCount = 0;
this.failureThreshold = threshold;
this.timeout = timeout;
this.state = 'CLOSED';
this.nextAttempt = Date.now();
}
async call(fn) {
if (this.state === 'OPEN') {
if (Date.now() < this.nextAttempt) {
throw new Error('Circuit breaker is OPEN');
}
this.state = 'HALF_OPEN';
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failureCount++;
if (this.failureCount >= this.failureThreshold) {
this.state = 'OPEN';
this.nextAttempt = Date.now() + this.timeout;
}
}
}
4. Log and Monitor Errors
class ErrorLogger {
log(error, context) {
const errorData = {
timestamp: new Date().toISOString(),
request_id: error.request_id,
error_code: error.code,
message: error.message,
context: {
user_id: context.userId,
endpoint: context.endpoint,
method: context.method,
...context
},
stack_trace: error.stack
};
// Send to logging service
logger.error(errorData);
// Track in analytics
analytics.track('API_ERROR', errorData);
// Alert on critical errors
if (this.isCritical(error)) {
alerting.notify(errorData);
}
}
isCritical(error) {
const criticalCodes = [
'PAYMENT_FAILED',
'SERVICE_UNAVAILABLE',
'DATABASE_ERROR'
];
return criticalCodes.includes(error.code);
}
}
Error Recovery Strategies
Idempotency for Safe Retries
// Use idempotency keys to safely retry requests
const createOrder = async (orderData) => {
const idempotencyKey = `order-${uuidv4()}`;
try {
return await api.post('/orders', orderData, {
headers: {
'Idempotency-Key': idempotencyKey
}
});
} catch (error) {
if (error.code === 'DUPLICATE_REQUEST') {
// Return existing order from previous request
return error.details.existing_resource;
}
throw error;
}
};
Graceful Degradation
class ResilientClient {
async getProductWithFallback(productId) {
try {
// Try primary API
return await this.api.get(`/products/${productId}`);
} catch (error) {
if (error.code === 'SERVICE_UNAVAILABLE') {
// Fall back to cache
const cached = await this.cache.get(`product:${productId}`);
if (cached) {
return { ...cached, from_cache: true };
}
// Fall back to secondary service
return await this.secondaryApi.get(`/products/${productId}`);
}
throw error;
}
}
}
Common Error Scenarios
Handling Validation Errors
// Request
POST /v1/orders
{
"customer_email": "invalid-email",
"items": []
}
// Response (422)
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"type": "validation_error",
"details": {
"errors": [
{
"field": "customer_email",
"message": "Invalid email format",
"expected": "valid email address"
},
{
"field": "items",
"message": "At least one item is required",
"expected": "non-empty array"
}
]
},
"request_id": "req_abc123"
}
}
Handling Resource Conflicts
// Request
POST /v1/customers
{
"email": "existing@example.com"
}
// Response (409)
{
"error": {
"code": "RESOURCE_ALREADY_EXISTS",
"message": "Customer with this email already exists",
"type": "conflict_error",
"details": {
"existing_id": "cus_123abc",
"field": "email",
"value": "existing@example.com"
},
"request_id": "req_def456"
}
}
Error Webhooks
Configure error webhooks to receive notifications for critical failures:
{
"event": "api.error",
"created": "2024-01-15T10:30:00Z",
"data": {
"error_code": "PAYMENT_FAILED",
"request_id": "req_xyz789",
"customer_id": "cus_123",
"order_id": "ord_456",
"amount": 9999,
"currency": "usd"
}
}
SDK Error Handling
Our SDKs provide built-in error handling:
try {
const order = await stateset.orders.create({
customer_email: 'customer@example.com',
items: [...]
});
} catch (error) {
if (error.code === 'INSUFFICIENT_INVENTORY') {
// Handle inventory shortage
const available = error.details.available_items;
console.log(`Only ${available} items available`);
} else if (error.code === 'VALIDATION_ERROR') {
// Handle validation errors
error.details.errors.forEach(err => {
console.log(`${err.field}: ${err.message}`);
});
} else {
// Generic error handling
console.error('Unexpected error:', error.message);
}
}
Testing Error Scenarios
Use test mode to simulate error conditions:
# Trigger specific error in test mode
curl -X POST https://api.sandbox.stateset.com/v1/orders \
-H "Authorization: Bearer sk_test_..." \
-H "X-Test-Error-Code: INSUFFICIENT_INVENTORY" \
-d '{...}'
Support
If you encounter persistent errors or need help with error handling:
Related: Rate Limiting | Authentication | Webhooks