StateSet uses conventional HTTP response codes and provides detailed error messages to help you quickly identify and resolve issues.

🚨 Error Response Format

All errors follow a consistent JSON structure:
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_missing",
    "message": "The 'amount' parameter is required but was not provided",
    "param": "amount",
    "doc_url": "https://docs.stateset.com/errors/parameter_missing",
    "request_id": "req_1234567890abcdef"
  }
}

Error Object Fields

FieldTypeDescription
typestringThe type of error returned
codestringA short string identifying the error
messagestringA human-readable message providing details
paramstringThe parameter related to the error (if applicable)
doc_urlstringLink to relevant documentation
request_idstringUnique identifier for this request

📊 HTTP Status Codes

CodeMeaningDescription
200OKRequest succeeded
201CreatedResource successfully created
202AcceptedRequest accepted for processing
204No ContentRequest succeeded with no response body

🔍 Error Types

Authentication Errors

Occur when API keys are missing, invalid, or lack permissions.
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The provided API key is invalid",
    "request_id": "req_abc123"
  }
}

Invalid Request Errors

Occur when request parameters are invalid or missing.
{
  "error": {
    "type": "invalid_request_error",
    "code": "parameter_invalid",
    "message": "Amount must be a positive number",
    "param": "amount",
    "request_id": "req_def456"
  }
}

Rate Limit Errors

Occur when you exceed API rate limits.
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after 60 seconds",
    "request_id": "req_ghi789"
  }
}
Response headers include:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 60

API Errors

Occur due to problems on StateSet’s servers.
{
  "error": {
    "type": "api_error",
    "code": "internal_server_error",
    "message": "An unexpected error occurred. Please try again",
    "request_id": "req_jkl012"
  }
}

💻 Error Handling Examples

const { StateSet } = require('@stateset/sdk');

const stateset = new StateSet({
  apiKey: process.env.STATESET_API_KEY
});

async function makePayment(amount, recipient) {
  try {
    const payment = await stateset.payments.create({
      amount,
      recipient,
      currency: 'ssusd'
    });
    return payment;
  } catch (error) {
    // Handle different error types
    switch (error.type) {
      case 'authentication_error':
        console.error('Authentication failed:', error.message);
        // Refresh API key or prompt for authentication
        break;
        
      case 'invalid_request_error':
        console.error('Invalid request:', error.message);
        if (error.param) {
          console.error('Problem with parameter:', error.param);
        }
        break;
        
      case 'rate_limit_error':
        console.error('Rate limit hit, retrying after delay...');
        const retryAfter = error.headers?.['retry-after'] || 60;
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        return makePayment(amount, recipient); // Retry
        
      case 'api_error':
        console.error('StateSet API error:', error.message);
        // Log to monitoring service
        break;
        
      default:
        console.error('Unknown error:', error);
    }
    
    throw error;
  }
}

🔄 Retry Strategy

Implement exponential backoff with jitter for transient errors:
async function retryWithBackoff(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      // Don't retry client errors (except rate limits)
      if (error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429) {
        throw error;
      }
      
      if (i === maxRetries - 1) throw error;
      
      // Exponential backoff with jitter
      const delay = Math.min(1000 * Math.pow(2, i) + Math.random() * 1000, 10000);
      console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Usage
const payment = await retryWithBackoff(() => 
  stateset.payments.create({ amount: 100, recipient: 'stateset1abc...' })
);

🛡️ Idempotency

Prevent duplicate operations using idempotency keys:
const payment = await stateset.payments.create({
  amount: 100,
  recipient: 'stateset1abc...',
  idempotency_key: 'unique-operation-key-123'
});

// Safe to retry - will return the same result
const samePayment = await stateset.payments.create({
  amount: 100,
  recipient: 'stateset1abc...',
  idempotency_key: 'unique-operation-key-123'
});

📈 Common Error Scenarios

Insufficient Funds

{
  "error": {
    "type": "invalid_request_error",
    "code": "insufficient_funds",
    "message": "Account has insufficient funds for this transaction",
    "param": "amount",
    "available_balance": "50.00",
    "requested_amount": "100.00",
    "currency": "ssusd"
  }
}

Invalid Address

{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_address",
    "message": "The recipient address is not a valid StateSet address",
    "param": "recipient",
    "provided_value": "invalid-address"
  }
}

Compliance Block

{
  "error": {
    "type": "compliance_error",
    "code": "transaction_blocked",
    "message": "This transaction cannot be processed due to compliance restrictions",
    "compliance_reason": "sanctions_screening",
    "request_id": "req_xyz789"
  }
}

🔍 Debugging Tips

1. Use Request IDs

Always log the request_id for support inquiries:
try {
  const result = await stateset.someMethod();
} catch (error) {
  console.error(`Request failed: ${error.request_id}`);
  // Include request_id in bug reports
}

2. Enable Debug Mode

Get detailed request/response logs:
const stateset = new StateSet({
  apiKey: process.env.STATESET_API_KEY,
  debug: true // Logs all requests/responses
});

3. Check Status Page

Monitor API health at status.stateset.com

4. Use Test Mode

Test error scenarios safely:
// Force specific errors in test mode
const payment = await stateset.payments.create({
  amount: 100,
  recipient: 'stateset1_test_insufficient_funds', // Special test address
  currency: 'ssusd'
});

📊 Error Monitoring

Set up proper error tracking:
// Example with Sentry
import * as Sentry from '@sentry/node';

async function trackError(error) {
  Sentry.captureException(error, {
    tags: {
      error_type: error.type,
      error_code: error.code,
      request_id: error.request_id
    },
    extra: {
      param: error.param,
      api_version: 'v1'
    }
  });
}

🆘 Getting Help