Docs/Error Handling

Error Handling

Understanding and handling errors in the Fivo API.

Error Response Format

All API errors follow a consistent format:

Error Response Structure
{
  "success": false,
  "error": "Human-readable error message",
  "details": [
    {
      "field": "amount",
      "message": "Must be a positive number"
    }
  ]
}

HTTP Status Codes

200OK

Request successful

201Created

Resource created successfully

400Bad Request

Invalid request data or validation error

401Unauthorized

Missing or invalid authentication

403Forbidden

Not authorized to access this resource

404Not Found

Resource not found

429Too Many Requests

Rate limit exceeded

500Internal Error

Server error - please contact support

Common Errors

Validation Errors (400)

Invalid input data

Request body doesn't match expected schema. Check the array for specific field errors.details

json
{
  "success": false,
  "error": "Invalid input data",
  "details": [
    {"path": ["amount"], "message": "Expected number, received string"},
    {"path": ["token"], "message": "Invalid enum value. Expected 'USDC' | 'EURC'"}
  ]
}
Invalid amount

Amount must be between 0.01 and 1,000,000.

Invalid merchant address

The doesn't match the merchant's wallet address.toAddress

Authentication Errors (401/403)

No token provided

Protected endpoint requires authentication. Include or header.AuthorizationX-API-Key

Invalid or expired token

JWT token has expired (15 min lifetime) or is malformed. Re-authenticate to get a new token.

Invalid API key

API key not found or has been revoked. Check that you're using the correct key.

Resource Errors (404)

Merchant not found

No merchant exists with the given ID. Verify your .merchantId

Payment not found

No payment exists with the given ID. Check the payment ID is correct.

Payment already exists

A 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

Error Response with Code
{
  "success": false,
  "error": "Human-readable message",
  "code": "RATE_LIMIT_EXCEEDED",
  "retryAfter": 60
}

General Error Codes

RATE_LIMIT_EXCEEDED429

Rate limit exceeded for this endpoint

INVALID_UUID_FORMAT400

ID parameter is not a valid UUID

MISSING_PARAMETER400

A required parameter is missing

2FA_REQUIRED403

Operation requires 2FA to be enabled

2FA_CODE_REQUIRED400

2FA code was not provided

2FA_INVALID401

2FA code is incorrect or expired

SELF_TRANSFER_NOT_ALLOWED400

Cannot withdraw to your own Fivo wallet

INVALID_MERCHANT_ID400

Merchant ID format is invalid

WEBHOOK_LIMIT_REACHED400

Maximum webhooks per merchant reached

REFUND_WINDOW_EXPIRED400

Refund window (180 days) has expired

REFUND_EXCEEDS_REMAINING400

Amount exceeds refundable balance

PAYMENT_NOT_COMPLETED400

Payment is not in completed status

NO_SOURCE_ADDRESS400

Payment has no source address

REFUND_NOT_CANCELABLE400

Refund is not in pending status

Blockchain Error Codes

These codes appear in the field of failed payments:failure_reason

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:

Rate Limit Response
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

HeaderDescription
Retry-AfterSeconds to wait before retrying
X-RateLimit-LimitMaximum requests allowed in window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix 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

i

Best Practice

Implement exponential backoff when you receive 429 errors. Start with the value and increase wait time for subsequent retries.Retry-After

Cross-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 failed

The claimed amount doesn't match the actual blockchain transaction amount. This could indicate an attempt to manipulate payment records.

!

Security

Fraud attempts are logged with full details (IP, wallet address, transaction). Repeated attempts may result in IP blocking.

Error Handling Example

Here's how to properly handle API errors in your code:

JavaScript Error Handling
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
Contact Support