<!-- Agent Datasets docs · Foreign Exchange guide · canonical: https://www.agentdatasets.com/docs/guides/fx · rendered from https://www.agentdatasets.com -->

# Foreign Exchange

Daily ECB euro reference rates and EUR-triangulated conversions.

## Where the data comes from

Every value this category returns is attributable to one of these publishers, and every payload carries the source tag with it.

| Source | Publisher | What we hold | Licence |
| --- | --- | --- | --- |
| `ecb` | European Central Bank | Ten curated ECB key-interest-rate, €STR, and euro-area AAA central-government yield-curve spot-rate series | ECB information reuse terms (ecb-reuse) |

**Required notices.**

- Reproduced ECB information must appear accurately and cite the ECB as source.
- Where ECB information is incorporated in documents that are sold, buyers must be informed that the information is available free of charge from the ECB website.
- The ECB does not charge for the €STR or license its use.

## How the rates work

The euro is always the pivot. A pair with EUR on one side is served from the published fixing directly, or as its inverse; any other pair is triangulated through the euro, flagged `derived: true`, and names the arithmetic it used in `meta.derived_method`. That flag is the whole story an agent needs about how much processing sits between the publisher and the number — check it before you quote a rate as published.

Dates resolve rather than fail. Ask for a weekend or a holiday and you get the newest prior fixing, with `requested_date` and `rate_date` both echoed in the payload so the substitution is visible instead of silent. Values are exact decimal strings, never floats.

## Worked workflows

### Convert one amount on one date

The single-answer path. Give it an amount, two currencies, and optionally a date:

```python
fx_convert(amount="1000", from_currency="USD", to_currency="EUR", date="2026-08-07")
```

The payload is scalar — one object, no list, and `pagination` is `null`:

```json
{
  "data": {
    "amount": "1000",
    "from_currency": "USD",
    "to_currency": "EUR",
    "requested_date": "2026-08-07",
    "rate_date": "2026-08-07",
    "rate": "0.914500",
    "converted": "914.500000",
    "derived": false,
    "unit": "EUR per USD",
    "currency": "EUR",
    "as_of": "2026-08-07T16:00:00Z"
  },
  "meta": {
    "source": "ecb",
    "as_of": "2026-08-07T16:00:00Z",
    "attribution": "...",
    "derived_method": "conversion from ECB reference rate"
  },
  "pagination": null
}
```

Values above are illustrative; the field names are the real ones. Omit `date` for the latest available fixing.

### Read a fixing series

For history — a chart, a volatility calculation, a period average — ask for the series rather than looping conversions:

```python
fx_get_rates(base="EUR", quote="USD", start="2026-08-01", end="2026-08-07", limit=100)
```

```json
{
  "data": {
    "base": "EUR",
    "quote": "USD",
    "unit": "USD per EUR",
    "currency": "USD",
    "rates": [
      { "date": "2026-08-07", "value": "1.093400", "as_of": "2026-08-07T16:00:00Z", "derived": false }
    ]
  },
  "meta": { "source": "ecb", "as_of": "2026-08-07T16:00:00Z", "attribution": "...", "derived_method": null },
  "pagination": { "limit": 100, "has_more": true, "next_cursor": "eyJ2IjoxLCJrIjpbLi4uXX0" }
}
```

Rates come back newest-first. When `has_more` is true, continue with the cursor and every other argument unchanged:

```python
fx_get_rates(base="EUR", quote="USD", start="2026-08-01", end="2026-08-07", limit=100, cursor="eyJ2IjoxLCJrIjpbLi4uXX0")
```

### Cross two non-euro currencies

Nothing special is required — ask for the pair and read the flag:

```python
fx_get_rates(base="GBP", quote="JPY", limit=30)
```

Every rate in that response carries `derived: true`, and `meta.derived_method` states the triangulation. Treat a derived cross as what it is: two reference fixings divided, not a quoted market cross.

## Coverage and caveats

- **These are reference rates, not prices.** The ECB publishes them for information purposes only and strongly discourages using them for transaction purposes. They are not transaction or execution prices, and no tool here will turn them into one.
- **Coverage is the euro reference set.** A currency the ECB does not publish against the euro is a `bad_parameter`, not an empty result. A date outside the published history comes back as `out_of_coverage` from `fx_convert`.
- **A reversed date window or an unparseable cursor is `bad_parameter` too** — the surface refuses ambiguous input rather than guessing at it.
- **Check freshness before you trust recency.** `platform_get_freshness(limit=50)` reports the last successful refresh and the freshest value timestamp for the FX dataset, so an agent can tell "the market did not move" from "our connector has not run".

## Tools and endpoints

| Tool | What it does | Reference |
| --- | --- | --- |
| `fx_convert` | Convert one amount with ECB reference rates and explicit date resolution. | https://www.agentdatasets.com/docs/tools/fx_convert.md |
| `fx_get_rates` | Get daily ECB euro reference rates or EUR-triangulated cross-rates. | https://www.agentdatasets.com/docs/tools/fx_get_rates.md |

Over HTTP: https://www.agentdatasets.com/docs/rest/fx.md
