# ECB Exchange Rates – Invoice Currency Converter (`fast_data_asap/ecb-exchange-rates-invoice-converter`) Actor

Convert invoice amounts to EUR (or any ECB currency) with the official ECB euro reference rates for the invoice date. Weekend/holiday fallback flagged, rate day and source URL per row for audit. Batch conversion or daily rate tables. Pay per result row.

- **URL**: https://apify.com/fast_data_asap/ecb-exchange-rates-invoice-converter.md
- **Developed by:** [Fast Data](https://apify.com/fast_data_asap) (community)
- **Categories:** Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ECB Exchange Rates – Invoice Currency Converter (official euro reference rates)

Convert invoice amounts in foreign currencies to **EUR** (or any other ECB currency) with the **official ECB euro foreign exchange reference rates** for the invoice date. Every result row tells you **which rate day was actually used**, whether a **weekend / TARGET-holiday fallback** was applied, and gives the **exact ECB API URL** for that rate – so your bookkeeping stays traceable.

Two modes:

- **convert** (default): a list of `{amount, currency, date}` rows → converted amounts, one row per input row
- **rates**: daily ECB reference rates for a list of currencies and a date range → one row per currency and fixing day

**Price: $0.001 per result row** ($1 per 1,000 rows). Error rows (unknown currency, future date, …) are free. No start fee.

### Who is it for?

- **Bookkeeping, accounts payable and controlling** teams that receive invoices in USD, GBP, CHF, PLN … and need the EUR value at the invoice date
- **Developers and automation builders** (n8n, Make, Zapier) who want a batch conversion step with the official ECB rates and no API key
- **AI agents** (via MCP) that have to convert amounts reproducibly instead of guessing a rate
- **E-invoice workflows** – combine it with our [XRechnung & ZUGFeRD parser](https://apify.com/fast_data_asap/xrechnung-zugferd-einvoice-parser): take `currency`, `grandTotal` and `issueDate` from the parsed invoice and convert it here

### What makes it useful

| | |
|---|---|
| Data source | Only the public [ECB Data Portal API](https://data.ecb.europa.eu/), dataset **EXR** (`D.<CUR>.EUR.SP00.A`), the daily euro reference rates published by the European Central Bank for about 30 currencies |
| Exact ECB rates | Rates are returned exactly as the ECB publishes them (units of foreign currency per 1 EUR), no markup, no mid-market estimate from another provider |
| Audit trail | `rateDate`, `fallbackUsed`, `daysShifted`, `fallbackRule` and a `sourceUrl` that returns exactly the rate used |
| Weekend / holiday handling | No ECB rate on weekends and TARGET holidays. `fallback`: `previous` (default, last earlier fixing day), `next` or `none` (error row) |
| Cross rates | USD → GBP, CHF → PLN etc. are calculated via the euro (`amount / rate(from) × rate(to)`), both rates are returned |
| Batch | Hundreds of invoices in one run. One ECB request per currency covers all dates of the run (plus a small in-memory cache) |
| Rounding | `convertedAmount` rounded half-up to 2 decimals, `convertedAmountUnrounded` for your own rounding rules |
| Fast | Default input (3 invoices) finishes in about 5 seconds on 256 MB |

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | `convert` | `rates` | `convert` | What to do |
| `items` | array | 3 sample invoices | convert mode: `{"amount", "currency", "date", "id"?, "targetCurrency"?}`; `date` in ISO format `YYYY-MM-DD`; amounts as numbers or strings (`"1.234,56"` and `"1,234.56"` are accepted) |
| `targetCurrency` | string | `EUR` | convert mode: currency to convert into (can be overridden per row) |
| `fallback` | `previous` | `next` | `none` | `previous` | convert mode: rule for dates without an ECB rate |
| `currencies` | array | `USD, GBP, CHF, JPY, PLN` | rates mode: currencies to list |
| `startDate` / `endDate` | `YYYY-MM-DD` | last 30 days | rates mode: date range |

Example (convert mode, the default input):

```json
{
  "mode": "convert",
  "targetCurrency": "EUR",
  "fallback": "previous",
  "items": [
    { "id": "INV-1001", "amount": 1250.00, "currency": "USD", "date": "2026-11-07" },
    { "id": "INV-1002", "amount": 480.50, "currency": "GBP", "date": "2026-11-05" },
    { "id": "INV-1003", "amount": 2999.90, "currency": "CHF", "date": "2026-10-30" }
  ]
}
```

Example (rates mode):

```json
{ "mode": "rates", "currencies": ["USD", "JPY"], "startDate": "2026-11-02", "endDate": "2026-11-10" }
```

### Output

Real result from the default input. 2026-11-07 is a Saturday, so the rate of Friday 2026-11-06 is used and flagged:

```json
{
  "id": "INV-1001",
  "amount": 1250,
  "currency": "USD",
  "date": "2026-11-07",
  "targetCurrency": "EUR",
  "rateDate": "2026-11-06",
  "rate": 1.1165,
  "targetRateDate": null,
  "targetRate": 1,
  "crossRate": 0.8956560681,
  "convertedAmount": 1119.57,
  "convertedAmountUnrounded": 1119.57008509,
  "fallbackUsed": true,
  "daysShifted": -1,
  "fallbackRule": "previous",
  "source": "ECB euro foreign exchange reference rates",
  "sourceUrl": "https://data-api.ecb.europa.eu/service/data/EXR/D.USD.EUR.SP00.A?format=csvdata&startPeriod=2026-11-06&endPeriod=2026-11-06",
  "targetSourceUrl": null,
  "status": "ok",
  "error": null
}
```

The other rows of the same run: 480.50 GBP on 2026-11-05 (rate 0.83393) → **576.19 EUR**; 2,999.90 CHF on 2026-10-30 (rate 0.9194) → **3,262.89 EUR**, both without fallback.

| Field | Meaning |
|---|---|
| `rate` | ECB rate of `currency`: units of `currency` per 1 EUR (1 for EUR) |
| `targetRate` / `targetRateDate` | Same for `targetCurrency` (date only for non-EUR targets) |
| `crossRate` | Units of `targetCurrency` per 1 unit of `currency` |
| `rateDate` | ECB fixing day actually used |
| `fallbackUsed` / `daysShifted` | `true` / negative days if an earlier day was used (positive with `fallback: next`) |
| `status` / `error` | `ok`, or `error` with a message: unknown currency, invalid amount, date in the future, date before 1999-01-04 or before the ECB published that currency, no fixing within 10 days |

Rates mode rows look like this (real values):

```json
{ "date": "2026-11-02", "currency": "USD", "baseCurrency": "EUR", "rate": 1.1216, "inverseRate": 0.89158345, "source": "ECB euro foreign exchange reference rates", "sourceUrl": "https://data-api.ecb.europa.eu/service/data/EXR/D.USD.EUR.SP00.A?format=csvdata&startPeriod=2026-11-02&endPeriod=2026-11-02", "status": "ok", "error": null }
```

`inverseRate` = EUR per 1 unit of the currency.

Good to know: EUR → EUR returns rate 1 without calling the ECB. The ECB publishes the rates on TARGET working days around 16:00 CET; for today's date before publication the `previous` fallback uses the last published day. Currencies the ECB no longer publishes (e.g. HRK, BGN) work for the periods in which they were published.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| `converted-row` – one converted amount | $0.001 |
| `rate-row` – one daily rate (rates mode) | $0.001 |

Rows with `status: "error"` are not charged. Platform usage is minimal (no browser, no proxy).

### Usage via API, n8n and MCP

**API** (synchronous, returns the dataset items):

```bash
curl -X POST "https://api.apify.com/v2/acts/fast_data_asap~ecb-exchange-rates-invoice-converter/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"amount":100,"currency":"USD","date":"2026-11-06"}]}'
```

**n8n / Make / Zapier:** use the Apify integration, actor `fast_data_asap/ecb-exchange-rates-invoice-converter`, and map your invoice rows to `items`.

**AI agents (MCP):** add `https://mcp.apify.com?tools=fast_data_asap/ecb-exchange-rates-invoice-converter` to Claude, Cursor or any MCP client. The agent can then convert amounts with the official ECB rates and cite `rateDate` and `sourceUrl`.

### Important notes

- **Source:** European Central Bank, euro foreign exchange reference rates (ECB Data Portal). This actor is not affiliated with or endorsed by the ECB.
- The ECB states that its reference rates are published **for information purposes only**. Using them for transactions or bookkeeping is your decision.
- **No tax or legal advice.** For VAT and other tax purposes, other rates may be required (in Germany, for example, the monthly average rates published by the Federal Ministry of Finance under § 16 (6) UStG). Check with your tax advisor which rate applies to you.
- The actor only calls the public ECB API with an identifying User-Agent, respects robots.txt, uses no proxies and processes no personal data. Your input amounts are only used to compute the result.

# Actor input Schema

## `mode` (type: `string`):

"convert": convert a list of invoice amounts (amount + currency + date). "rates": return the daily ECB reference rates for a list of currencies and a date range.

## `items` (type: `array`):

List of objects {"amount": 1250.00, "currency": "USD", "date": "2026-11-07", "id": "INV-1001"}. date = invoice or booking date (YYYY-MM-DD). Optional per-row "targetCurrency" overrides the global target currency.

## `targetCurrency` (type: `string`):

3-letter ISO code to convert into. Default EUR. Any ECB currency works (e.g. USD → GBP is calculated via the euro cross rate).

## `fallback` (type: `string`):

What to do when there is no ECB rate on the given date (weekend, TARGET holiday, today before ~16:00 CET): "previous" = last earlier fixing day, "next" = next fixing day, "none" = return an error row.

## `currencies` (type: `array`):

3-letter ISO codes of the currencies to list, e.g. USD, GBP, CHF.

## `startDate` (type: `string`):

YYYY-MM-DD. Default: 30 days before the end date.

## `endDate` (type: `string`):

YYYY-MM-DD. Default: today.

## Actor input object example

```json
{
  "mode": "convert",
  "items": [
    {
      "id": "INV-1001",
      "amount": 1250,
      "currency": "USD",
      "date": "2026-11-07"
    },
    {
      "id": "INV-1002",
      "amount": 480.5,
      "currency": "GBP",
      "date": "2026-11-05"
    },
    {
      "id": "INV-1003",
      "amount": 2999.9,
      "currency": "CHF",
      "date": "2026-10-30"
    }
  ],
  "targetCurrency": "EUR",
  "fallback": "previous",
  "currencies": [
    "USD",
    "GBP",
    "CHF",
    "JPY",
    "PLN"
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `overview` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "items": [
        {
            "id": "INV-1001",
            "amount": 1250,
            "currency": "USD",
            "date": "2026-11-07"
        },
        {
            "id": "INV-1002",
            "amount": 480.5,
            "currency": "GBP",
            "date": "2026-11-05"
        },
        {
            "id": "INV-1003",
            "amount": 2999.9,
            "currency": "CHF",
            "date": "2026-10-30"
        }
    ],
    "currencies": [
        "USD",
        "GBP",
        "CHF",
        "JPY",
        "PLN"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fast_data_asap/ecb-exchange-rates-invoice-converter").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "items": [
        {
            "id": "INV-1001",
            "amount": 1250,
            "currency": "USD",
            "date": "2026-11-07",
        },
        {
            "id": "INV-1002",
            "amount": 480.5,
            "currency": "GBP",
            "date": "2026-11-05",
        },
        {
            "id": "INV-1003",
            "amount": 2999.9,
            "currency": "CHF",
            "date": "2026-10-30",
        },
    ],
    "currencies": [
        "USD",
        "GBP",
        "CHF",
        "JPY",
        "PLN",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("fast_data_asap/ecb-exchange-rates-invoice-converter").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "items": [
    {
      "id": "INV-1001",
      "amount": 1250,
      "currency": "USD",
      "date": "2026-11-07"
    },
    {
      "id": "INV-1002",
      "amount": 480.5,
      "currency": "GBP",
      "date": "2026-11-05"
    },
    {
      "id": "INV-1003",
      "amount": 2999.9,
      "currency": "CHF",
      "date": "2026-10-30"
    }
  ],
  "currencies": [
    "USD",
    "GBP",
    "CHF",
    "JPY",
    "PLN"
  ]
}' |
apify call fast_data_asap/ecb-exchange-rates-invoice-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fast_data_asap/ecb-exchange-rates-invoice-converter"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ZDhNjmqvqALf0QofI/builds/M0kXYWFfXixEnNoPJ/openapi.json
