Error Handling
The FYATU API uses conventional HTTP response codes and returns detailed error messages with machine-readable error codes to help you handle errors programmatically.
All API responses follow a consistent format:
Success Response
Error Response
{
"success" : true ,
"status" : 200 ,
"message" : "Operation completed successfully" ,
"data" : {
// Response data here
},
"meta" : {
"requestId" : "req_7af4d2b8e91c35fa" ,
"timestamp" : "2026-01-05T10:30:00+00:00"
}
}
Always include the requestId from the meta object when contacting support — it helps us trace your request through our systems.
HTTP Status Codes
Code Status Description 200OK Request succeeded 201Created Resource created successfully 400Bad Request Invalid request parameters or validation failed 401Unauthorized Authentication failed or token expired 402Payment Required Insufficient wallet balance 403Forbidden Access denied (scope mismatch or resource not owned) 404Not Found Resource doesn’t exist 409Conflict Duplicate reference or conflicting operation 422Unprocessable Entity Request understood but cannot be processed 429Too Many Requests Rate limit exceeded 500Server Error Something went wrong on our end
Error Codes
Each error response includes a machine-readable code field:
Code HTTP Description AUTH_TOKEN_MISSING401 No authorization token provided AUTH_TOKEN_INVALID401 Token is malformed, expired, or revoked AUTH_INVALID_CREDENTIALS401 App ID or secret key is incorrect AUTH_SCOPE_DENIED403 Token doesn’t have the required scope for this endpoint VALIDATION_ERROR400 One or more request fields failed validation RESOURCE_NOT_FOUND404 The requested resource does not exist INSUFFICIENT_BALANCE402 Wallet balance is too low for this operation DUPLICATE_REFERENCE409 The externalReference has already been used RATE_LIMIT_EXCEEDED429 Too many requests — slow down INTERNAL_ERROR500 Unexpected server error
Common Error Scenarios
Authentication Errors (401)
{
"success" : false ,
"status" : 401 ,
"message" : "Authorization token is required" ,
"error" : { "code" : "AUTH_TOKEN_MISSING" }
}
Solution : Include the Authorization: Bearer {token} header in your request.
{
"success" : false ,
"status" : 401 ,
"message" : "Invalid or expired token" ,
"error" : { "code" : "AUTH_TOKEN_INVALID" }
}
Solution : Refresh your token via POST /v3/auth/refresh or request a new one via POST /v3/auth/token.
{
"success" : false ,
"status" : 403 ,
"message" : "Access denied. Required scope: cards:write" ,
"error" : { "code" : "AUTH_SCOPE_DENIED" }
}
Solution : Your app type doesn’t have access to this endpoint. A Collection App cannot access Card endpoints and vice versa.
Validation Errors (400)
{
"success" : false ,
"status" : 400 ,
"message" : "Validation failed" ,
"error" : {
"code" : "VALIDATION_ERROR" ,
"details" : [
{ "field" : "amount" , "message" : "Amount must be greater than 0" },
{ "field" : "email" , "message" : "The email field must contain a valid email address" }
]
}
}
Solution : Check the details array for specific field requirements and fix the request payload.
Insufficient Balance (402)
{
"success" : false ,
"status" : 402 ,
"message" : "Insufficient balance. Required: $105.00, Available: $50.00" ,
"error" : { "code" : "INSUFFICIENT_BALANCE" }
}
Solution : Fund your business wallet before retrying. The required amount includes applicable fees.
Resource Not Found (404)
{
"success" : false ,
"status" : 404 ,
"message" : "Card not found" ,
"error" : { "code" : "RESOURCE_NOT_FOUND" }
}
Solution : Verify the resource ID exists and belongs to your app.
Duplicate Reference (409)
{
"success" : false ,
"status" : 409 ,
"message" : "A collection with this external reference already exists" ,
"error" : { "code" : "DUPLICATE_REFERENCE" }
}
Solution : Use a unique externalReference for each new operation.
Rate Limiting (429)
{
"success" : false ,
"status" : 429 ,
"message" : "Rate limit exceeded. Try again in 60 seconds." ,
"error" : { "code" : "RATE_LIMIT_EXCEEDED" }
}
Solution : Implement exponential backoff in your retry logic.
Error Handling Best Practices
1. Always Check the Response
const response = await fetch ( 'https://api.fyatu.com/api/v3/cards' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ accessToken } ` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ( cardData )
});
const result = await response . json ();
if ( ! result . success ) {
console . error ( `API Error [ ${ result . error ?. code } ]: ${ result . message } ` );
console . error ( 'Request ID:' , result . meta ?. requestId );
return ;
}
// Process successful response
console . log ( 'Card created:' , result . data . cardId );
2. Handle Specific Error Codes
async function createCollection ( data ) {
const result = await fyatuRequest ( 'POST' , '/v3/collections' , data );
if ( result . success ) {
return { ok: true , collection: result . data };
}
switch ( result . error ?. code ) {
case 'AUTH_TOKEN_INVALID' :
// Token expired — refresh and retry
await refreshToken ();
return createCollection ( data );
case 'VALIDATION_ERROR' :
return { ok: false , fields: result . error . details };
case 'INSUFFICIENT_BALANCE' :
return { ok: false , error: 'Please fund your wallet' };
case 'DUPLICATE_REFERENCE' :
return { ok: false , error: 'This order was already submitted' };
case 'RATE_LIMIT_EXCEEDED' :
await sleep ( 60000 );
return createCollection ( data );
default :
return { ok: false , error: result . message };
}
}
3. Implement Retry with Backoff
async function requestWithRetry ( method , endpoint , data , maxRetries = 3 ) {
for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
const result = await fyatuRequest ( method , endpoint , data );
if ( result . success ) return result ;
// Only retry on rate limits and server errors
if ( result . status === 429 || result . status >= 500 ) {
const waitMs = Math . pow ( 2 , attempt ) * 1000 ;
console . log ( `Retry ${ attempt } / ${ maxRetries } in ${ waitMs } ms...` );
await new Promise ( r => setTimeout ( r , waitMs ));
continue ;
}
// Don't retry client errors (400, 401, 403, 404, 409)
return result ;
}
throw new Error ( `Failed after ${ maxRetries } retries` );
}
4. Log Errors for Debugging
function logApiError ( endpoint , result ) {
console . error ({
timestamp: new Date (). toISOString (),
endpoint ,
status: result . status ,
code: result . error ?. code ,
message: result . message ,
requestId: result . meta ?. requestId ,
// Never log tokens, card numbers, or secrets
});
}
Idempotency
For operations that create resources, use the externalReference field to prevent duplicates:
// Use a deterministic reference for each operation
const reference = `order_ ${ orderId } _ ${ customerId } ` ;
const result = await fyatuRequest ( 'POST' , '/v3/collections' , {
amount: 25.00 ,
currency: 'USD' ,
externalReference: reference ,
description: 'Premium subscription'
});
// If you retry with the same externalReference,
// the API returns 409 instead of creating a duplicate
This prevents duplicate charges if your request times out and you retry.
Rate Limits
Endpoint Category Rate Limit Authentication (/v3/auth/*) 10 requests per minute Read endpoints (GET) 120 requests per minute Write endpoints (POST/PUT/DELETE) 60 requests per minute
Exceeding rate limits will result in 429 Too Many Requests. Implement exponential backoff in your retry logic.