Error Response Format
All API errors follow a consistent format:
{
"success": false,
"error": "Human-readable error message",
"details": [
{
"field": "amount",
"message": "Must be a positive number"
}
]
}HTTP Status Codes
200OKRequest successful
201CreatedResource created successfully
400Bad RequestInvalid request data or validation error
401UnauthorizedMissing or invalid authentication
403ForbiddenNot authorized to access this resource
404Not FoundResource not found
429Too Many RequestsRate limit exceeded
500Internal ErrorServer error - please contact support
| Code | Status | Description |
|---|---|---|
200 | OK | Request successful |
201 | Created | Resource created successfully |
400 | Bad Request | Invalid request data or validation error |
401 | Unauthorized | Missing or invalid authentication |
403 | Forbidden | Not authorized to access this resource |
404 | Not Found | Resource not found |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Error | Server error - please contact support |
Common Errors
Validation Errors (400)
Invalid input dataRequest body doesn't match expected schema. Check the array for specific field errors.details
{
"success": false,
"error": "Invalid input data",
"details": [
{"path": ["amount"], "message": "Expected number, received string"},
{"path": ["token"], "message": "Invalid enum value. Expected 'USDC' | 'EURC'"}
]
}Invalid amountAmount must be between 0.01 and 1,000,000.
Invalid merchant addressThe doesn't match the merchant's wallet address.toAddress
Authentication Errors (401/403)
No token providedProtected endpoint requires authentication. Include or header.AuthorizationX-API-Key
Invalid or expired tokenJWT token has expired (15 min lifetime) or is malformed. Re-authenticate to get a new token.
Invalid API keyAPI key not found or has been revoked. Check that you're using the correct key.
Resource Errors (404)
Merchant not foundNo merchant exists with the given ID. Verify your .merchantId
Payment not foundNo payment exists with the given ID. Check the payment ID is correct.
Payment already existsA payment with this already exists. The API returns with the existing payment data. This prevents double-spend attacks.txHash200
API Error Codes
When an error occurs, the response includes a machine-readable field that you can use for programmatic error handling:code
{
"success": false,
"error": "Human-readable message",
"code": "RATE_LIMIT_EXCEEDED",
"retryAfter": 60
}General Error Codes
RATE_LIMIT_EXCEEDED429Rate limit exceeded for this endpoint
INVALID_UUID_FORMAT400ID parameter is not a valid UUID
MISSING_PARAMETER400A required parameter is missing
2FA_REQUIRED403Operation requires 2FA to be enabled
2FA_CODE_REQUIRED4002FA code was not provided
2FA_INVALID4012FA code is incorrect or expired
SELF_TRANSFER_NOT_ALLOWED400Cannot withdraw to your own Fivo wallet
INVALID_MERCHANT_ID400Merchant ID format is invalid
WEBHOOK_LIMIT_REACHED400Maximum webhooks per merchant reached
REFUND_WINDOW_EXPIRED400Refund window (180 days) has expired
REFUND_EXCEEDS_REMAINING400Amount exceeds refundable balance
PAYMENT_NOT_COMPLETED400Payment is not in completed status
NO_SOURCE_ADDRESS400Payment has no source address
REFUND_NOT_CANCELABLE400Refund is not in pending status
| Code | HTTP | Description |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Rate limit exceeded for this endpoint |
INVALID_UUID_FORMAT | 400 | ID parameter is not a valid UUID |
MISSING_PARAMETER | 400 | A required parameter is missing |
2FA_REQUIRED | 403 | Operation requires 2FA to be enabled |
2FA_CODE_REQUIRED | 400 | 2FA code was not provided |
2FA_INVALID | 401 | 2FA code is incorrect or expired |
SELF_TRANSFER_NOT_ALLOWED | 400 | Cannot withdraw to your own Fivo wallet |
INVALID_MERCHANT_ID | 400 | Merchant ID format is invalid |
WEBHOOK_LIMIT_REACHED | 400 | Maximum webhooks per merchant reached |
REFUND_WINDOW_EXPIRED | 400 | Refund window (180 days) has expired |
REFUND_EXCEEDS_REMAINING | 400 | Amount exceeds refundable balance |
PAYMENT_NOT_COMPLETED | 400 | Payment is not in completed status |
NO_SOURCE_ADDRESS | 400 | Payment has no source address |
REFUND_NOT_CANCELABLE | 400 | Refund is not in pending status |
Blockchain Error Codes
These codes appear in the field of failed payments:failure_reason
E001Insufficient funds in sender wallet
E002Transaction reverted on-chain
E003Network timeout during transaction
E004Invalid wallet address
E005Gas estimation failed
E006User cancelled the transaction
E007CCTP attestation failed
E999Unknown blockchain error
| Code | Description |
|---|---|
E001 | Insufficient funds in sender wallet |
E002 | Transaction reverted on-chain |
E003 | Network timeout during transaction |
E004 | Invalid wallet address |
E005 | Gas estimation failed |
E006 | User cancelled the transaction |
E007 | CCTP attestation failed |
E999 | Unknown blockchain error |
Rate Limiting
When you exceed rate limits, you'll receive a 429 response with additional headers:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312800
{
"success": false,
"error": "Rate limit exceeded",
"message": "Too many requests. Please retry after 1 minute.",
"code": "RATE_LIMIT_EXCEEDED",
"retryAfter": 60,
"context": "general"
}Rate Limit Headers
| Header | Description |
|---|---|
Retry-After | Seconds to wait before retrying |
X-RateLimit-Limit | Maximum requests allowed in window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when limit resets |
Rate Limits by Endpoint
API Key endpoints
200 req / 1 minute
Per: API Key
General API
100 req / 1 minute
Per: IP
Payment creation (widget)
20 req / 1 minute
Per: IP
Login
5 req / 5 minutes
Per: IP + email
Registration
3 req / 15 minutes
Per: IP
Password Reset
3 req / 15 minutes
Per: IP + email
2FA verification
5 req / 5 minutes
Per: IP
Withdrawals
10 req / 10 minutes
Per: IP
Contact form
3 req / 15 minutes
Per: IP
| Endpoint | Limit | Window | Per |
|---|---|---|---|
| API Key endpoints | 200 req | 1 minute | API Key |
| General API | 100 req | 1 minute | IP |
| Payment creation (widget) | 20 req | 1 minute | IP |
| Login | 5 req | 5 minutes | IP + email |
| Registration | 3 req | 15 minutes | IP |
| Password Reset | 3 req | 15 minutes | IP + email |
| 2FA verification | 5 req | 5 minutes | IP |
| Withdrawals | 10 req | 10 minutes | IP |
| Contact form | 3 req | 15 minutes | IP |
Best Practice
Retry-AfterCross-Chain Errors
Cross-chain payments are handled client-side by Bridge Kit in the widget. If the bridge fails (e.g. attestation timeout, mint failure), the widget shows the error directly to the customer. These errors do not reach the backend API.
If a cross-chain payment fails after the burn transaction, the customer can contact support with their transaction hash. Failed payments store the error in the field, accessible via the payment status API.failure_reason
Fraud Detection
Fivo includes built-in fraud detection. These errors indicate potential attacks:
Payment amount verification failedThe claimed amount doesn't match the actual blockchain transaction amount. This could indicate an attempt to manipulate payment records.
Security
Error Handling Example
Here's how to properly handle API errors in your code:
async function createCheckoutSession(data) {
try {
const response = await fetch('https://api.fivo.finance/checkout/sessions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.FIVO_API_KEY
},
body: JSON.stringify(data)
});
const result = await response.json();
if (!response.ok) {
// Handle specific error codes
switch (response.status) {
case 400:
console.error('Validation error:', result.details);
throw new Error('Invalid session data');
case 401:
console.error('Authentication failed');
throw new Error('Please check your API key');
case 429:
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retry after ${retryAfter}s`);
throw new Error('Too many requests');
default:
throw new Error(result.error || 'Unknown error');
}
}
return result.data;
} catch (error) {
console.error('Checkout session failed:', error.message);
throw error;
}
}Still Having Issues?
If you encounter an error not listed here, please contact support with:
- The full error response
- Request details (endpoint, method, body)
- Payment ID or transaction hash (if applicable)
- Timestamp of when the error occurred