Documentation Index
Fetch the complete documentation index at: https://apidocs.hopnow.io/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The HopNow API supports multiple currencies for accounts, balances, payins, payouts, and FX operations. This guide covers best practices for handling currencies correctly.
Supported Currencies
The API supports all major fiat currencies (ISO 4217) and popular cryptocurrencies:
Fiat Currencies
- USD - US Dollar
- EUR - Euro
- GBP - British Pound
- MXN - Mexican Peso
- BRL - Brazilian Real
- And 150+ other ISO 4217 currencies
Cryptocurrencies
- BTC - Bitcoin
- ETH - Ethereum
- USDC_ETHEREUM - USD Coin on Ethereum
- USDC_POLYGON - USD Coin on Polygon
- USDT - Tether
Currency Codes
Always use standard currency codes:
# Good - ISO 4217 codes
amount_usd = "100.00"
currency = "USD"
# Good - Crypto with network
currency = "USDC_ETHEREUM"
# Bad - Do not use symbols
currency = "$" # ❌ Invalid
Decimal Precision
Different currencies have different decimal precision requirements:
Standard Fiat (2 decimals)
{
"amount": "100.50",
"currency": "USD"
}
Zero-Decimal Currencies
Some currencies don’t use decimal places (e.g., JPY, KRW):
{
"amount": "10000",
"currency": "JPY"
}
Cryptocurrencies (up to 8 decimals)
{
"amount": "0.00123456",
"currency": "BTC"
}
Always use string format for amounts to avoid floating-point precision errors:
# Good - String format
payout_data = {
"amount": "100.50",
"currency": "USD"
}
# Bad - Float (can cause precision errors)
payout_data = {
"amount": 100.5, # ❌ May cause rounding errors
"currency": "USD"
}
Multi-Currency Accounts
Accounts can hold balances in multiple currencies simultaneously:
def get_balance_by_currency(account, currency):
"""Get balance for specific currency"""
for balance in account["balances"]:
if balance["currency"] == currency:
return balance
return None
# Usage
account = get_account("acc_123")
usd_balance = get_balance_by_currency(account, "USD")
eur_balance = get_balance_by_currency(account, "EUR")
Currency Conversion (FX)
Use the FX endpoints for currency conversion:
# 1. Create a quote
quote = create_fx_quote(
account_id="acct_123",
source_currency="USD",
target_currency="EUR",
amount="1000.00",
amount_type="source"
)
# 2. Review the rate
print(f"Rate: {quote['all_in_rate']}")
print(f"You'll receive: {quote['target_amount']} EUR")
# 3. Execute before expiration
trade = execute_fx_quote(account_id="acct_123", quote_id=quote['id'])
Currency Matching
Always ensure currency matches across related operations:
Payout Destinations
# Payout destination currency must match payout currency
destination = create_payout_destination(
beneficiary_id="bene_123",
currency="USD", # Destination currency
account_number="..."
)
# Later, payout must use same currency
payout = create_payout(
beneficiary_id="bene_123",
payout_destination_id=destination["id"],
amount="100.00",
currency="USD" # Must match destination
)
Virtual Accounts
Each virtual account supports one currency:
# Create separate virtual accounts for each currency
va_usd = create_virtual_account(
account_id="acc_123",
currency="USD",
label="USD Collections"
)
va_eur = create_virtual_account(
account_id="acc_123",
currency="EUR",
label="EUR Collections"
)
Balance Checks
Always check sufficient balance before creating payouts:
def can_create_payout(account_id, currency, amount):
"""Check if account has sufficient balance"""
account = get_account(account_id)
balance = get_balance_by_currency(account, currency)
if not balance:
return False, f"No {currency} balance"
available = Decimal(balance["available_balance"])
required = Decimal(amount)
if available < required:
return False, f"Insufficient funds: {available} < {required}"
return True, "Sufficient balance"
# Usage
can_pay, message = can_create_payout("acc_123", "USD", "100.00")
if not can_pay:
print(f"Cannot create payout: {message}")
Currency Display
Format currencies correctly for display:
def format_currency(amount, currency):
"""Format amount with proper currency symbol and precision"""
amount_decimal = Decimal(amount)
# Currency symbols
symbols = {
"USD": "$",
"EUR": "€",
"GBP": "£",
"JPY": "¥"
}
# Precision by currency
if currency in ["JPY", "KRW"]:
# Zero-decimal currencies
return f"{symbols.get(currency, currency)} {amount_decimal:,.0f}"
else:
# Standard 2-decimal currencies
return f"{symbols.get(currency, currency)} {amount_decimal:,.2f}"
# Usage
print(format_currency("1000.50", "USD")) # $ 1,000.50
print(format_currency("10000", "JPY")) # ¥ 10,000
Common Pitfalls
1. Floating Point Arithmetic
❌ Never use float for money calculations:
# Bad
total = 100.10 + 200.20 # May result in 300.2999999999
# Good
from decimal import Decimal
total = Decimal("100.10") + Decimal("200.20") # Exactly 300.30
2. Currency Mismatch
❌ Don’t create payouts with mismatched currencies:
# Bad - will fail
create_payout(
beneficiary_id="bene_123",
payout_destination_id="dest_usd", # USD destination
amount="100.00",
currency="EUR" # ❌ Currency mismatch
)
3. Ignoring Balance Currency
❌ Don’t assume single currency:
# Bad - assumes single currency
balance = account["balances"][0]["available_balance"]
# Good - specify currency
usd_balance = get_balance_by_currency(account, "USD")
Best Practices Summary
- ✅ Always use string format for amounts
- ✅ Use standard ISO 4217 currency codes
- ✅ Check currency matches for related operations
- ✅ Verify sufficient balance before payouts
- ✅ Use Decimal for money calculations
- ✅ Handle multi-currency accounts properly
- ✅ Respect currency-specific decimal precision
- ✅ Use FX endpoints for currency conversion