# Currencies and exchange rates

Choose a merchant price currency when creating a link or checkout. Eligible buyers can then choose a currency offered by Stripe at checkout. This release uses Stripe Adaptive Pricing; it is not a selector for every world currency.

> Developer preview. Test and live accounts use separate payment data. Verify supported currencies and checkout behavior for each merchant before accepting live payments.

## Price, payment and payout

| Currency | What it means | Who chooses it |
|---|---|---|
| Price / integration | Your original price and the API's order-verification amount | Merchant |
| Payment / presentment | The currency and amount the buyer confirms | Buyer, from the choices Stripe offers |
| Payout / settlement | The currency deposited into the connected bank account | Connected account's supported payout settings |

A USD price does not promise a USD or JMD bank payout. Check the connected account's settlement settings separately. Atlas does not change payout configuration when a buyer selects a currency.

## Supported flows

| Flow | Buyer currency selection | Rate display |
|---|---|---|
| Standalone `POST /checkouts`, hosted | Adaptive Pricing requested by default; optional `adaptive_pricing: false` | Stripe-hosted checkout |
| Standalone `POST /checkouts`, `ui_mode: elements` | Same eligibility, plus client-side opt-in | Currency Selector and your current Stripe.js total/rate |
| Customer-specific checkout links and Atlas subscription enrollment | Adaptive Pricing requested | Stripe-hosted checkout |
| One-time fixed-price Payment Links | Depends on the connected account's Payment Links / Adaptive Pricing configuration | Stripe-hosted checkout |
| Customer-entered donation amount | Fixed merchant currency | No Atlas conversion quote |
| Catalog / wallet capture-on-delivery order | Fixed order currency | Authorization amount; no Atlas FX conversion |
| Save a wallet card | No purchase | No payment or FX quote |

Stripe chooses offered currencies using buyer location and account eligibility. The price currency must be a supported settlement currency of the merchant of record. Manual capture is excluded. Unsupported sessions keep their original currency. Payment methods can change with currency. [Stripe Adaptive Pricing](https://docs.stripe.com/payments/currencies/localize-prices/adaptive-pricing?payment-ui=embedded-components).

## Set the price correctly

The dashboard's payment-link form loads charge currencies for the connected merchant's country. Changing the currency keeps the number entered; it does not convert it. If the list cannot load, retry before creating the link. Stripe still checks account and payment-method eligibility.

For server integrations, read `GET /api/v1/capabilities` with `account:read`. Each `currencies` entry contains `code`, `decimals`, and `amount_multiple`. These are merchant charge currencies, not a list of currencies a particular buyer will be offered.

| Price | API currency | Integer amount |
|---|---|---|
| 25.00 US dollars | USD | 2500 |
| 2500 Japanese yen | JPY | 2500 |
| 1.230 Kuwaiti dinars | KWD | 1230 |
| 5 Icelandic krónur | ISK | 500 |
| 500 Ugandan shillings | UGX | 50000 |

Never multiply every currency by 100. ISK and UGX require a multiple of 100 in Stripe's two-decimal charge representation; supported three-decimal currencies require a multiple of 10. Reject unsupported precision instead of rounding the customer's price. Stripe minimums and maximums still apply. [Stripe currency rules](https://docs.stripe.com/currencies).

## Show a real quote before payment

For hosted checkout, let Stripe display the choices and converted total. For an embedded [Payment Element](https://dashboard.atlaspay.sh/docs/payment-elements), initialize `CheckoutElementsProvider` with `adaptivePricing: { allowed: true }` and render `CurrencySelectorElement` near the total.

Read `checkout.currency`, `checkout.total.total.amount`, and the selected entry in `checkout.currencyOptions` from `useCheckoutElements()` on every render. When that entry has `currencyConversion`, display `1 sourceCurrency = fxRate selectedCurrency`. The rate includes Stripe's conversion fee. Do not label it a mid-market rate or add another conversion fee to the quoted total. When there is no conversion, show the fixed currency without inventing a rate. [Stripe's session fields](https://docs.stripe.com/js/custom_checkout/session_object), [conversion fees](https://support.stripe.com/questions/adaptive-pricing).

Also use Stripe's current formatted values for any line items, taxes, shipping, or discounts you display. Never convert the original server amount with an unrelated FX feed. A card issuer may charge its own fees, including when the buyer keeps the merchant currency.

## Verify and refund in the original currency

Atlas `GET /checkouts/{id}` keeps `amount` and `currency` in the integration currency. Match those against your original server order; require `status: paid`, `risk_decision: allow`, and `fulfillment_allowed: true` before fulfillment. A different payment currency does not bypass risk review.

The optional `presentment` object contains the buyer's actual `amount`, `currency`, and `effective_exchange_rate` when Stripe supplies them. Amounts use that currency's charge units. The effective rate is derived from the two rounded amounts and is for receipts/reconciliation only; it is not the pre-payment quote. It can be null for a zero amount. Missing presentment data means unavailable, not a zero payment. Transaction details show this buyer amount and effective conversion separately.

Refund requests remain in the original integration currency. Do not put a converted buyer amount into `POST /refunds`. Stripe handles the corresponding presentment refund. Do not recompute it using today's exchange rate. [Stripe refund behavior](https://docs.stripe.com/payments/currencies/localize-prices/adaptive-pricing?payment-ui=embedded-components).

Subscription checkout displays the selected recurring billing terms before confirmation. The wallet offer starts from the merchant's price; invoices and the billing portal are authoritative for actual billing amounts, taxes and adjustments. Do not promise future exchange rates from a previous checkout quote.

## Sandbox acceptance

1. Configure Adaptive Pricing for the correct connected account and test/live context. Fixed-price Payment Links use the applicable Stripe settings; Atlas does not alter those settings automatically.
2. Create a test checkout with a settlement-eligible base currency. Use a test customer email such as `test+location_FR@example.com` to simulate a buyer location. Check both hosted and Elements flows.
3. Switch each offered currency. Confirm the currency code, quote, total and available payment methods update together. A same-country or ineligible session must show the fixed currency without a broken selector.
4. Complete a Stripe test payment, retrieve the checkout on the merchant server, and verify original amount/currency, presentment and risk gates. Test a partial refund in original charge units.
5. Repeat with a subscription, a zero-decimal currency, a three-decimal currency, ISK/UGX, an expired session, and an asynchronous payment. Capture-on-delivery must still reject conversion and preserve its original authorization amount.

For the embedded integration, continue to [Payment Element](https://dashboard.atlaspay.sh/docs/payment-elements).

---

Source: [Atlas Pay — Currencies & FX rates](https://dashboard.atlaspay.sh/docs/currencies)

Prepared by Kyle Campbell
