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). 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 | read | frankfurter__latest-rates | Latest rates |
historical-rates | read | frankfurter__historical-rates | Rates on a date |
time-series | read | frankfurter__time-series | Rates time series |
convert | read | frankfurter__convert | Convert currency |
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
bashcurl -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"]} }'
tsimport { 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);
pythonfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/frankfurter/latest-rates@1", "input": {"base": "USD", "symbols": ["EUR", "GBP", "JPY"]},})print(result["output"])
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 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
bashcurl -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"]} }'
tsimport { 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);
pythonfrom b3os import B3OSb3os = 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"])
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 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
bashcurl -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"] } }'
tsimport { 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);
pythonfrom b3os import B3OSb3os = 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"])
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 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
bashcurl -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"} }'
tsimport { 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);
pythonfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({ "ref": "io.b3os/frankfurter/convert@1", "input": {"amount": 250, "from": "GBP", "to": "USD"},})print(result["output"])
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 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
bashcurl -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": {}}'
tsimport { 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);
pythonfrom b3os import B3OSb3os = B3OS()result = b3os.actions.call({"ref": "io.b3os/frankfurter/list-currencies@1", "input": {}})print(result["output"])
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 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. |