# ECB Exchange Rates and Riksbank Policy Rate (EUR, SEK) (`nightwave-owner/ecb-exchange-rates`) Actor

Returns official ECB euro reference exchange rates (daily or monthly averages) for about 30 currencies, against EUR or as SEK cross rates, plus optional ECB key interest rates and the Riksbank policy rate. Supports onlyNew for scheduled runs.

- **URL**: https://apify.com/nightwave-owner/ecb-exchange-rates.md
- **Developed by:** [Viktor Wiberg](https://apify.com/nightwave-owner) (community)
- **Categories:** Developer tools, AI, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 rates

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 and Riksbank Policy Rate (EUR, SEK)

Official euro foreign exchange reference rates from the European Central Bank, daily or as monthly averages, for about 30 currencies. Get them as the ECB publishes them (units of a currency per 1 euro) or as Swedish krona cross rates, and add the ECB key interest rates and the Riksbank policy rate when you need them. One clean row per date and currency, with the source series and the license on every row.

Typical uses: converting invoices and ledgers at the official reference rate of a given day, monthly average rates for accounting and reporting, filling a currency table in an ERP or BI tool, and following when the ECB or the Riksbank changes its policy rate. The actor only delivers data. It gives no advice.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `currencies` | array | `USD`, `SEK`, `GBP`, `NOK`, `DKK` | ISO 4217 codes. With base `SEK` the default list has `EUR` in place of `SEK`. |
| `base` | string | `EUR` | `EUR` gives the ECB rates as published. `SEK` gives cross rates per 1 Swedish krona. |
| `dateFrom` | string | 7 days before `dateTo` (daily), 11 months before (monthly) | `YYYY-MM-DD`, or `YYYY-MM` for monthly. History starts on 1999-01-04. |
| `dateTo` | string | today in Frankfurt | Last date, inclusive. |
| `frequency` | string | `daily` | `daily` or `monthly` (the ECB monthly average). |
| `includePolicyRates` | boolean | `false` | Adds the ECB deposit facility, main refinancing operations and marginal lending facility rates, and the Riksbank policy rate. |
| `onlyNew` | boolean | `false` | Return only rows that earlier runs with the same input did not deliver. See "Monitoring and scheduling". |
| `maxResults` | integer | `50` | Maximum number of rows, newest first. 1 to 10 000. |

A run with empty input returns the last week of daily reference rates for USD, SEK, GBP, NOK and DKK against the euro: 25 rows on a normal week.

Currencies with current ECB reference rates: AUD, BGN, BRL, CAD, CHF, CNY, CZK, DKK, GBP, HKD, HUF, IDR, ILS, INR, ISK, JPY, KRW, MXN, MYR, NOK, NZD, PHP, PLN, RON, SEK, SGD, THB, TRY, USD, ZAR. Discontinued currencies (for example HRK, RUB and the pre-euro currencies) return history up to their last date.

Example input, used for the output below:

```json
{
  "base": "SEK",
  "currencies": ["USD", "EUR"],
  "dateFrom": "2026-09-28",
  "dateTo": "2026-10-02",
  "includePolicyRates": true,
  "maxResults": 50
}
```

### Output

| Field | Description |
|---|---|
| `type` | `exchangeRate` or `policyRate` |
| `date` | `YYYY-MM-DD`, or `YYYY-MM` for monthly rows |
| `base` | `EUR` or `SEK` for exchange rates, `null` for policy rates |
| `currency` | The quoted currency. For policy rates, the currency area (`EUR` or `SEK`) |
| `rate` | Units of `currency` per 1 `base`. For policy rates, the rate in percent per year |
| `inverseRate` | Units of `base` per 1 `currency`, for example SEK per USD. `null` for policy rates |
| `rateName` | What the number is, for example `USD per 1 SEK` or `Riksbank policy rate` |
| `unit` | The unit of `rate` |
| `frequency` | `daily` or `monthly` |
| `derived` | `true` when the rate is a cross rate calculated from two ECB series |
| `source`, `series`, `license` | The publisher, the exact series key and the reuse terms |

Rows from the cloud run with the example input above (run `5DALpJY51gQX8PfAo`, 2026-10-03, 30 rows; 2 of 30 shown):

```json
{
  "type": "exchangeRate",
  "date": "2026-10-02",
  "base": "SEK",
  "currency": "USD",
  "rate": 0.0994243,
  "inverseRate": 10.0579,
  "rateName": "USD per 1 SEK",
  "unit": "USD",
  "frequency": "daily",
  "derived": true,
  "source": "European Central Bank, euro foreign exchange reference rates (ECB Data Portal)",
  "series": "EXR.D.USD.EUR.SP00.A / EXR.D.SEK.EUR.SP00.A",
  "license": "Source: ECB statistics. Free reuse with the source quoted, ECB statistics reuse policy"
}
{
  "type": "policyRate",
  "date": "2026-10-02",
  "base": null,
  "currency": "SEK",
  "rate": 1.75,
  "inverseRate": null,
  "rateName": "Riksbank policy rate",
  "unit": "percent per year",
  "frequency": "daily",
  "derived": false,
  "source": "Sveriges Riksbank, interest rates and exchange rates API (SWEA)",
  "series": "SECBREPOEFF",
  "license": "Source: Sveriges Riksbank. Free to use and adapt without permission or agreement"
}
```

### Example from a real run

Input:

```json
{
  "currencies": [
    "USD",
    "SEK"
  ],
  "maxResults": 5
}
```

Output (first 3 of 5 rows, values unchanged):

```json
[
  {
    "type": "exchangeRate",
    "date": "2026-10-02",
    "base": "EUR",
    "currency": "SEK",
    "rate": 11.29,
    "inverseRate": 0.088574,
    "rateName": "SEK per 1 EUR",
    "unit": "SEK",
    "frequency": "daily",
    "derived": false,
    "source": "European Central Bank, euro foreign exchange reference rates (ECB Data Portal)",
    "series": "EXR.D.SEK.EUR.SP00.A",
    "license": "Source: ECB statistics. Free reuse with the source quoted, ECB statistics reuse policy"
  },
  {
    "type": "exchangeRate",
    "date": "2026-10-02",
    "base": "EUR",
    "currency": "USD",
    "rate": 1.1225,
    "inverseRate": 0.890869,
    "rateName": "USD per 1 EUR",
    "unit": "USD",
    "frequency": "daily",
    "derived": false,
    "source": "European Central Bank, euro foreign exchange reference rates (ECB Data Portal)",
    "series": "EXR.D.USD.EUR.SP00.A",
    "license": "Source: ECB statistics. Free reuse with the source quoted, ECB statistics reuse policy"
  },
  {
    "type": "exchangeRate",
    "date": "2026-10-01",
    "base": "EUR",
    "currency": "SEK",
    "rate": 11.331,
    "inverseRate": 0.0882535,
    "rateName": "SEK per 1 EUR",
    "unit": "SEK",
    "frequency": "daily",
    "derived": false,
    "source": "European Central Bank, euro foreign exchange reference rates (ECB Data Portal)",
    "series": "EXR.D.SEK.EUR.SP00.A",
    "license": "Source: ECB statistics. Free reuse with the source quoted, ECB statistics reuse policy"
  }
]
```

Run sEQP32eEb9GBodcHz on 2026-10-04, 5 rows, 109 seconds.

### How the krona rates are calculated

The ECB quotes every currency against the euro. With base `SEK` the actor divides the two ECB rates of the same day: USD per SEK = (USD per EUR) / (SEK per EUR). Those rows have `derived: true` and both series keys in `series`. EUR per SEK is the inverse of the ECB's own SEK rate and is not marked as derived. Rates are rounded to six significant digits.

Cross rates calculated this way can differ slightly from the Riksbank's own SEK fixings, which are set at a different time of day. For monthly rows the krona rate is the ratio of the two ECB monthly averages.

### Good to know

- **Reference rates are not trading rates.** The ECB sets them once a day around 14:10 CET and publishes them around 16:00 CET on TARGET business days. There are no rates on weekends and on TARGET holidays, so a run for a Saturday returns 0 exchange rate rows.
- **Policy rates.** The ECB series have a value for every calendar day. The Riksbank series has a value for every Swedish banking day. With `monthly` the actor returns the rate in force on the last day with a value in each month; for the current month that is the latest day so far.
- **Why the Riksbank exchange rates are not used.** The Riksbank API answers at most 5 calls per minute and 1 000 per day from one IP address without a personal key. Apify runs share IP addresses, so one call per currency would be throttled. The actor makes a single call to the Riksbank, for the policy rate, and takes all exchange rates from the ECB.
- **Polite to the sources.** One request to the ECB for all exchange rates, one for the ECB policy rates and one to the Riksbank. Each request is retried up to four times (2, 4, 8 and 16 seconds) on network errors, 429 and 5xx, since the ECB Data Portal answers 504 now and then. An answer in an unexpected format stops the run with a clear message instead of storing broken rows.
- Unknown currency codes stop the run with the list of valid codes.

### Monitoring and scheduling

Set `onlyNew` to `true` to use the actor for a daily feed. The actor then remembers which rows it has delivered for the same input, in a named key-value store in your Apify account (`nightwave-state-ecb-exchange-rates`, one record per input). Each run returns and charges only rows that earlier runs did not deliver. The first run returns everything in the selection, and a run without news finishes successfully with 0 rows.

A row is identified by type, frequency, base, currency, series and date. Leave the dates empty so that every run covers the last week up to today. `onlyNew` and `maxResults` are not part of the remembered input, so you can change them without starting over. Changing any other field starts a fresh state. To start over with the same input, delete the record in the key-value store.

Example: a run every weekday at 16:30 Central European time that adds the day's krona rates and any policy rate change to your dataset. In Apify Console, open **Schedules**, create a schedule with the cron expression `30 16 * * 1-5`, timezone `Europe/Stockholm`, and add this actor with the input below.

```json
{
  "base": "SEK",
  "currencies": ["EUR", "USD", "GBP", "NOK", "DKK"],
  "includePolicyRates": true,
  "onlyNew": true,
  "maxResults": 100
}
```

The same schedule through the Apify API:

```sh
curl -X POST "https://api.apify.com/v2/schedules?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"name": "daily-sek-rates", "cronExpression": "30 16 * * 1-5", "timezone": "Europe/Stockholm", "isEnabled": true, "isExclusive": true,
       "actions": [{"type": "RUN_ACTOR", "actorId": "nightwave-owner~ecb-exchange-rates",
                    "runInput": {"contentType": "application/json", "body": "{\"base\":\"SEK\",\"currencies\":[\"EUR\",\"USD\",\"GBP\",\"NOK\",\"DKK\"],\"includePolicyRates\":true,\"onlyNew\":true,\"maxResults\":100}"}}]}'
```

If you prefer a daily schedule, use `30 16 * * *` instead. The ECB does not publish reference rates on weekends (or on TARGET holidays), so with `onlyNew` a daily run returns 0 new rows on Saturday and Sunday and costs only the small platform usage of the run.

### Data sources and licenses

- **ECB Data Portal**, `https://data-api.ecb.europa.eu/service/data/EXR/...` for the euro reference rates and `.../FM/D.U2.EUR.4F.KR....LEV` for the key ECB interest rates ([API documentation](https://data.ecb.europa.eu/help/api/overview)). No key is needed. Under the [ECB policy on the reuse of ESCB statistics](https://www.ecb.europa.eu/stats/ecb_statistics/governance_and_quality_framework/html/usage_policy.en.html), publicly available statistics may be reused free of charge, also commercially, provided the source is quoted ("Source: ECB statistics.") and the statistics are not modified. The krona cross rates are calculated by this actor, are marked with `derived: true`, and both original series are named on each row.
- **Sveriges Riksbank SWEA API**, `https://api.riksbank.se/swea/v1/Observations/SECBREPOEFF/...` for the policy rate ([about the API](https://www.riksbank.se/en-gb/statistics/interest-rates-and-exchange-rates/retrieving-interest-rates-and-exchange-rates-via-api/)). No key is needed. According to the Riksbank the data is free of charge and may be adapted and used without permission or agreement.

Every row carries `source` and `license` so you can credit the publisher. This actor is not affiliated with or endorsed by the European Central Bank or Sveriges Riksbank.

### Pricing

Pay per result: 0.002 USD per row returned (event `rate`), which is 2.00 USD per 1 000 rows. On top of that you pay Apify for the platform usage of your run, which is small: the test run that returned 1 000 rows (run `8FCGU943Q6EeHDgYq`, 2026-10-03) used 0.0052 USD. `maxResults` caps how many rows a run returns, and so what a run can cost.

Rows are delivered only after they have been charged. If you set a maximum cost per run (maxTotalChargeUsd), the run stops there and its status message says how many rows were delivered.

### Contact

Built and maintained by Nightwave AB. Questions, bugs and feature requests: kontakt@nightwave.se

### På svenska

Actorn hämtar Europeiska centralbankens officiella referenskurser för euron, dagligen eller som månadsgenomsnitt, för ett 30-tal valutor. Välj bas `EUR` för kurserna som ECB publicerar dem, eller `SEK` för korskurser per svensk krona (`inverseRate` ger kronor per enhet, till exempel SEK per USD). Med `includePolicyRates` tillkommer ECB:s styrräntor (inlåningsränta, refiränta och utlåningsränta) och Riksbankens styrränta.

Exempel från en verklig körning: input och de första raderna i outputen finns i avsnittet Example from a real run ovan (körning sEQP32eEb9GBodcHz, 2026-10-04, 5 rader, 109 sekunder).

- Kronkurserna räknas fram ur två ECB-kurser samma dag och har `derived: true`. De kan skilja sig något från Riksbankens egna kurser, som sätts vid en annan tid på dagen.
- Riksbankens valutakurser används inte: utan personlig nyckel tillåter Riksbankens API 5 anrop per minut och 1 000 per dygn per IP-adress, och Apify-körningar delar IP-adresser. Actorn gör därför bara ett anrop till Riksbanken, för styrräntan.
- Tom input ger senaste veckans dagliga kurser för USD, SEK, GBP, NOK och DKK mot euro, 25 rader en vanlig vecka. `maxResults` är som standard 50.
- Med `onlyNew: true` levereras bara rader som tidigare körningar med samma input inte har levererat. Det passar för schemalagda körningar (se "Monitoring and scheduling").
- Källor: ECB Data Portal (fri återanvändning med källangivelse, "Source: ECB statistics.") och Riksbankens API (fritt att använda och bearbeta utan tillstånd). Endast data, inga råd.
- Pris: 0,002 USD per rad (2,00 USD per 1 000), plus Apifys plattformsanvändning.
- Kontakt: kontakt@nightwave.se

# Actor input Schema

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

ISO 4217 codes, for example USD, SEK, GBP, NOK, DKK, CHF, JPY. About 30 currencies have current ECB reference rates, see the README. EUR is allowed when the base is SEK. Empty gives USD, SEK, GBP, NOK and DKK.

## `base` (type: `string`):

EUR gives the ECB rates as published: units of the currency per 1 euro. SEK gives cross rates per 1 Swedish krona, calculated from the ECB rates, with SEK per unit of the currency in inverseRate. Example: SEK.

## `dateFrom` (type: `string`):

First date, YYYY-MM-DD (or YYYY-MM for monthly). Example: 2026-09-01. Empty gives 7 days before the end date (daily) or 11 months before it (monthly). History starts 1999-01-04.

## `dateTo` (type: `string`):

Last date, inclusive, YYYY-MM-DD (or YYYY-MM for monthly). Example: 2026-09-30. Empty gives today in Frankfurt time.

## `frequency` (type: `string`):

daily gives one reference rate per TARGET business day. monthly gives the ECB monthly average per month, and the policy rate in force at the end of each month.

## `includePolicyRates` (type: `boolean`):

Adds rows for the ECB deposit facility rate, main refinancing operations rate and marginal lending facility rate, and the Riksbank policy rate, in percent per year.

## `maxResults` (type: `integer`):

Maximum number of rows, newest first. Example: 50. 1 to 10 000.

## `onlyNew` (type: `boolean`):

For scheduled runs: return only rows that earlier runs with the same input did not deliver. The first run returns everything.

## Actor input object example

```json
{
  "currencies": [
    "USD",
    "SEK",
    "GBP"
  ],
  "base": "SEK",
  "dateFrom": "2026-09-01",
  "dateTo": "2026-09-30",
  "frequency": "monthly",
  "includePolicyRates": true,
  "maxResults": 50,
  "onlyNew": false
}
```

# Actor output Schema

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

All rows produced by the run, as JSON. Open in Apify Console or download via the dataset API.

# 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",
        "SEK",
        "GBP",
        "NOK",
        "DKK"
    ],
    "maxResults": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("nightwave-owner/ecb-exchange-rates").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",
        "SEK",
        "GBP",
        "NOK",
        "DKK",
    ],
    "maxResults": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("nightwave-owner/ecb-exchange-rates").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",
    "SEK",
    "GBP",
    "NOK",
    "DKK"
  ],
  "maxResults": 50
}' |
apify call nightwave-owner/ecb-exchange-rates --silent --output-dataset

```

## MCP server setup

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

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/vkhbfw1z3wUt1kN5c/builds/O70hTaJVT4bT3R7Dc/openapi.json
