Skip to main content

Multi-currency and FX quotes

Quick Reference

WhatMulti-currency pricing and FX rate quotes
WhyOffer your customers prices in their own currency and increase conversion rates
Reading Time10 min
DifficultyBeginner
PrerequisitesAuthentication → Create charge

Why offer multi-currency

Your customers abandon checkout when they see prices in a foreign currency. Multi-currency solves this.

Without multi-currencyWith A55 multi-currency
Customer sees R$ 500.00 but pays in USDCustomer sees US$ 87.26 — the exact amount they pay
Customer does not know the real exchange rateYou show the mid-market rate with full transparency
Customer calls their bank to dispute the amountNo surprises — the price matches the charge
You lose cross-border salesYou convert international visitors into paying customers

The business impact is measurable:

  • Higher conversion: Customers buy when they understand the price in their own currency.
  • Fewer chargebacks: Transparent pricing reduces "I did not recognize this amount" disputes.
  • Competitive edge: You offer the same experience as global platforms like Amazon, Shopify, and Stripe.
  • LATAM coverage: 8 currencies across 7 countries — USD, BRL, EUR, MXN, ARS, COP, CLP, PEN.
Your customers see their currency

A merchant in Brazil can display prices in USD, EUR, or MXN to international buyers. A SaaS platform can show subscription prices in each customer's local currency. An e-commerce site can let buyers switch currencies at checkout.


How it works — three steps

The multi-currency flow has three steps. You call the FX endpoint, display the converted price, and create the charge.


Step 1 — Get the exchange rate

Call the FX endpoint to get the current mid-market rate between two currencies.

Endpoint: POST /api/v1/bank/wallet/fx/rate/

Request:

FieldTypeRequiredDescription
from_currencystringYesSource currency (ISO 4217). Example: USD
to_currencystringYesTarget currency (ISO 4217). Example: BRL

Response:

FieldTypeDescription
pricefloatThe exchange rate, rounded to 2 decimal places. When converting to a zero-decimal currency (CLP, COP), round the final amount to an integer
curl -X POST 'https://core-manager.a55.tech/api/v1/bank/wallet/fx/rate/' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"from_currency": "USD",
"to_currency": "BRL"
}'

Response:

{
"price": 5.73
}

This means 1 USD = 5.73 BRL at this moment.


Step 2 — Display the converted price to your customer

Use the rate to show your customer the price in their currency. This happens in your application — no A55 API call is needed.

Example (BRL — 2 decimals): Your product costs US$ 100.00. The rate is 5.73.

Price in BRL = US$ 100.00 × 5.73 = R$ 573.00
What the customer seesValue
Product priceUS$ 100.00
Exchange rate1 USD = 5.73 BRL
Amount to payR$ 573.00

Example (CLP — zero-decimal): Your product costs US$ 100.00. The rate is 950.73.

Price in CLP = US$ 100.00 × 950.73 = CLP 95,073  (round to integer)
What the customer seesValue
Product priceUS$ 100.00
Exchange rate1 USD = 950.73 CLP
Amount to payCLP $95,073
CLP and COP: always round to integer

For zero-decimal currencies, the amount you send in the charge request must be an integer. 95073, not 95073.00. The backend truncates decimal places for CLP and COP.

Best practice: show both currencies

Display the original price AND the converted price. This builds trust. Your customer knows the exact rate and the exact amount their card or bank account will be charged.


Step 3 — Create the charge

Create the charge in the settlement currency (the currency of the wallet). The charge amount is the converted value from Step 2.

curl -X POST 'https://core-manager.a55.tech/api/v1/bank/wallet/charge/' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"wallet_uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"merchant_id": "11111111-1111-1111-1111-111111111111",
"payer_name": "John Smith",
"payer_email": "john@example.com",
"payer_tax_id": "12345678909",
"payer_cell_phone": "+5511999999999",
"installment_value": 573.00,
"currency": "BRL",
"due_date": "2026-04-30",
"description": "Order #12345 (US$ 100.00 at 5.73)",
"type_charge": "credit_card",
"installment_count": 1,
"payer_address": {
"street": "Av. Paulista",
"address_number": "1000",
"complement": "Sala 101",
"neighborhood": "Bela Vista",
"city": "São Paulo",
"state": "SP",
"postal_code": "01310-100",
"country": "BR"
}
}'
Record the rate in the description field

Store the rate in the charge description field (for example: "Order #12345 (US$ 100.00 at 5.73)"). This creates an audit trail for reconciliation and dispute resolution.

The charge response includes automatic multi-currency conversion:

{
"charge_uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"local_currency": 573.00,
"currency": "BRL",
"usd_currency": 100.00,
"eur_currency": 91.45,
"type": "credit_card",
"status": "confirmed",
"installment_count": 1,
"installments": [
{
"local_currency": 573.00,
"currency": "BRL",
"usd_currency": 100.00,
"eur_currency": 91.45,
"due_date": "2026-04-30",
"status": "confirmed",
"installment_number": 1
}
]
}

Every charge response includes three currency values:

FieldDescriptionExample
local_currencyAmount in the wallet's settlement currency573.00 (BRL)
usd_currencyEquivalent amount in US dollars100.00 (USD)
eur_currencyEquivalent amount in euros91.45 (EUR)

You can use these values for multi-currency reporting, reconciliation, and analytics dashboards without calling the FX endpoint again.


Complete integration example

This example shows the full flow — authenticate, get the FX rate, calculate the price, and create the charge.

import requests

BASE = "https://core-manager.a55.tech/api/v1"
AUTH_URL = "https://smart-capital.auth.us-east-1.amazoncognito.com/oauth2/token"

# Authenticate
token_resp = requests.post(AUTH_URL, data={
"grant_type": "client_credentials",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
}, headers={"Content-Type": "application/x-www-form-urlencoded"})
token = token_resp.json()["access_token"]
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}

# Step 1: Get the exchange rate
fx_resp = requests.post(f"{BASE}/bank/wallet/fx/rate/", json={
"from_currency": "USD",
"to_currency": "BRL",
}, headers=headers)
rate = fx_resp.json()["price"]
print(f"Exchange rate: 1 USD = {rate} BRL")

# Step 2: Calculate the converted price
product_price_usd = 100.00
ZERO_DECIMAL_CURRENCIES = {"CLP", "COP"}
target_currency = "BRL"

if target_currency in ZERO_DECIMAL_CURRENCIES:
charge_amount = round(product_price_usd * rate)
else:
charge_amount = round(product_price_usd * rate, 2)
print(f"Charge amount: {charge_amount}")

# Step 3: Create the charge in BRL
charge_resp = requests.post(f"{BASE}/bank/wallet/charge/", json={
"wallet_uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"merchant_id": "11111111-1111-1111-1111-111111111111",
"payer_name": "John Smith",
"payer_email": "john@example.com",
"payer_tax_id": "12345678909",
"payer_cell_phone": "+5511999999999",
"installment_value": charge_amount,
"currency": "BRL",
"due_date": "2026-04-30",
"description": f"Order #12345 (US$ {product_price_usd} at {rate})",
"type_charge": "credit_card",
"payer_address": {
"street": "Av. Paulista", "address_number": "1000",
"complement": "Sala 101", "neighborhood": "Bela Vista",
"city": "São Paulo", "state": "SP",
"postal_code": "01310-100", "country": "BR",
},
}, headers=headers)

charge = charge_resp.json()
print(f"Charge UUID: {charge['charge_uuid']}")
print(f"Local (BRL): {charge['local_currency']}")
print(f"USD: {charge['usd_currency']}")
print(f"EUR: {charge['eur_currency']}")

Supported currencies

The FX API supports 8 currencies across 7 LATAM countries plus USD and EUR, producing 56 conversion pairs.

CodeCurrencyCountry / RegionDecimalsWallet supported
USDUS DollarUnited States2
BRLBrazilian RealBrazil2Yes
EUREuroEurozone2
MXNMexican PesoMexico2Yes
ARSArgentine PesoArgentina2Yes
COPColombian PesoColombia0
CLPChilean PesoChile0Yes
PENPeruvian SolPeru2
Zero-decimal currencies in FX conversion

When converting to CLP or COP, the final charge amount must be an integer. After multiplying by the FX rate, round to the nearest whole number using round() (not floor()). Example: USD 100.00 × 950.73 = CLP 95,073 (not 95073.00).

Key cross-border corridors

PairUse case
USD → BRLUS companies selling to Brazilian customers
USD → MXNUS companies selling to Mexican customers
EUR → BRLEuropean companies entering Brazil
BRL → USDBrazilian SaaS, exports, remittances
USD → CLPUS companies selling to Chilean customers
USD → ARSUS companies selling to Argentine customers
USD → COPUS companies selling to Colombian customers
USD → PENUS companies selling to Peruvian customers

Rate source and freshness

PropertyValue
Rate sourceMid-market (interbank) — the Bid/Ask midpoint as reported by third-party data sources, with zero A55 markup
Cache window~17 minutes (1,000 seconds)
Data sourcesCascading fallback — the system queries multiple external providers in sequence to ensure rate availability
PrecisionRate rounded to 2 decimal places; final charge amount follows currency decimals (0 for CLP/COP, 2 for all others)
API availability24/7 — the endpoint responds at all times, including weekends and holidays
Weekend ratesOutside forex market hours (weekends, holidays), data sources return the last available trading rate
Why mid-market rates

The mid-market rate is the midpoint between the buy and sell price in the interbank market. It has zero markup. Central banks, regulators, and fintech companies use it as the fairest reference for currency conversion. The Forex market trades over US$ 9.6 trillion per day (BIS 2025) — no other financial market offers this level of liquidity and price accuracy.


How card networks and issuers add fees to the exchange rate

The A55 FX endpoint returns the mid-market rate with zero markup. But between A55 and the cardholder's credit card statement, two additional layers add fees. Understanding this chain helps you distinguish expected bank fees from integration errors.

The conversion chain

When a US cardholder pays on a BRL merchant site, five steps determine the final statement amount:

StepActorWhat happens
1A55 FX endpointReturns mid-market rate (for example, 5.50 BRL/USD)
2MerchantCharges R$ 550.00 in BRL (settlement currency)
3Card network (Visa or Mastercard)Converts R$ 550.00 to USD at their published daily rate — mid-market plus network markup (~1%)
4Issuing bankAdds foreign transaction fee (0–3%, most cards charge 1–2%)
5Cardholder statementShows the final amount: approximately US$ 101–104

Fee breakdown by layer

LayerWhat it isWho paysTypical range
A55 FX quoteMid-market interbank rate, no markup0%
Card network assessmentVisa ISA or Mastercard Cross-Border AssessmentMerchant (passed through processor)0.6–1.4%
Network currency conversionEmbedded in the card network's published exchange rateCardholder~1%
Issuer foreign transaction feeFee charged by the cardholder's bank for foreign currency transactionsCardholder0–3%
Total impact on cardholderDifference between mid-market rate and statement amountCardholder~1.6–4.4%

Visa vs Mastercard fee comparison

VisaMastercard
Cross-border assessment (merchant side)ISA: 1.00% (USD settlement) / 1.40% (non-USD)0.60% (USD settlement) / 1.00% (non-USD)
Conversion markup (cardholder side)~1% over mid-market~1% over mid-market
Rate application timingTypically at settlement (1–2 business days after authorization)At authorization (point of sale)
Published rate checkerVisa exchange rate calculatorMastercard currency converter

What you control vs what you cannot control

You controlYou cannot control
When to fetch the FX rate (freshness)The card network's published exchange rate
The BRL amount submitted in the chargeThe issuer's foreign transaction fee (0–3%)
The price and rate displayed to the customerWhether the cardholder's card charges 0% or 3% FX fee
The audit trail stored for dispute defenseThe conversion date the network applies

Real-world scenarios

ScenarioExpected statement amountRisk
Fresh rate + card with 0% foreign fee~US$ 101.00None
Fresh rate + card with 2% foreign fee~US$ 103.00None
Fresh rate + card with 3% foreign fee~US$ 104.00None — within expected range
Stale rate (45 min old) + 2% foreign fee~US$ 106–108High — Mastercard 4834 chargeback

The first three rows show expected, non-disputable variance caused by bank fees. The last row shows the stale-rate problem compounded by fees — this combination produces the chargebacks.

Conversion timing and weekends

Mastercard applies the exchange rate at the time of authorization (when the cardholder pays). Visa typically applies the rate at the time of settlement (1–2 business days later). This means:

  • Mastercard charges: The rate applied is very close to the rate at the time of purchase.
  • Visa charges: The rate may shift between authorization and settlement. In volatile markets, this creates additional variance.

For weekend transactions, both networks use the last available Friday rate (New York 5:00 PM EST) until Forex markets reopen Sunday evening. Weekend transactions carry higher risk of rate divergence if the market moves significantly over the 48-hour closure.


Rate freshness best practices

Leading payment platforms (Stripe, Wise, Adyen) distinguish between two uses of exchange rates. The A55 FX endpoint serves both, but the refresh strategy differs.

Display pricing — product pages and catalogs

When showing multi-currency prices on product listing pages or pricing pages, you can cache the rate server-side and refresh periodically.

RecommendationDetails
Refresh frequencyCall the FX endpoint every 10–15 minutes
CachingCache the rate server-side to avoid an API call on every page load
Price disclaimerLabel prices as "approximate — final amount determined at checkout"

Transactional checkout — creating actual charges

When the customer confirms payment and you create the charge, use the freshest rate possible to ensure the displayed amount matches the charged amount.

RecommendationDetails
Refresh timingRe-fetch the rate when the customer clicks "Confirm payment"
Display the rateShow the original amount, exchange rate, and converted amount on the payment confirmation page
Record the rateStore the rate in the charge description field and in your database
Amount consistencyEnsure the amount shown to the customer matches the installment_value exactly
Use fresh rates for charges

The exchange rate remains constant within the cache window (~17 minutes). If your customer spends time on the checkout page, re-fetch the rate before creating the charge. Using a stale rate may cause the charged amount to differ from the displayed amount.

How a stale rate causes chargebacks — a real scenario

If you are new to payments, this section explains why rate freshness matters. Here is a real chargeback scenario:

Scenario: Your product costs US$ 100.00. The customer pays with a USD credit card. Your wallet settlement currency is BRL.

TimeEventRateAmount
10:00 AMYou fetch the rate and display the price1 USD = 5.73 BRLPage shows "R$ 573.00"
10:45 AMCustomer clicks "Confirm" — you create the charge using the 10:00 AM rateReal rate is now 5.50You submit R$ 573.00
10:45 AMIssuing bank converts R$ 573.00 back to USD at current rateIssuer uses 5.50Statement shows US$ 104.18
Next dayCardholder checks statement"I agreed to pay US$ 100.00, why was I charged US$ 104.18?"
3 days laterCardholder files dispute with issuerMastercard reason code 4834: "Transaction Amount Differs"

What happened: You calculated the BRL amount using a 45-minute-old rate (5.73). But the cardholder's issuing bank converted BRL back to USD at the current rate (5.50), resulting in US$ 104.18 instead of US$ 100.00. The US$ 4.18 difference triggered the chargeback.

The fix: At the moment the customer clicks "Confirm" (10:45 AM), re-call the FX endpoint to get the current rate (5.50), calculate R$ 550.00, and submit R$ 550.00. The issuer converts back to approximately US$ 100.00 — the statement matches the displayed price, no dispute.

Issuer FX markup — why the statement may still differ slightly

Even with a perfectly timed rate, the cardholder's issuing bank adds its own FX markup (typically 1–3% over mid-market). This is standard across Visa and Mastercard networks — the cardholder's bank agreement covers this markup. A charge that converts to exactly US$ 100.00 at mid-market may appear as US$ 101.00–103.00 on the statement. This small, expected variance rarely triggers disputes. The critical issue — and the one that causes Mastercard 4834 chargebacks — is the large discrepancy caused by stale rates, as shown in the scenario above.

Key rule

Fetch the rate at the last possible moment before creating the charge. The shorter the gap between fetching the rate and creating the charge, the smaller the discrepancy on the cardholder's statement.

Why re-fetching at confirm is the best approach

Three strategies exist for preventing FX-related chargebacks in cross-border payments:

StrategyHow it worksAvailable in A55
Re-fetch at confirmGet the freshest mid-market rate before creating the chargeYes — call the FX endpoint at the last moment
DCC (Dynamic Currency Conversion)Charge the cardholder in their own currency so the issuer does not convertNo — requires DCC certification and multi-currency settlement
Rate lockLock the quoted rate for a guaranteed periodNo — the FX endpoint returns a real-time quote, not a locked rate

Re-fetching at confirm minimizes rate drift (the largest source of chargebacks). Combined with transparent disclosure and record-keeping, this is the industry-standard approach used by Stripe, Adyen, and Wise for merchants who settle in a single currency.

Chargeback prevention checklist

For every cross-border charge, verify:

  • You fetched a fresh rate immediately before creating the charge
  • The payment confirmation page shows the original amount, exchange rate, and converted amount together
  • The payment confirmation page includes a note: "Final amount on your card statement may vary slightly due to your bank's exchange rate"
  • The rate and original amount are stored in the charge description field
  • The installment_value exactly matches the amount displayed to the customer
  • Your database records: rate value, fetch timestamp, displayed amount, charged amount
  • For zero-decimal currencies (CLP, COP), the amount is an integer

Use cases

ScenarioHow to use the FX endpoint
Cross-border checkoutGet the rate, display the converted price to the buyer before they confirm payment
Dynamic pricingUpdate product prices on your website based on current exchange rates
Multi-currency dashboardConvert all transaction values to USD or EUR for consolidated reporting
Financial reconciliationCompare the rate at transaction time with the rate at settlement time
Subscription pricingShow subscribers their monthly charge in their local currency
Invoice generationInclude the exchange rate and both currency amounts on invoices

Important notes

Capital controls (ARS)

For currencies with capital controls — particularly the Argentine Peso (ARS) — the mid-market rate may differ from official or parallel rates used locally. The rate returned reflects the international interbank market.

The FX endpoint is a quote — it does not lock the rate

The FX endpoint returns the current interbank market rate for display and calculation. It does not lock the rate. The actual conversion applied to a charge depends on the acquirer at the time the transaction is processed. To minimize discrepancy, fetch a fresh quote immediately before creating the charge.

Build an FX audit trail

For every cross-border charge, record: the time you fetched the rate, the rate value, the amount displayed to the customer, and the amount charged. Include the rate in the charge description field (for example: "Order #12345 (US$ 100.00 at 5.73)") and persist the full record in your system. This data is essential for reconciliation and dispute resolution.