> ## Documentation Index
> Fetch the complete documentation index at: https://docs.beta.b3os.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Frankfurter exchange rates

The io.b3os/frankfurter pack: 5 actions with call snippets, fixture outputs, connection setup and error codes, generated from version 1.0.0.

`io.b3os/frankfurter` 1.0.0 · `finance`, `currency`, `open-data` · MIT

Foreign exchange reference rates published by the European Central Bank, through the free Frankfurter API (no key): latest and historical rates for the currencies the ECB publishes, time series between two dates, conversions and the currency list. Rates are published on working days only; weekends and holidays return the previous working day.

Every call's result carries `upstream_status` and `timing`: `validate_ms`, `inject_ms`, `render_ms`, `upstream_ms`, `map_ms` and `total_ms`. `upstream` is the service's time; the others are B3OS's own ([call actions](/actions/call)). The snippets below show no timing values, because a fixture records none.

## Connection

No credential: a keyless public API. Calls name no connection.

Hosts it reaches: `api.frankfurter.dev`.

## Actions

| Action | Effect | MCP tool | Title |
|---|---|---|---|
| [`latest-rates`](/actions/catalog/frankfurter#frankfurter-latest-rates) | read | `frankfurter__latest-rates` | Latest rates |
| [`historical-rates`](/actions/catalog/frankfurter#frankfurter-historical-rates) | read | `frankfurter__historical-rates` | Rates on a date |
| [`time-series`](/actions/catalog/frankfurter#frankfurter-time-series) | read | `frankfurter__time-series` | Rates time series |
| [`convert`](/actions/catalog/frankfurter#frankfurter-convert) | read | `frankfurter__convert` | Convert currency |
| [`list-currencies`](/actions/catalog/frankfurter#frankfurter-list-currencies) | read | `frankfurter__list-currencies` | List currencies |

latest-rates

**Latest rates.** The most recent ECB reference rates from a base currency to all others (or the symbols you list), multiplied by amount.

Ref `io.b3os/frankfurter/latest-rates@1.0.0` · effect `read` · no connection · MCP tool `frankfurter__latest-rates`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/frankfurter/latest-rates@1",
          "input": {"base": "USD", "symbols": ["EUR", "GBP", "JPY"]}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/frankfurter/latest-rates@1",
      input: { base: "USD", symbols: ["EUR", "GBP", "JPY"] },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/frankfurter/latest-rates@1",
        "input": {"base": "USD", "symbols": ["EUR", "GBP", "JPY"]},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "frankfurter__latest-rates",
        "arguments": {"base": "USD", "symbols": ["EUR", "GBP", "JPY"]}
      }
    }
    ```

    Expose the pack as tools with `--packs frankfurter` on the local server or `?packs=frankfurter` on the remote URL, and the agent calls `frankfurter__latest-rates` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Latest rates (response recorded 2026-10-26). From the bundle's `fixtures/latest-rates.json`, not a live call.

```json
{
  "base": "USD",
  "date": "2026-10-23",
  "amount": 1,
  "rates": {"EUR": 0.89342, "GBP": 0.74804, "JPY": 156.8}
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | Unknown currency, or no rates for that date (rates start on 1999-01-04). |
| `rate_limited` | 429 | yes | Frankfurter is rate limiting this address; retry shortly. |

historical-rates

**Rates on a date.** ECB reference rates on a past date (the last working day on or before it), from a base currency to all others or the symbols you list.

Ref `io.b3os/frankfurter/historical-rates@1.0.0` · effect `read` · no connection · MCP tool `frankfurter__historical-rates`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/frankfurter/historical-rates@1",
          "input": {"date": "2024-01-02", "base": "EUR", "symbols": ["USD", "CHF"]}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/frankfurter/historical-rates@1",
      input: { date: "2024-01-02", base: "EUR", symbols: ["USD", "CHF"] },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/frankfurter/historical-rates@1",
        "input": {"date": "2024-01-02", "base": "EUR", "symbols": ["USD", "CHF"]},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "frankfurter__historical-rates",
        "arguments": {"date": "2024-01-02", "base": "EUR", "symbols": ["USD", "CHF"]}
      }
    }
    ```

    Expose the pack as tools with `--packs frankfurter` on the local server or `?packs=frankfurter` on the remote URL, and the agent calls `frankfurter__historical-rates` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Rates on a date (response recorded 2026-10-26). From the bundle's `fixtures/historical-rates.json`, not a live call.

```json
{
  "base": "EUR",
  "date": "2024-01-02",
  "amount": 1,
  "rates": {"CHF": 0.9305, "USD": 1.0956}
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | Unknown currency, or no rates for that date (rates start on 1999-01-04). |
| `rate_limited` | 429 | yes | Frankfurter is rate limiting this address; retry shortly. |

time-series

**Rates time series.** Daily ECB reference rates between two dates (end defaults to the latest), keyed by date, for the symbols you list. List few symbols over long ranges: every working day is one entry.

Ref `io.b3os/frankfurter/time-series@1.0.0` · effect `read` · no connection · MCP tool `frankfurter__time-series`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/frankfurter/time-series@1",
          "input": {
            "start_date": "2026-10-19",
            "end_date": "2026-10-23",
            "base": "USD",
            "symbols": ["EUR"]
          }
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/frankfurter/time-series@1",
      input: {
        start_date: "2026-10-19",
        end_date: "2026-10-23",
        base: "USD",
        symbols: ["EUR"],
      },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/frankfurter/time-series@1",
        "input": {
            "start_date": "2026-10-19",
            "end_date": "2026-10-23",
            "base": "USD",
            "symbols": ["EUR"],
        },
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "frankfurter__time-series",
        "arguments": {
          "start_date": "2026-10-19",
          "end_date": "2026-10-23",
          "base": "USD",
          "symbols": ["EUR"]
        }
      }
    }
    ```

    Expose the pack as tools with `--packs frankfurter` on the local server or `?packs=frankfurter` on the remote URL, and the agent calls `frankfurter__time-series` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Rates time series (response recorded 2026-10-26). From the bundle's `fixtures/time-series.json`, not a live call.

```json
{
  "base": "USD",
  "start_date": "2026-10-19",
  "end_date": "2026-10-23",
  "rates": {
    "2026-10-19": {"EUR": 0.89087},
    "2026-10-20": {"EUR": 0.89166},
    "2026-10-21": {"EUR": 0.89015},
    "2026-10-22": {"EUR": 0.89246},
    "2026-10-23": {"EUR": 0.89342}
  }
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | Unknown currency, or no rates for that date (rates start on 1999-01-04). |
| `rate_limited` | 429 | yes | Frankfurter is rate limiting this address; retry shortly. |

convert

**Convert currency.** Convert an amount from one currency to another at the latest ECB reference rate (or on a past date), returning the converted amount and the rate.

Ref `io.b3os/frankfurter/convert@1.0.0` · effect `read` · no connection · MCP tool `frankfurter__convert`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
          "ref": "io.b3os/frankfurter/convert@1",
          "input": {"amount": 250, "from": "GBP", "to": "USD"}
        }'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({
      ref: "io.b3os/frankfurter/convert@1",
      input: { amount: 250, from: "GBP", to: "USD" },
    });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({
        "ref": "io.b3os/frankfurter/convert@1",
        "input": {"amount": 250, "from": "GBP", "to": "USD"},
    })
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {
        "name": "frankfurter__convert",
        "arguments": {"amount": 250, "from": "GBP", "to": "USD"}
      }
    }
    ```

    Expose the pack as tools with `--packs frankfurter` on the local server or `?packs=frankfurter` on the remote URL, and the agent calls `frankfurter__convert` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: Convert currency (response recorded 2026-10-26). From the bundle's `fixtures/convert.json`, not a live call.

```json
{
  "amount": 250,
  "from": "GBP",
  "to": "USD",
  "date": "2026-10-23",
  "result": 334.2,
  "rate": 1.3368
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | Unknown currency, or no rates for that date (rates start on 1999-01-04). |
| `rate_limited` | 429 | yes | Frankfurter is rate limiting this address; retry shortly. |

list-currencies

**List currencies.** Every currency Frankfurter has ECB rates for, as ISO 4217 code to English name.

Ref `io.b3os/frankfurter/list-currencies@1.0.0` · effect `read` · no connection · MCP tool `frankfurter__list-currencies`

**curl**

```bash
    curl -s https://beta-api.b3os.org/v1/actions/call \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"ref": "io.b3os/frankfurter/list-currencies@1", "input": {}}'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const result = await b3os.actions.call({ ref: "io.b3os/frankfurter/list-currencies@1", input: {} });
    console.log(result.output);
    ```
  **Python**

```python
    from b3os import B3OS

    b3os = B3OS()
    result = b3os.actions.call({"ref": "io.b3os/frankfurter/list-currencies@1", "input": {}})
    print(result["output"])
    ```
  **MCP**

```json
    {
      "method": "tools/call",
      "params": {"name": "frankfurter__list-currencies", "arguments": {}}
    }
    ```

    Expose the pack as tools with `--packs frankfurter` on the local server or `?packs=frankfurter` on the remote URL, and the agent calls `frankfurter__list-currencies` with the action's input. The tool needs no connection. Without exposing the pack, `actions_call` takes the same input with `ref`.

Output, labeled `fixture`: List currencies (response recorded 2026-10-26). From the bundle's `fixtures/list-currencies.json`, not a live call.

```json
{
  "currencies": {
    "AUD": "Australian Dollar",
    "BRL": "Brazilian Real",
    "CAD": "Canadian Dollar",
    "CHF": "Swiss Franc",
    "CNY": "Chinese Renminbi Yuan",
    "CZK": "Czech Koruna",
    "DKK": "Danish Krone",
    "EUR": "Euro",
    "GBP": "British Pound",
    "HKD": "Hong Kong Dollar",
    "HUF": "Hungarian Forint",
    "IDR": "Indonesian Rupiah",
    "ILS": "Israeli New Shekel",
    "INR": "Indian Rupee",
    "ISK": "Icelandic Króna",
    "JPY": "Japanese Yen",
    "KRW": "South Korean Won",
    "MXN": "Mexican Peso",
    "MYR": "Malaysian Ringgit",
    "NOK": "Norwegian Krone",
    "NZD": "New Zealand Dollar",
    "PHP": "Philippine Peso",
    "PLN": "Polish Złoty",
    "RON": "Romanian Leu",
    "SEK": "Swedish Krona",
    "SGD": "Singapore Dollar",
    "THB": "Thai Baht",
    "TRY": "Turkish Lira",
    "USD": "United States Dollar",
    "ZAR": "South African Rand"
  }
}
```

When the service answers with an error, the call fails with [`upstream_error`](/errors#upstream_error) and `pack_error.code` is one of:

| `pack_error.code` | Service status | Retryable | Message |
|---|---|---|---|
| `not_found` | 404 | no | Unknown currency, or no rates for that date (rates start on 1999-01-04). |
| `rate_limited` | 429 | yes | Frankfurter is rate limiting this address; retry shortly. |