Skip to main content
API v2 is deprecated. This version will be discontinued on December 31, 2026. Please migrate to API v3 for new features, improved security, and continued support.

Error Handling

The FYATU API uses conventional HTTP response codes and returns detailed error messages to help you understand what went wrong.

Response Format

All API responses follow a consistent format:
{
  "status": "success",
  "statusCode": 200,
  "errors": false,
  "message": "Operation completed successfully",
  "data": {
    // Response data here
  }
}

HTTP Status Codes

CodeStatusDescription
200OKRequest succeeded
400Bad RequestInvalid request parameters
401UnauthorizedAuthentication failed
402Payment RequiredInsufficient balance
403ForbiddenAccess denied (e.g., cardholder not active)
404Not FoundResource doesn’t exist
422Unprocessable EntityRequest couldn’t be processed
429Too Many RequestsRate limit exceeded
500Server ErrorSomething went wrong on our end

Common Error Scenarios

Authentication Errors (401)

Missing Credentials
{
  "status": "failed",
  "statusCode": 401,
  "message": "Unauthorized: Missing credentials"
}
Solution: Include both Business-ID and Authorization headers in your request.
Invalid API Key
{
  "status": "failed",
  "statusCode": 401,
  "message": "Invalid API Key"
}
Solution: Verify your API key is correct and hasn’t been revoked.
IP Not Authorized
{
  "status": "failed",
  "statusCode": 401,
  "message": "Access denied: IP not authorized"
}
Solution: Add your IP to the whitelist in the dashboard, or disable IP whitelisting.

Validation Errors (400)

Invalid Email
{
  "status": "failed",
  "statusCode": 400,
  "message": "The email field must contain a valid email address"
}
Multiple Validation Errors
{
  "status": "failed",
  "statusCode": 400,
  "message": "The firstName field is required & The phone field must be in E.164 format"
}
Solution: Check the error message for specific field requirements and fix the request payload.

Insufficient Balance (402)

{
  "status": "failed",
  "statusCode": 402,
  "message": "Insufficient balance. Required: $105.00"
}
Solution: Fund your business wallet before retrying the operation. The required amount includes fees.

Resource Not Found (404)

{
  "status": "failed",
  "statusCode": 404,
  "message": "No card found with ID: card_xyz789"
}
Solution: Verify the resource ID exists and belongs to your business.

Business Logic Errors (400/403)

Card Not Active
{
  "status": "failed",
  "statusCode": 400,
  "message": "This card is not active. Please activate it first"
}
Cardholder Not Active
{
  "status": "failed",
  "statusCode": 403,
  "message": "Cardholder is not active"
}
Solution: Check the resource status and take appropriate action (e.g., unfreeze card, activate cardholder).

Webhook Errors (422)

{
  "status": "failed",
  "statusCode": 422,
  "message": "URL did not return a successful response (expected HTTP 200, got 404)"
}
Solution: Ensure your webhook endpoint is accessible and returns HTTP 200.

Error Handling Best Practices

1. Always Check the Status

const response = await fetch('https://api.fyatu.com/api/v2/cards', {
  method: 'POST',
  headers: { /* ... */ },
  body: JSON.stringify(cardData)
});

const result = await response.json();

if (result.status === 'failed') {
  console.error('API Error:', result.message);
  // Handle the error appropriately
  return;
}

// Process successful response
console.log('Card created:', result.data.cardId);

2. Handle Specific Error Codes

async function createCard(cardData) {
  const response = await fyatuRequest('/cards', {
    method: 'POST',
    body: JSON.stringify(cardData)
  });

  const result = await response.json();

  switch (result.statusCode) {
    case 200:
      return { success: true, card: result.data };

    case 400:
      return { success: false, error: 'validation', message: result.message };

    case 401:
      // Re-authenticate or refresh token
      return { success: false, error: 'auth', message: 'Please re-authenticate' };

    case 402:
      return { success: false, error: 'balance', message: 'Insufficient funds' };

    case 404:
      return { success: false, error: 'not_found', message: result.message };

    case 429:
      // Implement retry with backoff
      return { success: false, error: 'rate_limit', retryAfter: 60 };

    default:
      return { success: false, error: 'unknown', message: result.message };
  }
}

3. Implement Retry Logic

async function requestWithRetry(endpoint, options, maxRetries = 3) {
  let lastError;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fyatuRequest(endpoint, options);
      const result = await response.json();

      if (result.statusCode === 429) {
        // Rate limited - wait and retry
        const waitTime = Math.pow(2, attempt) * 1000; // Exponential backoff
        await new Promise(resolve => setTimeout(resolve, waitTime));
        continue;
      }

      if (result.statusCode >= 500) {
        // Server error - retry
        const waitTime = Math.pow(2, attempt) * 1000;
        await new Promise(resolve => setTimeout(resolve, waitTime));
        continue;
      }

      return result;
    } catch (error) {
      lastError = error;
      if (attempt < maxRetries) {
        const waitTime = Math.pow(2, attempt) * 1000;
        await new Promise(resolve => setTimeout(resolve, waitTime));
      }
    }
  }

  throw lastError;
}

4. Log Errors for Debugging

function logApiError(endpoint, error, requestData) {
  console.error({
    timestamp: new Date().toISOString(),
    endpoint,
    statusCode: error.statusCode,
    message: error.message,
    requestId: error.requestId, // If provided
    // Don't log sensitive data like API keys or card numbers
    requestData: sanitize(requestData)
  });
}

Idempotency

For operations that create resources or modify state, consider implementing idempotency on your end:
// Generate a unique idempotency key
const idempotencyKey = `card_${userId}_${Date.now()}`;

// Store the key and check before retrying
if (await hasProcessed(idempotencyKey)) {
  return getPreviousResult(idempotencyKey);
}

const result = await createCard(cardData);
await storeResult(idempotencyKey, result);
This prevents duplicate card issuance if your request times out and you retry.