Tilbage til blog

Wise Exchange Rate API: How to Get Wise's Rates, and When You Need an Alternative

V
Vlado Grigirov
September 04, 2026
Currency API Exchange Rates Wise API Comparison Fintech Developer Guide

If you have ever tried to show Wise's exchange rate inside your own product, you have probably discovered that the Wise exchange rate API is not quite the thing you expected. Wise publishes genuinely excellent mid-market rate data, and it exposes that data over a REST endpoint — but it sits behind a partner onboarding process, it lives in a payments API rather than a market-data API, and the rate you get back is deliberately not the price your user will pay.

This guide covers exactly what Wise exposes, how to authenticate against it, what each endpoint actually returns, and the five structural limits that decide whether Wise is the right source for your project. It also covers the honest answer to the question most people are really asking: if you just need reliable mid-market exchange rates in an app, is Wise the tool for that job?

What the Wise exchange rate API actually is

Wise is a money transfer company. Its API — branded Wise Platform — is built to move money: create quotes, register recipients, fund transfers, reconcile balances, issue cards. Exchange rates appear in that API because you cannot price a transfer without them, not because Wise sells market data.

That framing explains almost every surprise developers hit. Rates are one small module inside a payments platform, and they are scoped to the currency routes Wise actually supports.

Three separate surfaces, three different access paths

The single biggest source of confusion is that "the Wise rate API" refers to at least three distinct things:

  1. GET /rates — the Exchange Rates endpoint. Returns Wise's mid-market rate for a currency pair, current or historical. This is what most people mean.
  2. POST /quotes — the Quotes endpoint. Returns a priced transfer: rate, fee, estimated delivery time, and a rate expiration timestamp.
  3. GET /comparisons — the Comparison endpoint. Returns estimated price and speed data for Wise and competing providers and banks on a given route.

They are documented in the same reference, they use different authentication schemes, and they answer very different questions. Reaching for the wrong one is the usual cause of "why is this rate different from what wise.com shows me?"

How to get access to Wise rate data

There is no self-serve API key. Access falls into two tracks:

Platform partners. You onboard as a Wise Platform partner and authenticate with OAuth 2.0 (client ID and client secret) to obtain a token. The /rates reference notes that the endpoint "only supports Bearer authentication for non-Affiliate partners," using a User Token or Personal Token.

Affiliate partners. You join the Wise affiliate programme, then email partnerwise@wise.com to request credentials. Wise reviews the request and, if approved, issues Basic auth credentials that unlock exactly two endpoints: Exchange Rates List and Get Temporary Quote. Nothing else.

This is the fork in the road. If you are building a comparison site, a travel blog widget, or a fintech marketing page, the affiliate track is designed for you. If you are building a product feature — multi-currency pricing, invoicing, a converter screen, an internal reporting job — you are asking a payments partner team to approve you for market data, which is not what either side wants from the relationship.

Note also that Wise pins the API version into the URL path: production is https://api.wise.com/2026Q3/rates, with sandbox at https://api.wise-sandbox.com/2026Q3/rates. Legacy affiliate documentation still references /v1/rates on api.transferwise.com. Version strings embedded in paths mean your integration quietly ages unless someone owns upgrading it.

Calling the Wise rates endpoint

Once you have a token, the endpoint itself is clean and well designed. Four call shapes are documented:

# Latest rates for every supported currency
curl -X GET 'https://api.wise.com/2026Q3/rates' \
  -H 'Authorization: Bearer <YOUR_TOKEN>'

# Latest rate for a single pair
curl -X GET 'https://api.wise.com/2026Q3/rates?source=EUR&target=USD' \
  -H 'Authorization: Bearer <YOUR_TOKEN>'

# Rate at a specific historical moment
curl -X GET 'https://api.wise.com/2026Q3/rates?source=EUR&target=USD&time=2019-02-13T14:53:01' \
  -H 'Authorization: Bearer <YOUR_TOKEN>'

# A time series, grouped by day, hour or minute
curl -X GET 'https://api.wise.com/2026Q3/rates?source=EUR&target=USD&from=2019-02-13&to=2019-03-13&group=day' \
  -H 'Authorization: Bearer <YOUR_TOKEN>'

The response is an array, one object per interval:

[
  {
    "rate": 1.166,
    "source": "EUR",
    "target": "USD",
    "time": "2018-08-31T10:43:31+0000"
  }
]

Two details worth flagging. First, group accepts day, hour or minute — minute-level history is unusually generous and genuinely useful for backtesting. Second, the response is always an array, even for a single pair, so parse accordingly:

import requests

TOKEN = "<YOUR_TOKEN>"
BASE = "https://api.wise.com/2026Q3"

def wise_rate(source: str, target: str) -> float:
    r = requests.get(
        f"{BASE}/rates",
        params={"source": source, "target": target},
        headers={"Authorization": f"Bearer {TOKEN}"},
        timeout=10,
    )
    r.raise_for_status()
    payload = r.json()
    if not payload:
        raise LookupError(f"No rate returned for {source}/{target}")
    return payload[0]["rate"]  # array, even for one pair

print(wise_rate("EUR", "USD"))

One more trap, well documented in the wild: if you send time and from/to in the same request, the range parameters win and time is ignored. This caused a long-standing bug in n8n's Wise node that took an upstream patch to fix. Send one or the other, never both.

The mid-market rate is not the price your user pays

Wise's /rates endpoint returns the mid-market rate — the midpoint between the buy and sell price on the interbank market. It is the "real" rate, and it is what Wise markets itself on. It is also, by definition, a rate nobody transacts at.

If you need what a transfer will actually cost, you need /quotes:

curl -X POST 'https://api.wise.com/2026Q3/quotes' \
  -H 'Authorization: Bearer <YOUR_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{
    "sourceCurrency": "GBP",
    "targetCurrency": "USD",
    "sourceAmount": 100
  }'

The quote response carries the fields that pricing logic actually needs: rate, rateType (for example FIXED), rateExpirationTime, a fee breakdown, feePercentage, and a paymentOptions array with estimatedDelivery per pay-in method. It also returns notices — Wise's own documented example warns that a customer may hold a maximum of three open transfers at a guaranteed rate before further transfers fall back to the live rate.

The practical consequence: a quote is a short-lived, stateful object tied to a transfer, not a rate lookup you can poll on a schedule. If your use case is "display today's USD price on a pricing page," quotes are the wrong primitive and rates are the right one. If your use case is "tell the user precisely what they will receive," rates alone will overstate it. Getting this distinction wrong is a common source of the rounding and reconciliation mismatches described in our guide to currency rounding and decimal places.

What the Comparison API really returns

The Comparison endpoint is the most interesting and the most misunderstood part of the platform. It returns provider-by-provider price and speed estimates for banks and money transfer services on a route:

curl -X GET 'https://api.wise.com/2026Q3/comparisons?sourceCurrency=GBP&targetCurrency=EUR&sendAmount=10000&filter=POPULAR'

Before you build anything on top of it, read Wise's own methodology note carefully. Wise states that it collects advertised rates and fees from third-party websites, calculates each provider's markup over the mid-market rate at the moment of collection, and then re-applies that stored markup to the current mid-market rate to produce the number you receive. Collection runs roughly once per hour.

In other words, competitor prices from this endpoint are modelled estimates derived from hourly scrapes, not live quotes. Wise says so plainly, which is to its credit — but it means the data is unsuitable for anything where you would need to stand behind the competitor number. Wise further restricts the estimates to bank transfer pay-in and pay-out only, and notes that many providers price card and cash transactions very differently.

Structurally, the response is denormalised: one provider can return several quotes for the same currency pair because pricing and delivery speed vary by destination country. You get a providers array, each with a quotes array, and reducing that to one headline number per provider is your job, not the API's.

Five limits to know before you build on Wise rates

  1. Access is a business relationship, not a signup. Affiliate approval or Platform onboarding gates every rate call. There is no dashboard where you generate a key in thirty seconds.
  2. Coverage follows transfer routes. Wise supports the currencies it can move money in. A dedicated data provider covers currencies it can price, which is a broader set — Finexly covers 170+ currencies, including ones no transfer corridor exists for.
  3. Rates are one module in a payments API. The surrounding surface is quotes, recipients, KYC, cards and webhooks. That is a large, security-sensitive integration to maintain when all you wanted was a number.
  4. No published quota. The /rates reference documents a 429 response but does not publish a public request allowance, so you are sizing capacity against an unstated limit. Compare that with an explicit, headers-in-every-response model.
  5. Two currencies per call. /rates takes a single source and target. Pricing a page in eight currencies means eight calls or a full-table fetch and client-side filtering.

None of these are defects. They are what a payments API looks like when you use it as a data API.

When Wise is the right choice — and when it isn't

Your use caseBest fitWhy
Comparison site or affiliate content showing "banks vs Wise"Wise Comparison APIIt is the only source for this data, and the affiliate track exists precisely for it
Actually sending money through WiseWise Quotes + TransfersYou need the priced, expiring quote object
Showing Wise's branded rate because your users asked for itWise /ratesBrand attribution is the whole point
Multi-currency pricing, checkout or a converter screenDedicated currency APIYou need breadth, a fast key, and a simple contract
Invoicing, billing and revenue reportingDedicated currency APIYou need a stable historical series and an audit trail
Backtesting or analyticsEitherWise's minute-level history is strong; a data API is easier to obtain
If you land in the top three rows, use Wise. It is the correct tool and this article is not going to pretend otherwise. If you land in the bottom rows, you are paying partner-onboarding cost for a lookup, and a purpose-built exchange rate API is the shorter path. The same reasoning applies to using a payment processor's FX endpoints as a data source, which we worked through in Stripe FX Quotes API vs a dedicated currency API.

Using a dedicated exchange rate API instead

A data API inverts the trade-off: no onboarding call, broader coverage, an explicit quota, and a response shape with nothing in it but the rate.

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.finexly.com/v1/rate?from=EUR&to=USD"
{ "pair": "EUR_USD", "rate": 1.0852 }

Pricing a page in several currencies is one round trip rather than one call per pair:

const apiKey = process.env.FINEXLY_API_KEY;

async function priceTable(base, quotes) {
  const q = quotes.map((c) => `${base}_${c}`).join(',');
  const res = await fetch(`https://api.finexly.com/v1/convert?q=${q}`, {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  if (!res.ok) throw new Error(`Finexly ${res.status}`);
  return res.json();
}

const rates = await priceTable('USD', ['EUR', 'GBP', 'JPY', 'CAD', 'AUD']);
// { "USD_EUR": { "rate": 0.9215 }, "USD_GBP": { "rate": 0.7892 }, ... }

And when you want the converted figure rather than the multiplier, let the API do the arithmetic so rounding happens in one place:

import requests

def convert(amount, src, dst, api_key):
    r = requests.get(
        "https://api.finexly.com/v1/convert-amount",
        params={"from": src, "to": dst, "amount": amount},
        headers={"Authorization": f"Bearer {api_key}"},
        timeout=10,
    )
    r.raise_for_status()
    return r.json()["result"]

print(convert(100, "USD", "EUR", "YOUR_API_KEY"))

Every response carries X-RateLimit-Limit, X-RateLimit-Used and X-RateLimit-Units, so quota is observable rather than inferred. Rates refresh every minute during market hours. The free tier is 1,000 requests per month at 10 requests per minute, with paid plans from $6.99/month for 3,500 requests up to 100,000 on the Professional plan — the full breakdown is on the pricing page.

A short note on volume: 1,000 requests a month sounds small until you cache. A single scheduled job that refreshes a full rate table every fifteen minutes uses roughly 2,900 calls a month; every sixty minutes uses about 730. Caching turns your call volume into a function of time rather than traffic, which is what makes a small tier viable at any scale. The patterns are covered in caching and error handling for currency APIs.

Migrating from Wise /rates

If you are moving an existing integration, the mapping is close to one-for-one:

WiseEquivalentNote
GET /ratesGET /v1/currencies then /v1/rateWise's bare /rates returns everything; fetch the currency list once
GET /rates?source=X&target=YGET /v1/rate?from=X&to=YReturns an object, not a single-element array
Several pairs, several callsGET /v1/convert?q=X_Y,X_ZOne request
Manual amount * rateGET /v1/convert-amountRounding handled server-side
?time= historical pointHistorical endpointRequires a paid plan; see the historical rates guide
Basic or OAuth tokenAuthorization: BearerKey from the dashboard, no approval step
The one thing that does not migrate is Wise's brand. If your value proposition is "we show you the Wise rate," only Wise can supply it. If your value proposition is "our prices are correct in your currency," any accurate mid-market source will do — and the sourcing question is worth understanding either way, which we unpack in where exchange rate APIs get their data.

Finally: please do not scrape wise.com. Several marketplace listings offer exactly that, and they are fragile, legally murky, and break the first time the page markup changes. If you need the Wise number specifically, take the affiliate track and get it from the API properly. If you need a number, use an API built to serve one. Our comparison of free currency APIs and the Frankfurter alternatives guide both cover the no-key options in more depth.

Frequently Asked Questions

Is the Wise exchange rate API free? There is no published per-request charge for the rates endpoint, but access is not open. You must be an approved Wise Platform partner or an approved affiliate partner, which means an application and a review rather than a signup form. For most projects the cost is time, not money.

Can I use the Wise API without an account? No. Both documented tracks require credentials — Bearer tokens for Platform partners, Basic auth client ID and secret for affiliate partners. The only endpoint whose documented example omits an authorization header is /comparisons, and building production traffic on that assumption is unwise.

Does the Wise API return the same rate shown on wise.com? /rates returns the mid-market rate, which is the headline figure Wise advertises. The amount a customer actually receives comes from /quotes and includes Wise's fee. If your numbers do not match the website, you are almost certainly comparing a mid-market rate against a priced quote.

How far back does Wise historical rate data go? The endpoint accepts arbitrary from/to timestamps with day, hour or minute grouping; Wise does not publish a fixed earliest date in the reference, so test the specific range you need rather than assuming coverage.

What is the best alternative to the Wise exchange rate API? It depends on what you are replacing. For competitor price comparison there is no alternative — Wise's Comparison API is unique. For mid-market rates in a product, a dedicated currency data API gives you broader coverage, instant keys and an explicit quota. Compare the options on our API comparison page.

Can I show Wise's rate to my users legally? If you are an approved affiliate or Platform partner, yes, within the terms of that agreement. Scraping the public site to obtain the same numbers is a different matter and is not something we would recommend building a business on.


Ready to skip the partner onboarding and just get rates? Get your free Finexly API key — no credit card required. Start with 1,000 free requests per month across 170+ currencies, and upgrade only when your traffic does. You can also try the rates in the browser first with our currency converter.

Vlado Grigirov

Senior Currency Markets Analyst & Financial Strategist

Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...

View full profile →