Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Implement a Currency Converter in FlutterFlow

Build a currency converter in FlutterFlow by calling the exchangerate-api.com API to fetch live exchange rates, caching the full rates map in App State so you only call the API once per session, displaying two currency DropDowns and an amount TextField, and computing the converted result in a Custom Function. A historical chart shows rate trends using fl_chart.

What you'll learn

  • Set up an API call to exchangerate-api.com and parse the response in FlutterFlow
  • Cache exchange rates in App State to avoid redundant API calls
  • Calculate converted amounts using a Custom Function triggered on TextField change
  • Display a historical rate chart using the fl_chart package
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner10 min read30-40 minFlutterFlow Free+March 2026RapidDev Engineering Team
TL;DR

Build a currency converter in FlutterFlow by calling the exchangerate-api.com API to fetch live exchange rates, caching the full rates map in App State so you only call the API once per session, displaying two currency DropDowns and an amount TextField, and computing the converted result in a Custom Function. A historical chart shows rate trends using fl_chart.

Real-Time Exchange Rate Conversion with Smart Caching

This tutorial shows you how to build a functional currency converter inside FlutterFlow. The key design decision is caching: instead of calling the exchange rate API on every keystroke or every DropDown change, you fetch the full rates map once on app start and store it in App State. The conversion calculation happens entirely in a Custom Function using the cached data — zero additional API calls. Two DropDown widgets let users select the from and to currencies. A TextField accepts the input amount and triggers the Custom Function on every change event. A results display shows the converted amount in real time. An optional historical chart section uses the fl_chart package to show how the selected currency pair has moved over 7 days.

Prerequisites

  • FlutterFlow account (Free plan works for this tutorial)
  • A free API key from exchangerate-api.com (sign up takes 1 minute)
  • Basic familiarity with FlutterFlow's API Calls panel and Custom Functions
  • App State variables created for caching rate data

Step-by-step guide

1

Set Up the Exchange Rate API Call in FlutterFlow

In FlutterFlow, open the API Calls panel from the left sidebar. Click the + button to create a new API call. Name it GetExchangeRates. Set the method to GET and the URL to https://v6.exchangerate-api.com/v6/YOUR_API_KEY/latest/USD. In FlutterFlow Settings, add your API key as an App Constant named EXCHANGE_RATE_API_KEY and reference it in the URL: https://v6.exchangerate-api.com/v6/[EXCHANGE_RATE_API_KEY]/latest/USD. Click Test API Call — you should see a JSON response with a conversion_rates object containing ~160 currency codes and their rates relative to USD. Click the JSON path arrows next to conversion_rates to create a JSON path for the rates map. Save the API call.

Expected result: The API call returns a 200 response with conversion_rates containing currency codes and exchange rates.

2

Cache Exchange Rates in App State

Open FlutterFlow's App State panel. Create two variables: ratesJson (String, persisted — stores the raw JSON string of conversion_rates), and ratesLastFetched (DateTime, persisted — records when rates were last fetched). On the App Start action (Settings → App Start Actions), add a conditional: if ratesLastFetched is null OR if the difference between DateTime.now() and ratesLastFetched is greater than 3 hours, then call GetExchangeRates. On success, update ratesJson with the response's conversion_rates JSON string and update ratesLastFetched to DateTime.now(). This means the API is called at most once every 3 hours per device, not on every user action.

Expected result: Exchange rates are fetched on first app launch and cached in App State. Subsequent opens within 3 hours skip the API call.

3

Build the Converter UI with Two DropDowns and a TextField

Create the converter page layout. Add a TextField at the top for the amount input. Set its keyboard type to Decimal. Store its value in a Page State variable named inputAmount (String). Below it, add a Row with two DropDown widgets side by side. Both DropDowns use a static option list of currency codes — add the most common ones: USD, EUR, GBP, JPY, CAD, AUD, CHF, CNY, INR, MXN, BRL, SGD. Store the selected values in Page State variables fromCurrency (String, default USD) and toCurrency (String, default EUR). Add a swap IconButton between the two DropDowns. On tap, swap the fromCurrency and toCurrency Page State values and trigger recalculation. Below the DropDowns, add a large Text widget that will display the converted result, bound to a Page State variable named convertedAmount (String).

Expected result: The page shows a numeric input field, two currency DropDowns with a swap button, and a converted amount display area.

4

Calculate Conversion with a Custom Function

Create a Custom Function named convertCurrency. It takes four arguments: ratesJson (String), fromCurrency (String), toCurrency (String), and amount (String). It returns a String. The function parses ratesJson, finds the rates for both currencies relative to USD, converts the amount from fromCurrency to USD then from USD to toCurrency, and returns a formatted result string. In FlutterFlow, wire this function to trigger whenever inputAmount, fromCurrency, or toCurrency changes: on the TextField's On Change action, call Update Page State and set convertedAmount to the result of convertCurrency. Do the same for both DropDowns' On Change actions.

convert_currency.dart
1// Custom Function: convertCurrency
2// Arguments: ratesJson (String), fromCurrency (String),
3// toCurrency (String), amount (String)
4// Return type: String
5import 'dart:convert';
6
7String convertCurrency(
8 String ratesJson,
9 String fromCurrency,
10 String toCurrency,
11 String amount,
12) {
13 if (ratesJson.isEmpty || amount.isEmpty) return '0.00';
14 final input = double.tryParse(amount);
15 if (input == null || input <= 0) return '0.00';
16
17 try {
18 final rates = Map<String, dynamic>.from(json.decode(ratesJson) as Map);
19 final fromRate = (rates[fromCurrency] as num?)?.toDouble() ?? 1.0;
20 final toRate = (rates[toCurrency] as num?)?.toDouble() ?? 1.0;
21 // Convert: amount / fromRate * toRate (both relative to USD)
22 final result = (input / fromRate) * toRate;
23 if (result >= 1000000) return result.toStringAsFixed(0);
24 if (result >= 100) return result.toStringAsFixed(2);
25 return result.toStringAsFixed(4);
26 } catch (_) {
27 return 'Error';
28 }
29}

Expected result: Typing an amount or changing a currency DropDown instantly updates the converted amount display without any API calls.

5

Add a Historical Rate Chart with fl_chart

For the historical chart, create a second API call named GetHistoricalRates using the exchangerate-api.com history endpoint: GET https://v6.exchangerate-api.com/v6/YOUR_API_KEY/history/USD/YEAR/MONTH/DAY. You will need to call this endpoint for each of the last 7 days using a loop or parallel API calls. Store the 7 data points in a Page State variable named historicalRates (List of Doubles). Create a Custom Widget named RateChart that uses the fl_chart package's LineChart. The widget accepts historicalRates (List of Doubles) and currencyPair (String) as parameters. Display the 7 data points as a line chart with date labels on the x-axis and rate values on the y-axis. Place this widget below the converter in a collapsible container.

Expected result: A line chart appears below the converter showing the selected currency pair's rate over the past 7 days.

Complete working example

convert_currency.dart
1// Custom Function: convertCurrency
2// FlutterFlow Custom Functions panel
3// Arguments:
4// ratesJson: String (from App State)
5// fromCurrency: String (from Page State)
6// toCurrency: String (from Page State)
7// amount: String (from TextField)
8// Return type: String
9
10import 'dart:convert';
11
12String convertCurrency(
13 String ratesJson,
14 String fromCurrency,
15 String toCurrency,
16 String amount,
17) {
18 // Handle empty inputs
19 if (ratesJson.isEmpty) return 'Loading...';
20 if (amount.isEmpty) return '0.00';
21
22 // Normalize decimal separator for European locales
23 final normalizedAmount = amount.replaceAll(',', '.');
24 final input = double.tryParse(normalizedAmount);
25 if (input == null) return 'Invalid';
26 if (input <= 0) return '0.00';
27
28 // Same currency shortcut
29 if (fromCurrency == toCurrency) {
30 return input.toStringAsFixed(2);
31 }
32
33 try {
34 final decoded = json.decode(ratesJson);
35 final rates = Map<String, dynamic>.from(decoded as Map);
36
37 // Rates are all relative to USD base
38 final fromRate = (rates[fromCurrency] as num?)?.toDouble();
39 final toRate = (rates[toCurrency] as num?)?.toDouble();
40
41 if (fromRate == null || fromRate == 0) return 'N/A';
42 if (toRate == null) return 'N/A';
43
44 // Convert to USD first, then to target currency
45 final inUsd = input / fromRate;
46 final result = inUsd * toRate;
47
48 // Format based on magnitude
49 if (result >= 1000000) {
50 return '${(result / 1000000).toStringAsFixed(2)}M';
51 } else if (result >= 1000) {
52 return result.toStringAsFixed(2);
53 } else if (result >= 1) {
54 return result.toStringAsFixed(4);
55 } else {
56 return result.toStringAsFixed(6);
57 }
58 } catch (e) {
59 return 'Error';
60 }
61}
62
63// Custom Function: getRateForPair
64// Returns the direct exchange rate between two currencies
65// Arguments: ratesJson (String), fromCurrency (String), toCurrency (String)
66// Return type: String
67String getRateForPair(String ratesJson, String fromCurrency, String toCurrency) {
68 if (ratesJson.isEmpty) return '';
69 try {
70 final rates = Map<String, dynamic>.from(json.decode(ratesJson) as Map);
71 final fromRate = (rates[fromCurrency] as num?)?.toDouble() ?? 1.0;
72 final toRate = (rates[toCurrency] as num?)?.toDouble() ?? 1.0;
73 final rate = toRate / fromRate;
74 return '1 $fromCurrency = ${rate.toStringAsFixed(4)} $toCurrency';
75 } catch (_) {
76 return '';
77 }
78}

Common mistakes when implementing a Currency Converter in FlutterFlow

Why it's a problem: Calling the exchange rate API on every keystroke in the amount TextField

How to avoid: Fetch rates once on app start and cache them in App State for 3 hours. The conversion calculation runs entirely in a Custom Function using cached data — no API call needed on keystroke.

Why it's a problem: Storing the exchange rates as a separate App State variable for each currency code (e.g., usdToEur, usdToGbp, usdToJpy...)

How to avoid: Store the entire conversion_rates JSON object as a single String in App State. Parse it in the Custom Function using dart:convert's json.decode. This keeps App State clean and supports all ~160 currencies.

Why it's a problem: Not handling the case where fromCurrency and toCurrency are the same

How to avoid: Add an early return in the Custom Function: if fromCurrency == toCurrency, return the input amount formatted to 2 decimal places.

Best practices

  • Cache exchange rates in persisted App State for 3-6 hours to minimize API calls and support offline usage.
  • Always show the last-updated timestamp next to the exchange rate so users know how fresh the data is.
  • Handle the same-currency case explicitly in your Custom Function to avoid floating-point rounding errors.
  • Support comma as decimal separator for European users by normalizing input in the Custom Function.
  • Show a loading indicator while rates are being fetched on first app launch and disable the converter UI until rates are ready.
  • Display the direct exchange rate (e.g., '1 USD = 0.9234 EUR') below the result so users can verify the calculation.
  • Add a favorites row of commonly used currency pairs at the top of the converter for quick access.

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I'm building a currency converter in FlutterFlow. I have the exchange rate JSON stored as a String in App State — it looks like {"USD": 1.0, "EUR": 0.92, "GBP": 0.79, ...}. Write a Dart Custom Function called convertCurrency that takes ratesJson (String), fromCurrency (String), toCurrency (String), and amount (String) as arguments and returns the converted amount formatted as a String. Handle edge cases like empty input, same currency, and JSON parse errors.

FlutterFlow Prompt

Create an API call in FlutterFlow named GetExchangeRates that calls GET https://v6.exchangerate-api.com/v6/API_KEY/latest/USD. Create JSON paths to extract the conversion_rates object. Then show me how to save the conversion_rates to a persisted App State String variable on App Start.

Frequently asked questions

Does the free exchangerate-api.com plan work for a production app?

The free plan gives 1,500 requests per month. With caching (one call per user per 3 hours), this supports around 1,500 unique active user sessions per month. For apps with more traffic, upgrade to the paid plan ($9.99/month for 100,000 requests) or switch to Open Exchange Rates.

How do I update the exchange rates more frequently for a trading app?

Reduce the cache TTL from 3 hours to 15 minutes, and change the App State fetch trigger to run when ratesLastFetched is older than 15 minutes. For real-time rates under 1-minute delay, use a paid Forex API like Fixer.io or Open Exchange Rates, not exchangerate-api.com.

Can I support cryptocurrencies like Bitcoin and Ethereum?

exchangerate-api.com does not include crypto. Use the CoinGecko API (free, no key required) as a separate API call for crypto rates. Create a second GetCryptoRates API call and merge the results into your ratesJson App State variable in the App Start action.

How do I show the amount in both currencies at the same time as the user types?

This already works with the TextField On Change action trigger. Every keystroke calls Update Page State with the convertCurrency result, which the result Text widget displays in real time. The Custom Function is synchronous and runs in microseconds so there is no noticeable delay.

Why does the converter show 'Error' instead of a result?

This usually means ratesJson is empty (rates not yet fetched) or the currency code in the DropDown does not match the key in the API response exactly. Currency codes are case-sensitive — the API uses uppercase codes like USD, EUR, GBP. Check that your DropDown options exactly match the API's currency code format.

Can I let users save favorite currency pairs?

Yes. Create a Firestore favorites collection with fields: userId, fromCurrency, toCurrency. Add a star IconButton on the converter page that saves the current pair to Firestore. On the converter page load, query the user's favorites and display them as quick-select chips above the DropDowns.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.