Official Central Bank Exchange Rates in QuickBooks Online

QuickBooks Online accepts custom exchange rates per currency per day. This guide pushes the official central-bank rate into a company with the Accounting API ExchangeRate entity.

Which endpoint: every guide below reads the bank's latest published table from GET /api/v1/central-bank/{bank}/latest (free key, one call per fetch) or the keyless evaluation copy at /api/public/central-bank/{bank}?format=json. Add ?source=USD&target=EUR for one resolved pair, format=xml or format=csv for importers that do not read JSON, and api_key= on the URL when the importer cannot send headers. Bank codes are on the central bank coverage map.

What QuickBooks allows

Once multicurrency is on, QuickBooks Online downloads market rates automatically, and it also lets you enter your own rate per currency per day. That override is a first-class API object: ExchangeRate in the Accounting API, keyed by source currency and AsOfDate. Transactions dated that day pick the override up unless a rate was set on the transaction itself. One POST per currency per day is the whole integration.

The rate QuickBooks expects

Rate is home-currency units per 1 unit of SourceCurrencyCode. For a USD company and EUR that is USD per EUR. Ask the API for that pair directly; the table's own direction does not matter because the endpoint inverts or crosses as needed and says so:

GET https://allratestoday.com/api/v1/central-bank/ecb/latest?source=EUR&target=USD
Authorization: Bearer art_live_your_key

{ "bank": "ecb", "rate_date": "2026-09-16", "source": "EUR", "target": "USD",
  "rate": 1.1537, "derived": false, "method": "published" }

Daily sync

Read the currencies the company has enabled, fetch the official rate for each against the home currency, and post it dated with the bank's rate_date. Python with plain requests after OAuth 2.0:

import requests

REALM = "1234567890"
QBO = f"https://quickbooks.api.intuit.com/v3/company/{REALM}"
QBO_H = {"Authorization": f"Bearer {qbo_access_token}", "Accept": "application/json"}
ART_H = {"Authorization": "Bearer art_live_your_key"}
BANK, HOME = "ecb", "USD"

# 1. currencies enabled in the company (reads are limited to enabled currencies since 2026-04-30)
q = requests.get(f"{QBO}/query", headers=QBO_H,
                 params={"query": "SELECT * FROM CompanyCurrency", "minorversion": 75}).json()
codes = [c["Code"] for c in q["QueryResponse"].get("CompanyCurrency", [])]

# 2. one official rate per currency, home units per 1 foreign unit
for code in codes:
    r = requests.get(f"https://allratestoday.com/api/v1/central-bank/{BANK}/latest",
                     params={"source": code, "target": HOME}, headers=ART_H, timeout=10)
    if r.status_code == 404:          # bank does not cover this currency
        continue
    body = r.json()
    payload = {"SourceCurrencyCode": code, "AsOfDate": body["rate_date"], "Rate": body["rate"]}
    requests.post(f"{QBO}/exchangerate", headers=QBO_H, params={"minorversion": 75}, json=payload).raise_for_status()
    print(code, body["rate_date"], body["rate"], "derived" if body["derived"] else "published")

Run it after the bank's publication time each business day. Re-posting the same currency and date updates the rate in place, so a rerun is safe.

Per-transaction override

If you only need the official rate on some documents, set ExchangeRate on the invoice or bill body instead of the company table. The value has the same meaning: home units per 1 unit of the document currency.

Notes

Other systems: Business Central · Xero · QuickBooks Online · SAP · Odoo · all integrations. Endpoint reference: Central Bank Rates.