Public exchange rate API for Costa Rica, powered by BCCR
Project description
TicoRates 🇨🇷
Free, open exchange rate API for Costa Rica — powered by BCCR. No sign-up, no token, ready to use.
Live server → https://ticorates.dev — free for everyone, no API key required.
How it works
- Request — you call any endpoint with a date and currency code.
- Cache check — if the rate is already in the database, it's returned instantly.
- BCCR fetch — on a cache miss, rates are fetched from Banco Central de Costa Rica in real time.
- Store & serve — the result is cached in SQLite for all future requests to the same date.
Historical dates are served from cache after the first request. Concurrent requests for the same date are deduplicated — only one BCCR call is made regardless of how many clients ask simultaneously.
Try it now
No installation. No registration. Paste and run:
# Today's USD rate
curl "https://ticorates.dev/rates/latest?currency=USD"
# Rate on a specific date
curl "https://ticorates.dev/rates?date=2025-01-15¤cy=USD"
# Last 30 days
curl "https://ticorates.dev/rates?from=2025-04-01&to=2025-04-30¤cy=USD"
# All supported currencies
curl https://ticorates.dev/currencies
Interactive docs → ticorates.dev/docs
Features
- REST API — simple HTTP endpoints, no authentication required
- 43 currencies — USD, EUR, GBP, JPY, CAD, AUD, CHF, and more
- On-demand caching — rates are fetched from BCCR on first request and served instantly after
- Historical rates — query any date or date range going back years
- MCP server — native integration with Claude, Cursor, Windsurf, and other AI tools
- Self-hosted — Docker image available for
linux/amd64andlinux/arm64
Table of Contents
API Reference
Base URL: https://ticorates.dev
Interactive docs: https://ticorates.dev/docs
GET /currencies
Returns all supported currency codes and their full names.
GET /currencies
Response
{
"USD": "United States Dollar",
"EUR": "Euro (European Union)",
"GBP": "British Pound Sterling (United Kingdom)",
"JPY": "Japanese Yen (Japan)"
}
GET /rates/latest
Returns today's exchange rate from BCCR for a specific currency.
| Parameter | Type | Required | Description |
|---|---|---|---|
currency |
string | Yes | Currency code (e.g. USD, EUR) |
GET /rates/latest?currency=USD
Response
{
"date": "2025-05-27",
"rates": {
"USD": {
"purchase": 512.50,
"sale": 519.75,
"description": "United States Dollar"
}
}
}
GET /rates
Returns rates for a specific date or date range. Provide either date or both from + to.
| Parameter | Type | Required | Description |
|---|---|---|---|
currency |
string | Yes | Currency code (e.g. USD, EUR) |
date |
string | No* | Single date in YYYY-MM-DD format |
from |
string | No* | Start of range in YYYY-MM-DD format |
to |
string | No* | End of range in YYYY-MM-DD format |
*Either date or both from + to must be provided.
GET /rates?date=2025-01-15¤cy=EUR
GET /rates?from=2025-01-01&to=2025-01-31¤cy=USD
A single-date request returns an object. A date-range request returns an array sorted by date.
Response — single date
{
"date": "2025-01-15",
"rates": {
"USD": { "purchase": 510.25, "sale": 517.50, "description": "United States Dollar" }
}
}
Response — date range
[
{
"date": "2025-01-01",
"rates": { "USD": { "purchase": 508.00, "sale": 515.00, "description": "United States Dollar" } }
},
{
"date": "2025-01-02",
"rates": { "USD": { "purchase": 509.50, "sale": 516.75, "description": "United States Dollar" } }
}
]
Weekends & holidays
BCCR only publishes rates on business days. TicoRates handles this transparently:
- Single date — if you request a weekend or holiday, the API returns the most
recent business day's rate (looking back up to a week). The
datefield in the response reflects the actual date returned, not the one requested. Requesting?date=2025-05-25(Sunday) returns{ "date": "2025-05-23", ... }. - Date range — days with no published data are simply omitted from the array, so a 14-day range may return fewer than 14 entries.
GET /health
Health check endpoint. Returns 200 OK when the service is running.
{ "status": "ok" }
Error responses
| Status | Condition |
|---|---|
400 |
Unsupported currency, or date / from+to not provided |
404 |
No BCCR data published for the requested date |
422 |
Missing required currency parameter, or invalid date format |
502 |
BCCR upstream error (rate limit or service unavailable) |
MCP Server
No API key required. The MCP server connects to
https://ticorates.devby default — install it and it just works.
TicoRates includes an MCP server that gives AI assistants direct access to Costa Rican exchange rates. Ask your AI questions like:
- "What's today's dollar rate in Costa Rica?"
- "How much has the euro changed this month?"
- "Convert 500 USD to colones using today's rate."
- "What was the average dollar rate in Q1 2025?"
Available tools
| Tool | Description |
|---|---|
get_supported_currencies |
List all available currency codes and names |
get_latest_rates |
Today's rate for a specific currency |
get_rates_for_date |
Historical rate for a specific date |
get_rates_for_date_range |
Rates for a date range, one entry per day |
convert_amount |
Convert between any two currencies |
get_rate_change |
Absolute and percentage change between two dates |
get_historical_average |
Average purchase/sale rate over a period |
Setup
The same config block works across all MCP-compatible clients. Pick yours below.
Claude Desktop
Edit claude_desktop_config.json and restart Claude Desktop.
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"ticorates": {
"command": "uvx",
"args": ["ticorates-mcp"]
}
}
}
Claude Code
Run once in your terminal:
claude mcp add ticorates -- uvx ticorates-mcp
Cursor
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"ticorates": {
"command": "uvx",
"args": ["ticorates-mcp"]
}
}
}
Or go to Settings → Cursor Settings → Features → MCP → Add MCP Server.
Windsurf
Open the Cascade panel → ⚙ Settings → MCP Servers → Add, then enter:
- Command:
uvx - Args:
ticorates-mcp
OpenAI Codex CLI
codex mcp add ticorates -- uvx ticorates-mcp
Other clients
Any MCP-compatible client that supports stdio transport works with TicoRates. Use the same JSON config structure shown above.
Pointing the MCP at a self-hosted instance
By default, ticorates-mcp connects to https://ticorates.dev. To use your own instance, set TICORATES_BASE_URL in your client's config:
{
"mcpServers": {
"ticorates": {
"command": "uvx",
"args": ["ticorates-mcp"],
"env": {
"TICORATES_BASE_URL": "http://your-server:8000"
}
}
}
}
Self-Hosting
Prerequisites
- Docker and Docker Compose
- A BCCR API key — register at the BCCR developer portal
Setup
1. Create a docker-compose.yml:
services:
ticorates:
image: jonach1998/ticorates:latest
ports:
- "8000:8000"
env_file: .env
environment:
- TZ=America/Costa_Rica
volumes:
- ticorates_data:/app/data
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
ticorates_data:
2. Create a .env file:
BCCR_API_KEY=your_token_here
BCCR_BASE_URL=https://apim.bccr.fi.cr/SDDE/api/Bccr.GE.SDDE.Publico.Indicadores.API
# Optional — change the SQLite database path (default: /app/data/ticorates.db)
# DATABASE_URL=sqlite:////custom/path/ticorates.db
3. Start the service:
docker compose up -d
The API will be available at http://localhost:8000.
Interactive docs at http://localhost:8000/docs.
Monitoring
The app exposes Prometheus metrics at /metrics (request counts by status, latency histograms). Scrape it from your monitoring stack — but keep /metrics off the public internet (block the path at your reverse proxy or tunnel), since it's an internal operational endpoint.
Development
Requirements: Python 3.13+, uv
# Clone the repo and install dependencies
git clone https://github.com/jonach1998/ticorates
cd ticorates
uv sync --extra dev
# Copy and fill in your BCCR credentials
cp .env.example .env
# Run the API
uv run uvicorn ticorates.main:app --reload
# Run the MCP server
uv run ticorates-mcp
# Run unit tests (no credentials needed)
uv run python -m pytest
# Run the full stress test against the live BCCR API (requires .env)
uv run python tests/stress/stress_test.py
Star History
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ticorates_mcp-1.1.0.tar.gz.
File metadata
- Download URL: ticorates_mcp-1.1.0.tar.gz
- Upload date:
- Size: 63.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
184d8aecd09d75299a7617c9febf987c354e9a7311f2a655947cbea09bc6da46
|
|
| MD5 |
3919c4bf9d3080c9607653c4466b88ad
|
|
| BLAKE2b-256 |
39df12f7874526f543c9d4c29effbd56cc831c93ab137fb19fb49270caf00333
|
Provenance
The following attestation bundles were made for ticorates_mcp-1.1.0.tar.gz:
Publisher:
test-and-publish.yml on jonach1998/ticorates
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ticorates_mcp-1.1.0.tar.gz -
Subject digest:
184d8aecd09d75299a7617c9febf987c354e9a7311f2a655947cbea09bc6da46 - Sigstore transparency entry: 1726072329
- Sigstore integration time:
-
Permalink:
jonach1998/ticorates@fe6055b67cc1ff6acef5855d4e62941090d7caaa -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/jonach1998
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
test-and-publish.yml@fe6055b67cc1ff6acef5855d4e62941090d7caaa -
Trigger Event:
push
-
Statement type:
File details
Details for the file ticorates_mcp-1.1.0-py3-none-any.whl.
File metadata
- Download URL: ticorates_mcp-1.1.0-py3-none-any.whl
- Upload date:
- Size: 20.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca92e499817e92401d43533b5bed804c56792ab92528107cead482c330435dfd
|
|
| MD5 |
de4fb0731fc56c176aedb725fcf126f5
|
|
| BLAKE2b-256 |
e71385a46cde6892871f1ee555354733bc0c9be245b2d386f5842465f6457e28
|
Provenance
The following attestation bundles were made for ticorates_mcp-1.1.0-py3-none-any.whl:
Publisher:
test-and-publish.yml on jonach1998/ticorates
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ticorates_mcp-1.1.0-py3-none-any.whl -
Subject digest:
ca92e499817e92401d43533b5bed804c56792ab92528107cead482c330435dfd - Sigstore transparency entry: 1726072433
- Sigstore integration time:
-
Permalink:
jonach1998/ticorates@fe6055b67cc1ff6acef5855d4e62941090d7caaa -
Branch / Tag:
refs/tags/v1.1.0 - Owner: https://github.com/jonach1998
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
test-and-publish.yml@fe6055b67cc1ff6acef5855d4e62941090d7caaa -
Trigger Event:
push
-
Statement type: