# ECB Euro Reference FX: Rolling Window Rates (`thatmike1/eu-ecb-reference-fx-window`) Actor

Export published ECB EUR-base reference rates from the rolling XML feed with exact decimal strings, publication dates and explicit missing-currency/date outcomes.

- **URL**: https://apify.com/thatmike1/eu-ecb-reference-fx-window.md
- **Developed by:** [Michal Pšenčík](https://apify.com/thatmike1) (community)
- **Categories:** Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Euro Reference FX: Rolling Window Rates

Export the European Central Bank's euro foreign exchange reference rates for the currencies and recent dates you choose, one dataset row per published date and currency, straight from the ECB's official rolling reference-rate file. Each row keeps the rate exactly as the ECB writes it (a decimal string, trailing digits untouched), states what it means (units of the quote currency for one euro), and carries the source URL with the SHA-256 of the file it came from. It is meant for small cost dashboards, reference-data notebooks and periodic reports that refresh the last week or so of rates without maintaining XML parsing themselves.

This is a narrow export of one official, informational series. The ECB publishes these rates for information only; they are not intended for market transactions, and this is not an execution quote, a live price or financial advice. The actor does not compute cross rates, inverse rates, averages or conversions, does not fill weekends or holidays, and covers only what the ECB's rolling file holds (about the last three months of publication days). It is independent of the ECB and not endorsed by it.

### Input

```json
{
    "currencies": ["USD", "GBP", "CZK"],
    "startDate": "2026-10-16",
    "endDate": "2026-10-22",
    "maxItems": 1000
}
```

- `currencies`: 1 to 10 three-letter codes, quoted against EUR. Surrounding spaces are trimmed and letters uppercased; duplicates collapse to the first occurrence and are billed once. Default `["USD", "GBP", "CZK"]`. `EUR` itself is refused, because the ECB publishes no EUR/EUR quotation. A code the ECB does not publish (for example RUB, suspended since 2022, or a mistyped code) is accepted and reported free as missing; it never becomes a rate.
- `endDate`: last publication date, `YYYY-MM-DD`, no later than today (UTC). Default: today.
- `startDate`: first publication date, `YYYY-MM-DD`, no earlier than 89 days before today (UTC). Default: six days before `endDate` (never earlier than that limit).
- `maxItems`: stop after this many rows are stored, 1 to 1000. Default 1000; ten currencies over 90 days is at most 900 rows.

The defaults are resolved once, from the UTC date at the start of the run, and recorded in `SUMMARY`. Unknown fields, `null`, wrong types, impossible dates, a reversed range and out-of-range values fail the run before any source request, with the reason in `SUMMARY`.

### Output

One row per published date and requested currency, dates ascending, currencies in input order within a date:

```json
{
    "schemaVersion": 1,
    "recordId": "ecb-fxref:2026-10-16:EUR:USD",
    "deliveryId": "1ac5e099ee8121b51878843ec2882841822b5052984a5929031c66fc10e34050",
    "observedAt": "2026-10-22T21:34:15.321Z",
    "contentHash": "5a8cc6c5c388d062e4d99ba529be8edfb5f8c4abe304abb16a1d9d1d839af936",
    "provenance": [
        {
            "url": "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml",
            "sha256": "de1353c5b67ed4c04f1e9c1f7246fec82f8ddc6041880ef0b1345f82157e197b"
        }
    ],
    "sourceDate": "2026-10-16",
    "baseCurrency": "EUR",
    "quoteCurrency": "USD",
    "rate": "1.1253",
    "rateMeaning": "quote_units_per_1_EUR",
    "kind": "ECB_reference_not_transaction"
}
```

- `rate` is a string holding the ECB's exact digits: 1 EUR = 1.1253 USD here. It is never the inverse, never rounded, and never passed through a floating-point number.
- `sourceDate` is the ECB publication date (a calendar date, no time zone). The ECB normally publishes around 16:00 CET on working days, excluding TARGET closing days, so today's rate may not exist yet when the run starts.
- `recordId` is stable across runs for the same date and currency. `contentHash` is the SHA-256 of the six source fields (keys sorted, compact JSON), so a corrected rate changes it and an unchanged repeat keeps it. `deliveryId` identifies this run's delivery of the row. `observedAt` is when the source file finished downloading.

A requested date or currency with no published rate gets no row. It is listed in `SUMMARY` instead: dates outside the file's current oldest..newest span as `outside_current_publication_window`, days inside the span with no publication (weekends, holidays) as `no_source_publication`, and published days without that currency as `currency_not_quoted`. These are never zero rates, carried-forward rates or claims about why the rate is absent. The whole file is validated before any row is delivered; if anything in it is malformed or contradictory, no rows are delivered and the reason goes to `SUMMARY`.

Export the dataset as JSON, CSV or Excel from the run's Storage tab or the API.

### Run summary (free)

Every run writes a `SUMMARY` record to its key-value store, also on failure: run status (`complete`, `partial`, `failed` or `capped`), the resolved input, request, byte and row counts, and one outcome per currency (`delivered`, `empty`, `missing`, `error` or `not_attempted`) with an error code, HTTP status and warnings. The warnings give the requested range, the file's current oldest and newest publication date, how many publication dates fell in your range, and every missing date for that currency. `empty` means no publication date fell in the range at all (for example a weekend-only range); `missing` means dates were published but never for this currency. When a cap stops the run, `firstUndeliveredKey` names the first date and currency left undelivered, so you can rerun from there.

### Pricing

Pay per event **plus platform usage**: besides the two events below, you pay the Apify platform usage of your own run (compute, storage and data transfer) at your plan's rates.

- **$0.00005** per Actor start (one start unit at the default 256 MB).
- **$0.0001** per date/currency rate stored in the dataset, including unchanged repeats.

The default run (three currencies, the last seven days) usually stores 12 to 15 rows, fewer in holiday weeks: $0.00125 to $0.00155 in events. One row costs $0.00015, ten $0.00105, the 900-row maximum $0.09005. A run finishes in seconds; at 256 MB it stops its own work after 300 seconds, so compute is at most about 0.021 compute units. Missing dates and currencies, failed runs and the `SUMMARY` record are free; a run that delivers no rows costs only the start fee. Every run fetches the current file and bills its rows again, even when nothing changed. There are no change alerts and no saved state between runs.

### Limits and behaviour

- One anonymous HTTPS GET per run to `https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml`, whatever the currencies or dates; no key, login, cookies, browser or proxy. The daily file, the full-history file and the ECB Data Portal are never used as fallbacks.
- Timeouts, connection resets and 5xx responses are retried twice (2 s, then 5 s, or longer if the source asks with `Retry-After`, up to 60 s), with at least 1.2 seconds between requests. A 403, 429, challenge page or HTML instead of XML stops the run without retry.
- Per run: 100 HTTP attempts, 4 MiB per response, 16 MiB of responses in total, 300 seconds of work. The file may hold at most 100 publication days and 50 currencies per day.
- No history beyond the rolling file, no revision tracking and no saved state between runs. A corrected rate appears under the same `recordId` with a new `contentHash`; earlier values are not reconstructed.

### Support

Open an issue on the Actor's Issues tab. Source documentation: [ECB euro foreign exchange reference rates](https://www.ecb.europa.eu/stats/policy_and_exchange_rates/euro_reference_exchange_rates/html/index.en.html) and the [ECB framework for the reference rates](https://www.ecb.europa.eu/stats/pdf/exchange/Frameworkfortheeuroforeignexchangereferencerates.en.pdf).

# Actor input Schema

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

1 to 10 three-letter currency codes, quoted against EUR (for example USD, GBP, CZK, JPY, CHF, PLN). Spaces are trimmed and letters uppercased; duplicates are delivered and billed once. EUR itself is rejected. A code the ECB does not publish (for example RUB, suspended since 2022) is reported free as missing, never as a rate.

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

First publication date to include, no earlier than 89 days before today (UTC). Leave empty for six days before the last date.

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

Last publication date to include, no later than today (UTC). Leave empty for today. The ECB publishes around 16:00 CET on working days, so today's rate may not exist yet.

## `maxItems` (type: `integer`):

Stop after this many date/currency rows are stored (each one is a billed dataset item). Ten currencies over 90 days is at most 900 rows.

## Actor input object example

```json
{
  "currencies": [
    "USD",
    "GBP",
    "CZK"
  ],
  "maxItems": 1000
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

## `summary` (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 = {
    "currencies": [
        "USD",
        "GBP",
        "CZK"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("thatmike1/eu-ecb-reference-fx-window").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 = { "currencies": [
        "USD",
        "GBP",
        "CZK",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("thatmike1/eu-ecb-reference-fx-window").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 '{
  "currencies": [
    "USD",
    "GBP",
    "CZK"
  ]
}' |
apify call thatmike1/eu-ecb-reference-fx-window --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thatmike1/eu-ecb-reference-fx-window"
        }
    }
}
```

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/QJduzyFDGREl7QF7A/builds/9jc8jXJQtPTomkPPX/openapi.json
