Troubleshooting & FAQ
Common issues, troubleshooting guides, and frequently asked questions for Fiatsend integration and usage.
Common Issues
Authentication Errors
401 Unauthorized
Problem: API requests are returning 401 Unauthorized errors.
Solutions:
-
Check API Key Format
// Correct format const sdk = new FiatsendSDK({ apiKey: "fs_your_64_character_api_key_here", environment: "production" });
-
Verify API Key Validity
// Test API key try { const balance = await sdk.wallet.getBalance("0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6"); console.log("API key is valid"); } catch (error) { if (error.status === 401) { console.log("API key is invalid or expired"); } }
-
Check Environment Configuration
// Ensure correct environment const sdk = new FiatsendSDK({ apiKey: process.env.FIATSEND_API_KEY, environment: process.env.NODE_ENV === 'production' ? 'production' : 'staging' });
403 Forbidden
Problem: API requests are returning 403 Forbidden errors.
Solutions:
-
Check API Key Permissions
- Ensure your API key has the required permissions
- Contact support to upgrade permissions if needed
-
Verify Request Headers
// Ensure proper headers const headers = { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json', 'X-API-USER': userId, 'X-API-KEY': apiKey, 'X-API-PUBKEY': publicKey };
Payment Issues
Payment Not Processing
Problem: Payments are not being processed or are stuck in pending status.
Solutions:
-
Check Payment Parameters
// Ensure all required parameters are provided const payment = await sdk.payment.initiatePayment({ amount: 100, // Must be a number currency: "USDT", // Must be valid currency recipient: "+233551234567", // Must be valid phone number country: "GH", // Must be valid country code description: "Payment description" // Optional but recommended });
-
Verify Recipient Phone Number
// Check if phone number exists in system const exists = await sdk.identity.checkNumberExists("+233551234567"); if (!exists.exists) { console.log("Phone number not found in Fiatsend network"); }
-
Check Wallet Balance
// Ensure sufficient balance const balance = await sdk.wallet.getBalance(walletAddress); if (balance.balances.USDT < amount) { console.log("Insufficient balance"); }
Mobile Money Payment Failures
Problem: Mobile money payments are failing.
Solutions:
-
Verify Mobile Money Provider
// Check supported providers const supportedProviders = ['mtn', 'airtel', 'telecel']; if (!supportedProviders.includes(provider)) { console.log("Unsupported mobile money provider"); }
-
Check Phone Number Format
// Ensure correct phone number format const phoneNumber = "0551234567"; // Local format for Ghana const fullNumber = "+233551234567"; // International format
-
Handle Provider-Specific Errors
try { const payment = await sdk.payment.createMTNPayment({ amount: 100, phoneNumber: "0551234567", externalRef: "PAY-12345", wallet: walletAddress }); } catch (error) { if (error.code === 'MTN_SERVICE_UNAVAILABLE') { console.log("MTN service temporarily unavailable"); } else if (error.code === 'INVALID_PHONE_NUMBER') { console.log("Invalid phone number format"); } }
Identity Management Issues
Identity NFT Creation Fails
Problem: Unable to create identity NFT for mobile number.
Solutions:
-
Check Mobile Number Format
// Ensure E.164 format const phoneNumber = "+233551234567"; // Correct format const phoneNumber = "0551234567"; // Incorrect format
-
Verify Wallet Connection
// Ensure wallet is connected and has sufficient gas const hasAccount = await sdk.core.hasAccount(walletAddress); if (!hasAccount) { console.log("Wallet not connected or insufficient gas"); }
-
Check for Existing Identity
// Check if identity already exists const exists = await sdk.identity.checkNumberExists(phoneNumber); if (exists.exists) { console.log("Identity already exists for this phone number"); }
Phone Number Resolution Fails
Problem: Unable to resolve phone number to wallet address.
Solutions:
-
Verify Phone Number Exists
// Check if phone number is registered const exists = await sdk.identity.checkNumberExists(phoneNumber); if (!exists.exists) { console.log("Phone number not registered in Fiatsend network"); }
-
Check Network Connection
// Ensure stable network connection try { const resolution = await sdk.identity.resolvePhoneToAddress(phoneNumber); } catch (error) { if (error.code === 'NETWORK_ERROR') { console.log("Network connection issue"); } }
SDK Integration Issues
Module Not Found Errors
Problem: Getting "Module not found" errors when importing SDK.
Solutions:
-
Check Installation
npm install @fiatsend/sdk # or yarn add @fiatsend/sdk
-
Verify Import Statement
// Correct import import { FiatsendSDK } from "@fiatsend/sdk"; // Incorrect import import Fiatsend from "@fiatsend/sdk";
-
Check Node.js Version
node --version # Should be 16 or higher
TypeScript Errors
Problem: TypeScript compilation errors with SDK.
Solutions:
-
Install TypeScript Types
npm install @types/node
-
Check TypeScript Configuration
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020"], "strict": true, "esModuleInterop": true, "skipLibCheck": true } }
-
Use Proper Type Annotations
import { FiatsendSDK, PaymentRequest } from "@fiatsend/sdk"; const sdk: FiatsendSDK = new FiatsendSDK({ apiKey: process.env.FIATSEND_API_KEY!, environment: "production" }); const payment: PaymentRequest = { amount: 100, currency: "USDT", recipient: "+233551234567", country: "GH" };
Frequently Asked Questions
General Questions
Q: What is Fiatsend?
A: Fiatsend is a Web3 payment platform designed for Africa that enables instant cross-border payments by connecting traditional finance with blockchain technology. Your mobile number becomes your crypto identity through NFT-based resolution.
Q: Which countries does Fiatsend support?
A: Fiatsend currently supports 7+ African countries including Ghana, Kenya, Nigeria, and others. We're continuously expanding to more countries.
Q: What currencies are supported?
A: Fiatsend supports multiple currencies including:
- Fiat: GHS (Ghana Cedi), USD (US Dollar)
- Crypto: USDT (Tether USD), USDC (USD Coin), GHSFIAT (Ghana Fiat Token), FSEND (Fiatsend Token)
Q: How fast are transactions?
A: Fiatsend provides sub-5 second settlement times for most transactions, with real-time processing and instant mobile money delivery.
Q: What are the fees?
A: Fiatsend offers competitive fees starting from 0.1% with no hidden charges. Fees vary based on transaction type and amount.
Technical Questions
Q: How do I get started with the SDK?
A: 1. Sign up at console.fiatsend.network (opens in a new tab)
2. Generate your API key
3. Install the SDK: npm install @fiatsend/sdk
4. Initialize the SDK with your API key
5. Start making payments!
Q: What blockchain networks are supported?
A: Fiatsend supports multiple blockchain networks:
- Lisk Sepolia (Chain ID: 324) - Testnet
- Polygon (Chain ID: 137) - Mainnet
- Ethereum (Chain ID: 1) - Mainnet
Q: How do I handle errors in my application?
A: The SDK provides comprehensive error handling with specific error codes and messages. Always wrap API calls in try-catch blocks and handle different error types appropriately.
Q: Can I use Fiatsend in a React application?
A: Yes! Fiatsend provides React hooks and components for easy integration. Check out our Integration Guides for examples.
Q: How do I test my integration?
A: Fiatsend provides a sandbox environment for testing. Use the staging environment and test API keys to develop and test your integration before going live.
Payment Questions
Q: How do mobile money payments work?
A: Fiatsend integrates directly with African mobile money providers (MTN, AirtelTigo, Telecel, Vodafone). When you send a payment, it's automatically converted and delivered to the recipient's mobile money wallet.
Q: What happens if a payment fails?
A: Failed payments are automatically refunded to the sender's wallet. You'll receive a webhook notification about the failure, and you can retry the payment.
Q: Can I send payments to any phone number?
A: You can send payments to any phone number, but the recipient must have a Fiatsend account and identity NFT to receive the payment.
Q: How do I check payment status?
A: Use the getTransactionStatus
method to check the current status of any payment:
const status = await sdk.payment.getTransactionStatus(transactionId);
console.log(status.status); // 'pending', 'completed', 'failed'
Q: What is the maximum payment amount?
A: Payment limits vary based on your verification level and the recipient's country. Check your account limits in the dashboard.
Identity Questions
Q: What is an identity NFT?
A: An identity NFT is a soulbound token that links your mobile number to your crypto identity. It enables seamless P2P transfers and identity verification.
Q: How do I create an identity NFT?
A: Use the mintIdentity
method to create an identity NFT:
const identity = await sdk.identity.mintIdentity({
phoneNumber: "+233551234567",
countryCode: "GH",
metadata: "User metadata",
walletAddress: "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6"
});
Q: Can I have multiple identities?
A: No, each mobile number can only have one identity NFT. However, you can update your identity information if needed.
Q: What is KYC verification?
A: KYC (Know Your Customer) verification is a process to verify your identity using official documents. It's required for higher transaction limits and certain features.
API Questions
Q: How do I manage my API keys?
A: You can manage your API keys through the Fiatsend dashboard:
- Go to your profile settings
- Navigate to the Security tab
- Click on API Keys
- Create, view, or delete API keys as needed
Q: What are the API rate limits?
A: API rate limits vary by endpoint type:
- Payment Operations: 100 requests per minute
- Wallet Operations: 200 requests per minute
- Identity Operations: 50 requests per minute
- General API: 1000 requests per minute
Q: How do I handle rate limiting?
A: The SDK automatically handles rate limiting with exponential backoff. You can also check rate limit headers in responses and implement your own retry logic.
Q: Can I use webhooks for real-time updates?
A: Yes! Fiatsend supports webhooks for real-time event notifications. Set up webhook endpoints to receive notifications about payment completions, failures, and other events.
Security Questions
Q: How secure is Fiatsend?
A: Fiatsend uses enterprise-level security with:
- Multi-signature wallets
- Encryption at rest and in transit
- KYC/AML compliance
- Smart contract audits
- Regulatory oversight
Q: How do I secure my API keys?
A: Always store API keys securely:
- Use environment variables
- Never commit keys to version control
- Rotate keys regularly
- Use different keys for different environments
Q: What should I do if my API key is compromised?
A: If your API key is compromised:
- Immediately revoke the compromised key
- Generate a new API key
- Update your application with the new key
- Review your transaction history for any unauthorized activity
Getting Help
Documentation
Support Channels
- Discord: Join our community (opens in a new tab)
- Email: support@fiatsend.network
- GitHub: Report issues (opens in a new tab)
Developer Resources
- SDK Documentation: @fiatsend/sdk (opens in a new tab)
- Code Examples: GitHub Examples (opens in a new tab)
- OpenAPI Spec: API Specification (opens in a new tab)
Status Page
- Service Status: status.fiatsend.network (opens in a new tab)
- Incident Updates: Real-time updates on service issues
- Maintenance Windows: Scheduled maintenance notifications
Best Practices
Error Handling
try {
const payment = await sdk.payment.initiatePayment(paymentData);
} catch (error) {
if (error.status === 400) {
// Handle validation errors
console.error("Invalid request:", error.message);
} else if (error.status === 401) {
// Handle authentication errors
console.error("Authentication failed:", error.message);
} else if (error.status === 429) {
// Handle rate limiting
console.error("Rate limited:", error.message);
} else {
// Handle other errors
console.error("Unexpected error:", error.message);
}
}
Retry Logic
const retryWithBackoff = async (fn, maxRetries = 3) => {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
if (error.status === 429) {
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
} else {
throw error;
}
}
}
};
Logging
const logger = {
info: (message, data) => console.log(`[INFO] ${message}`, data),
error: (message, error) => console.error(`[ERROR] ${message}`, error),
warn: (message, data) => console.warn(`[WARN] ${message}`, data)
};
// Usage
try {
const payment = await sdk.payment.initiatePayment(paymentData);
logger.info("Payment initiated", { transactionId: payment.transactionId });
} catch (error) {
logger.error("Payment failed", error);
}
Monitoring
const monitor = {
startTimer: (operation) => {
const start = Date.now();
return {
end: () => {
const duration = Date.now() - start;
console.log(`${operation} took ${duration}ms`);
return duration;
}
};
}
};
// Usage
const timer = monitor.startTimer("Payment Initiation");
try {
const payment = await sdk.payment.initiatePayment(paymentData);
timer.end();
} catch (error) {
timer.end();
throw error;
}