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.
All API responses follow a consistent format:
Success Response
Error Response
{
"status" : "success" ,
"statusCode" : 200 ,
"errors" : false ,
"message" : "Operation completed successfully" ,
"data" : {
// Response data here
}
}
HTTP Status Codes
Code Status Description 200OK Request succeeded 400Bad Request Invalid request parameters 401Unauthorized Authentication failed 402Payment Required Insufficient balance 403Forbidden Access denied (e.g., cardholder not active) 404Not Found Resource doesn’t exist 422Unprocessable Entity Request couldn’t be processed 429Too Many Requests Rate limit exceeded 500Server Error Something went wrong on our end
Common Error Scenarios
Authentication Errors (401)
{
"status" : "failed" ,
"statusCode" : 401 ,
"message" : "Unauthorized: Missing credentials"
}
Solution : Include both Business-ID and Authorization headers in your request.
{
"status" : "failed" ,
"statusCode" : 401 ,
"message" : "Invalid API Key"
}
Solution : Verify your API key is correct and hasn’t been revoked.
{
"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)
{
"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)
{
"status" : "failed" ,
"statusCode" : 400 ,
"message" : "This card is not active. Please activate it first"
}
{
"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.