Skip to main content

Error Response Format

All API errors return a consistent JSON structure:
{
  "status_code": 400,
  "message": "Bad Request",
  "error": "Detailed error description",
  "errors": ["field: validation message"]  // Optional, for validation errors
}
FieldTypeDescription
status_codenumberHTTP status code
messagestringHTTP status message
errorstringHuman-readable error description
errorsstring[]Array of validation errors (when applicable)

HTTP Status Codes

Success Codes

CodeDescription
200 OKRequest succeeded
201 CreatedResource created successfully
204 No ContentRequest succeeded with no response body

Client Error Codes

CodeDescriptionCommon Causes
400 Bad RequestInvalid requestValidation errors, malformed JSON
401 UnauthorizedAuthentication failedMissing or invalid API key
403 ForbiddenAccess deniedInsufficient permissions
404 Not FoundResource not foundInvalid ID or deleted resource
409 ConflictResource conflictDuplicate entry or state conflict
422 Unprocessable EntityBusiness logic errorInsufficient balance, expired payment
429 Too Many RequestsRate limit exceededSlow down requests

Server Error Codes

CodeDescriptionAction
500 Internal Server ErrorServer errorRetry with backoff
502 Bad GatewayUpstream errorRetry with backoff
503 Service UnavailableService downCheck status page

Common Error Scenarios

Validation Errors

When request validation fails, you’ll receive a 400 response with details:
{
  "status_code": 400,
  "message": "Bad Request",
  "error": "Validation failed",
  "errors": [
    "amount: must be a positive number",
    "currency_code: must be one of [USDC]"
  ]
}

Authentication Errors

Missing or invalid API key returns 401:
{
  "status_code": 401,
  "message": "Unauthorized",
  "error": "Invalid or missing API key"
}

Resource Not Found

When a resource doesn’t exist:
{
  "status_code": 404,
  "message": "Not Found",
  "error": "Payment not found"
}

Insufficient Balance

When attempting a payment without sufficient funds:
{
  "status_code": 422,
  "message": "Unprocessable Entity",
  "error": "Insufficient balance. Available: 50.00 USDC, Required: 100.00 USDC"
}

Payment Already Processed

When trying to notify for an already processed payment:
{
  "status_code": 400,
  "message": "Bad Request",
  "error": "Payment has already been processed"
}

Error Handling Best Practices

1. Always Check Status Codes

const response = await fetch('https://api-sandbox.superbank.com/v1/payments', {
  method: 'POST',
  headers: {
    'X-Api-Key': apiKey,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(paymentData),
});

if (!response.ok) {
  const error = await response.json();

  switch (response.status) {
    case 400:
      console.error('Validation error:', error.errors);
      break;
    case 401:
      console.error('Authentication failed - check your API key');
      break;
    case 422:
      console.error('Business error:', error.error);
      break;
    default:
      console.error('Unexpected error:', error);
  }
}

2. Implement Retry Logic

For transient errors (5xx), implement exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status < 500) {
      return response;
    }

    // Exponential backoff: 1s, 2s, 4s
    const delay = Math.pow(2, attempt) * 1000;
    await new Promise(resolve => setTimeout(resolve, delay));
  }

  throw new Error('Max retries exceeded');
}

3. Handle Rate Limits

If you receive a 429 response, respect the Retry-After header:
if (response.status === 429) {
  const retryAfter = response.headers.get('Retry-After');
  const delay = retryAfter ? parseInt(retryAfter) * 1000 : 60000;
  await new Promise(resolve => setTimeout(resolve, delay));
  // Retry the request
}

Idempotency

For payment creation, use the idempotency_key field to safely retry requests:
{
  "type": "LIQUIDITY",
  "amount": 100.00,
  "currency_code": "USDC",
  "chain": "SOLANA",
  "destination_wallet": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  "idempotency_key": "order-12345"
}
If you send the same request with the same idempotency key, you’ll receive the original payment instead of creating a duplicate.

Next Steps