Help us shape the future of Go! Take the 2026 Go Developer Survey

allratestoday

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 12 Imported by: 0

README

AllRatesToday Go SDK — allratestoday-go

The official Go client for the AllRatesToday currency API. A small, zero-dependency wrapper over net/http for Go services and CLI tools that need real-time, historical or official central-bank exchange rates without hand-rolling request and response types.

Go Reference Go Report Card zero dependencies Powered by AllRatesToday

🚀 Features

  • ⚡ Real-time rates — latest mid-market rates for any base currency
  • 🌍 160+ currencies — the full list is available keylessly via Symbols
  • 📅 Historical data — a past date, a date range, or a preset period (1d, 7d, 30d, 1y) across the last 365 days (paid plans)
  • 💱 Conversion — convert an amount at the current rate, or at a past date's rate on a paid plan
  • 🏛️ Official rates — the published tables of 121 central banks + 3 tax authorities, no key needed
  • 🧩 Typed responses — every method decodes into a documented struct with JSON tags
  • 🛡️ Typed errors — non-2xx responses surface as a *allratestoday.Error with status code and body
  • ⏱️ Context-aware — every method takes a context.Context for timeouts and cancellation
  • 🔧 Functional options — WithBaseURL and WithHTTPClient for testing and custom transports
  • 📦 Zero dependencies — standard library only (net/http + encoding/json)
  • 💹 Mid-market rates — no retail spread baked in

🔑 Get your API key

Create a free key at allratestoday.com/register: 300 free requests, lifetime (the allowance never resets). Keys look like art_live_..., and the SDK sends yours as a Bearer token in the Authorization header. Symbols, OfficialRates and OfficialSources work without a key; every other method returns allratestoday.ErrMissingAPIKey if the client has none.

A free key (and a 100-call agent trial key) covers the latest rates and conversion. History and past-date rates (ConvertOnDate, Historical, TimeSeries, GetHistoricalRates) need a paid plan; on a free or trial key they return a *allratestoday.Error with status 403 and code historical_requires_paid_plan. The keyed API sends no CORS headers, so use it from server-side code, not the browser.

📦 Installation

go get github.com/AllRates-Today/allratestoday-go@v1.1.1

Requires Go 1.22 or later. No third-party dependencies.

Upgrading from v1.0.x: v1.0.x called /v1/... paths that the API does not serve, so every call failed with HTTP 404. v1.1.0 keeps the same method names and response types but calls the real endpoints. Historical and TimeSeries now require at least one symbol and cover the last 365 days.

🏁 Quick start

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	allratestoday "github.com/AllRates-Today/allratestoday-go"
)

func main() {
	client := allratestoday.NewClient(os.Getenv("ALLRATES_API_KEY"))
	ctx := context.Background()

	// Latest rates for a base currency
	rates, err := client.Latest(ctx, "USD", []string{"EUR", "GBP"})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Base:", rates.Base, "as of", rates.Date)
	fmt.Println("Rates:", rates.Rates)

	// Convert an amount
	result, err := client.Convert(ctx, "USD", "EUR", 100)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("100 USD = %.2f EUR\n", result.Result)
}

📚 API reference

Construct a client with allratestoday.NewClient(apiKey, opts...). Every method takes a context.Context first and returns a typed result plus an error.

Method Endpoint Key Returns
Latest(ctx, base, symbols) GET /api/v1/rates yes *LatestResponse
GetRates(ctx, source, targets...) GET /api/v1/rates yes []Rate
GetRate(ctx, from, to) GET /api/v1/rates yes *RateResponse
Convert(ctx, from, to, amount) GET /api/v1/rates?amount= yes *ConvertResponse
ConvertOnDate(ctx, from, to, amount, date) GET /api/historical-rates paid plan *ConvertResponse
Historical(ctx, date, base, symbols) GET /api/historical-rates (one call per symbol) paid plan *HistoricalResponse
TimeSeries(ctx, startDate, endDate, base, symbols) GET /api/historical-rates (one call per symbol) paid plan *TimeSeriesResponse
GetHistoricalRates(ctx, source, target, period) GET /api/historical-rates paid plan *HistoricalRatesResponse
Symbols(ctx) GET /api/v1/symbols no *SymbolsResponse
OfficialRates(ctx, bank, source, target) GET /api/open/central-bank/{bank} no *OfficialRatesResponse
OfficialSources(ctx) GET /api/open/central-banks no *OfficialSourcesResponse
Latest(ctx, base, symbols)

Most recent mid-market rates for a base currency. Pass nil for every available currency. Date is the observation time, e.g. 2026-10-16T11:31:01+0000.

// All currencies
rates, err := client.Latest(ctx, "USD", nil)

// Specific currencies only
rates, err := client.Latest(ctx, "USD", []string{"EUR", "GBP", "JPY"})
fmt.Println(rates.Date, rates.Rates["EUR"])
GetRates(ctx, source, targets...) and GetRate(ctx, from, to)

GetRates returns the raw list, one Rate (Rate, Source, Target, Time) per target. GetRate is the single-pair shortcut.

list, err := client.GetRates(ctx, "USD", "EUR", "GBP")
for _, r := range list {
	fmt.Println(r.Source, r.Target, r.Rate, r.Time)
}

rate, err := client.GetRate(ctx, "USD", "EUR")
fmt.Println("USD/EUR:", rate.Rate, "at", rate.Date)
Convert(ctx, from, to, amount) and ConvertOnDate(ctx, from, to, amount, date)

Convert at the current rate, or at the rate on a past date (YYYY-MM-DD, last 365 days; the closest earlier point is used when the date has none). ConvertOnDate needs a paid plan.

result, err := client.Convert(ctx, "USD", "EUR", 250)
fmt.Println(result.Rate, result.Result)

past, err := client.ConvertOnDate(ctx, "USD", "EUR", 250, "2026-09-15")
fmt.Println(past.Date, past.Rate, past.Result)
Historical(ctx, date, base, symbols)

Paid plan. Rates on a past date (YYYY-MM-DD, last 365 days). symbols is required, and each symbol costs one request. Dates older than 30 days resolve against the weekly 1-year series, so you get the closest earlier weekly point.

rates, err := client.Historical(ctx, "2026-10-01", "USD", []string{"EUR", "GBP"})
fmt.Println(rates.Date, rates.Rates)
TimeSeries(ctx, startDate, endDate, base, symbols)

Paid plan. Rates across a date range, keyed by date then currency. The start date must be within the last 365 days; symbols is required, one request per symbol.

series, err := client.TimeSeries(ctx, "2026-10-01", "2026-10-15", "USD", []string{"EUR", "GBP"})
for date, dayRates := range series.Rates {
	fmt.Println(date, dayRates["EUR"], dayRates["GBP"])
}
GetHistoricalRates(ctx, source, target, period)

Paid plan. A pair's history over a preset period: "1d", "7d", "30d" or "1y" (daily points; weekly for "1y"). Rates is a slice of HistoricalRatePoint (Date, Rate, Timestamp in Unix milliseconds), sorted oldest first.

history, err := client.GetHistoricalRates(ctx, "USD", "EUR", "30d")
for _, point := range history.Rates {
	fmt.Println(point.Date, point.Rate)
}
Symbols(ctx)

Every supported currency, no key needed. Symbols maps each code to a CurrencySymbol (Code, Name, Symbol); Currencies keeps the API's order.

symbols, err := allratestoday.NewClient("").Symbols(ctx)
fmt.Println(symbols.Count, "currencies")
fmt.Println(symbols.Symbols["EUR"].Name, symbols.Symbols["EUR"].Symbol) // Euro €
OfficialRates(ctx, bank, source, target) and OfficialSources(ctx)

The latest official table published by a central bank or tax authority (121 central banks + 3 tax authorities: HMRC, US Treasury, Swiss BAZG). These are the fixed, citable rates for invoicing, tax, customs and accounting, not live market rates. No key needed. Cite RateDate, not today's date.

keyless := allratestoday.NewClient("")

// One pair (cross-computed inside the bank's table when not published directly)
ecb, err := keyless.OfficialRates(ctx, "ecb", "EUR", "USD")
fmt.Printf("ECB %s: 1 EUR = %v USD (%s)\n", ecb.RateDate, ecb.Rate, ecb.RateType)

// Full published table
table, err := keyless.OfficialRates(ctx, "ecb", "", "")
for _, row := range table.Rates {
	fmt.Println(row.Base, row.Quote, row.Type, row.Value)
}

// Every source with its latest publication date
sources, err := keyless.OfficialSources(ctx)
for _, s := range sources.Sources {
	fmt.Println(s.Code, s.Name, s.Latest, s.Stale)
}

Dated and historical central-bank tables (/api/v1/central-bank/{bank}/{date}) need a paid plan; see pricing.

Options

Override the default host (https://allratestoday.com) or the HTTP client:

client := allratestoday.NewClient("art_live_your_api_key",
	allratestoday.WithBaseURL("https://custom.example.com"),
	allratestoday.WithHTTPClient(&http.Client{Timeout: 5 * time.Second}),
)

The default HTTP client uses a 10-second timeout; use context.WithTimeout for per-request deadlines.

🗺️ Currencies covered

160+ currencies, including 🇺🇸 USD, 🇪🇺 EUR, 🇬🇧 GBP and 🇯🇵 JPY. Call Symbols for the authoritative, always-current list rather than hard-coding one.

🛡️ Error handling

Non-2xx API responses come back as a *allratestoday.Error carrying the HTTP status code and response body; a missing key is allratestoday.ErrMissingAPIKey; transport, validation and decode failures are wrapped standard errors. Use errors.As to branch:

rates, err := client.Latest(ctx, "USD", nil)
if err != nil {
	var apiErr *allratestoday.Error
	if errors.As(err, &apiErr) {
		log.Fatalf("API error %d: %s", apiErr.StatusCode, apiErr.Message)
	}
	log.Fatalf("request failed: %v", err) // network, timeout, or parse failure
}
fmt.Println(rates.Rates)

💡 Notes

  • Concurrency. A Client is safe for concurrent use by multiple goroutines — create one and share it.
  • Cancellation. Every method takes a context.Context, so timeouts and cancellation compose with the rest of your service.
  • Request cost. Historical and TimeSeries make one request per symbol, because the history endpoint takes one target per call.
  • Tests. Run the unit tests with go test ./.... They use httptest with response bodies captured from the live API and never touch the network; set ALLRATES_API_KEY to also run the live smoke test (4 keyed requests; on a free key the two history calls are expected to return 403 historical_requires_paid_plan).

🤖 Use it from an AI agent

The same rates are available to coding agents and LLM tools without a second integration:

  • Claude Code plugin (no key): /plugin marketplace add AllRates-Today/claude-code-plugin then /plugin install allratestoday@allratestoday
  • Hosted MCP endpoint: https://allratestoday.com/api/mcp — Streamable HTTP, keyless, nothing to install
  • Local MCP servers: npx -y @allratestoday/mcp-server (live mid-market rates) · npx -y @allratestoday/central-bank-mcp (official central-bank rates)
  • Trial key for agents, no signup: POST https://allratestoday.com/api/agent/keys (send Content-Type: application/json) returns a 100-call key valid 7 days for latest rates and latest central-bank tables (history and dated tables are paid-plan only); both MCP servers expose it as request_trial_key
  • Daily Reference Rate (first published 2026-10-12): one fixed USD table per business day, the 16:00 London median of minute samples, never revised — keyless at https://allratestoday.com/api/open/reference-rate, get_reference_rate in the MCP server
  • Machine-readable site guide: llms.txt

📜 License

MIT — see LICENSE.

Documentation

Overview

Package allratestoday is the official Go client for the AllRatesToday exchange rate API (https://allratestoday.com). It provides real-time mid-market exchange rates for 160+ currencies, conversion, up to a year of daily history (paid plans), and the official rates published by 121 central banks and 3 tax authorities.

Create a free API key at https://allratestoday.com/register (300 free requests, lifetime). Keys look like "art_live_...", and the client sends yours as a Bearer token in the Authorization header. Symbols, OfficialRates and OfficialSources work without a key. Historical and dated rates (ConvertOnDate, Historical, TimeSeries, GetHistoricalRates) need a paid plan; free and trial keys get HTTP 403 with code "historical_requires_paid_plan". The keyed API sends no CORS headers, so call it from server-side code only.

client := allratestoday.NewClient("art_live_your_api_key")
rates, err := client.Latest(context.Background(), "USD", []string{"EUR", "GBP"})

Index

Constants

View Source
const DefaultBaseURL = "https://allratestoday.com"

DefaultBaseURL is the production API host.

Variables

View Source
var ErrMissingAPIKey = errors.New("allratestoday: API key is required; register for free at https://allratestoday.com/register")

ErrMissingAPIKey is returned by methods that need an API key when the client was created with an empty one.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the AllRatesToday API client. Create one with NewClient. A Client is safe for concurrent use by multiple goroutines.

func NewClient

func NewClient(apiKey string, opts ...Option) *Client

NewClient returns a Client that authenticates with the given API key. Get a free key at https://allratestoday.com/register. Pass "" to use only the keyless methods (Symbols, OfficialRates, OfficialSources).

func (*Client) Convert

func (c *Client) Convert(ctx context.Context, from, to string, amount float64) (*ConvertResponse, error)

Convert converts an amount from one currency to another at the current rate.

func (*Client) ConvertOnDate added in v1.1.0

func (c *Client) ConvertOnDate(ctx context.Context, from, to string, amount float64, date string) (*ConvertResponse, error)

ConvertOnDate converts an amount at the rate on a past date (YYYY-MM-DD, within the last 365 days). It uses the closest earlier point when the date has none (the 1-year window is weekly). Requires a paid plan: free and trial keys get a 403 *Error (code "historical_requires_paid_plan").

func (*Client) GetHistoricalRates

func (c *Client) GetHistoricalRates(ctx context.Context, source, target, period string) (*HistoricalRatesResponse, error)

GetHistoricalRates returns a currency pair's history over a preset period: "1d", "7d", "30d" or "1y" (daily points; weekly for "1y"). Points are sorted oldest first. Requires a paid plan: free and trial keys get a 403 *Error (code "historical_requires_paid_plan").

func (*Client) GetRate

func (c *Client) GetRate(ctx context.Context, from, to string) (*RateResponse, error)

GetRate returns the current rate for a single currency pair.

func (*Client) GetRates added in v1.1.0

func (c *Client) GetRates(ctx context.Context, source string, targets ...string) ([]Rate, error)

GetRates returns the raw rate list from GET /api/v1/rates, one entry per target, each with its observation time. Pass no targets for every available currency.

func (*Client) Historical

func (c *Client) Historical(ctx context.Context, date, base string, symbols []string) (*HistoricalResponse, error)

Historical returns rates as of a past date (YYYY-MM-DD, within the last 365 days) for the given symbols. symbols is required: the history endpoint takes one target per call, so each symbol costs one request. Requires a paid plan: free and trial keys get a 403 *Error (code "historical_requires_paid_plan").

func (*Client) Latest

func (c *Client) Latest(ctx context.Context, base string, symbols []string) (*LatestResponse, error)

Latest returns the most recent mid-market rates for a base currency. Pass a nil or empty symbols slice to receive every available currency.

func (*Client) OfficialRates added in v1.1.0

func (c *Client) OfficialRates(ctx context.Context, bank, source, target string) (*OfficialRatesResponse, error)

OfficialRates returns the latest table of official rates published by a central bank or tax authority (e.g. "ecb", "fed", "hmrc"). Pass source and target (e.g. "EUR", "USD") for one pair, or both empty for the full table. No API key needed.

func (*Client) OfficialSources added in v1.1.0

func (c *Client) OfficialSources(ctx context.Context) (*OfficialSourcesResponse, error)

OfficialSources lists every covered official source with its code, name, latest publication date and whether it is behind schedule. No API key needed.

func (*Client) Symbols

func (c *Client) Symbols(ctx context.Context) (*SymbolsResponse, error)

Symbols lists every supported currency. No API key needed.

func (*Client) TimeSeries

func (c *Client) TimeSeries(ctx context.Context, startDate, endDate, base string, symbols []string) (*TimeSeriesResponse, error)

TimeSeries returns daily rates between two dates (YYYY-MM-DD, start within the last 365 days), keyed by date then currency. symbols is required; each symbol costs one request. Requires a paid plan: free and trial keys get a 403 *Error (code "historical_requires_paid_plan").

type ConvertResponse

type ConvertResponse struct {
	// Deprecated: always true. Failures are returned as an error.
	Success bool    `json:"success"`
	From    string  `json:"from"`
	To      string  `json:"to"`
	Amount  float64 `json:"amount"`
	Result  float64 `json:"result"`
	Rate    float64 `json:"rate"`
	// Date is set (YYYY-MM-DD) only for ConvertOnDate.
	Date string `json:"date,omitempty"`
}

ConvertResponse is returned by Convert and ConvertOnDate.

type CurrencySymbol

type CurrencySymbol struct {
	Code   string `json:"code"`
	Name   string `json:"name"`
	Symbol string `json:"symbol"`
}

CurrencySymbol describes one supported currency.

type Error

type Error struct {
	// StatusCode is the HTTP status code returned by the API.
	StatusCode int
	// Message is the response body (usually a JSON error payload such as
	// {"error":"..."}).
	Message string
}

Error is returned when the API responds with a non-2xx status code.

func (*Error) Error

func (e *Error) Error() string

type HistoricalRatePoint

type HistoricalRatePoint struct {
	// Date is YYYY-MM-DD.
	Date string  `json:"date"`
	Rate float64 `json:"rate"`
	// Timestamp is milliseconds since the Unix epoch.
	Timestamp int64 `json:"timestamp"`
}

HistoricalRatePoint is a single observation in a HistoricalRatesResponse.

type HistoricalRatesResponse

type HistoricalRatesResponse struct {
	// Deprecated: always true. Failures are returned as an error.
	Success bool   `json:"success"`
	Source  string `json:"source"`
	Target  string `json:"target"`
	Period  string `json:"period"`
	// Rates is sorted oldest first.
	Rates []HistoricalRatePoint `json:"data"`
}

HistoricalRatesResponse is returned by GetHistoricalRates.

type HistoricalResponse

type HistoricalResponse struct {
	// Deprecated: always true. Failures are returned as an error.
	Success bool               `json:"success"`
	Base    string             `json:"base"`
	Date    string             `json:"date"`
	Rates   map[string]float64 `json:"rates"`
}

HistoricalResponse is returned by Historical.

type LatestResponse

type LatestResponse struct {
	// Deprecated: always true. Failures are returned as an error.
	Success bool   `json:"success"`
	Base    string `json:"base"`
	// Date is the observation time of the rates, e.g.
	// "2026-10-16T11:31:01+0000".
	Date  string             `json:"date"`
	Rates map[string]float64 `json:"rates"`
}

LatestResponse is returned by Latest.

type OfficialRateAttribution added in v1.1.0

type OfficialRateAttribution struct {
	Source string `json:"source"`
	URL    string `json:"url"`
	Terms  string `json:"terms"`
}

OfficialRateAttribution is the attribution block on official responses.

type OfficialRateEntry added in v1.1.0

type OfficialRateEntry struct {
	Base  string `json:"base"`
	Quote string `json:"quote"`
	// Type is the rate type as the institution labels it, e.g.
	// "reference", "buy", "sell", "mid".
	Type  string  `json:"type"`
	Value float64 `json:"value"`
}

OfficialRateEntry is one row of an official published table.

type OfficialRatesResponse added in v1.1.0

type OfficialRatesResponse struct {
	Bank string `json:"bank"`
	// RateDate is the publication date of the table (YYYY-MM-DD); cite this,
	// not today's date.
	RateDate string              `json:"rate_date"`
	Rates    []OfficialRateEntry `json:"rates,omitempty"`
	Source   string              `json:"source,omitempty"`
	Target   string              `json:"target,omitempty"`
	Rate     float64             `json:"rate,omitempty"`
	RateType string              `json:"rate_type,omitempty"`
	// Derived is true when the pair was cross-computed inside the bank's
	// own table rather than published directly.
	Derived bool   `json:"derived,omitempty"`
	Method  string `json:"method,omitempty"`
	AgeDays int    `json:"age_days"`
	// Stale is true when the institution is behind its own schedule.
	Stale       bool                    `json:"stale"`
	Cadence     string                  `json:"cadence,omitempty"`
	Attribution OfficialRateAttribution `json:"attribution"`
	FreeKey     string                  `json:"free_key,omitempty"`
}

OfficialRatesResponse is returned by OfficialRates. With a pair, Source, Target, Rate and RateType are set; without one, Rates holds the full table.

type OfficialSource added in v1.1.0

type OfficialSource struct {
	// Code is what you pass as bank to OfficialRates, e.g. "ecb".
	Code string `json:"code"`
	Name string `json:"name"`
	// Latest is the latest publication date, or "" if never ingested.
	Latest  string `json:"latest"`
	AgeDays int    `json:"age_days"`
	Stale   bool   `json:"stale"`
	Cadence string `json:"cadence"`
}

OfficialSource is one entry returned by OfficialSources.

type OfficialSourcesResponse added in v1.1.0

type OfficialSourcesResponse struct {
	Sources    []OfficialSource `json:"sources"`
	StaleCount int              `json:"stale_count"`
	CheckedAt  string           `json:"checked_at"`
	Docs       string           `json:"docs"`
	FreeKey    string           `json:"free_key"`
}

OfficialSourcesResponse is returned by OfficialSources.

type Option

type Option func(*Client)

Option configures a Client created by NewClient.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL overrides the default API host (useful for testing).

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) Option

WithHTTPClient replaces the underlying *http.Client (custom timeouts, proxies, instrumentation, ...).

type Rate added in v1.1.0

type Rate struct {
	Rate   float64 `json:"rate"`
	Source string  `json:"source"`
	Target string  `json:"target"`
	// Time is the observation time, e.g. "2026-10-16T11:31:01+0000".
	Time string `json:"time"`
}

Rate is one element of the list returned by GET /api/v1/rates.

type RateResponse

type RateResponse struct {
	// Deprecated: always true. Failures are returned as an error.
	Success bool    `json:"success"`
	From    string  `json:"from"`
	To      string  `json:"to"`
	Rate    float64 `json:"rate"`
	// Date is the observation time, e.g. "2026-10-16T11:31:01+0000".
	Date string `json:"date"`
}

RateResponse is returned by GetRate.

type SymbolsResponse

type SymbolsResponse struct {
	// Deprecated: always true. Failures are returned as an error.
	Success bool `json:"success"`
	// Symbols maps each currency code to its details.
	Symbols map[string]CurrencySymbol `json:"symbols"`
	// Currencies is the list in the order the API returns it.
	Currencies []CurrencySymbol `json:"currencies"`
	Count      int              `json:"count"`
}

SymbolsResponse is returned by Symbols.

type TimeSeriesResponse

type TimeSeriesResponse struct {
	// Deprecated: always true. Failures are returned as an error.
	Success   bool                          `json:"success"`
	Base      string                        `json:"base"`
	StartDate string                        `json:"start_date"`
	EndDate   string                        `json:"end_date"`
	Rates     map[string]map[string]float64 `json:"rates"`
}

TimeSeriesResponse is returned by TimeSeries. Rates is keyed by date (YYYY-MM-DD), then by currency code.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL