TASALO API is a production-ready REST API that aggregates exchange rates from multiple Cuban sources: ElToque (informal market), CADECA, BCC (official rates), and Binance (crypto). Built with FastAPI and PostgreSQL, it provides real-time currency data with automatic updates every 5 minutes, historical tracking, and change indicators.
Key Metrics:
- 📊 4 data sources aggregated
- ⏱️ 5-minute refresh interval
- 📈 Historical data tracking
- 🔒 Admin API with authentication
- 📝 Full OpenAPI documentation
- Features
- Quick Start
- API Reference
- Code Examples
- Installation
- Configuration
- Systemd Service
- Troubleshooting
- Contributing
- Roadmap
- License
| Source | Type | Currencies | Update Frequency |
|---|---|---|---|
| ElToque | Informal market | USD, EUR, MLC | Every 5 min |
| CADECA | Official exchange | USD, EUR | Every 5 min |
| BCC | Central Bank | USD, EUR | Every 5 min |
| Binance | Crypto P2P | USDT, BTC, ETH | Every 5 min |
| Cubanomic | Multi-source | USD, EUR, MLC | Daily (00:01 UTC) |
- RESTful Design: Standard HTTP methods and status codes
- Change Indicators: 🔺🔻📊 arrows showing rate movements vs previous snapshot
- Historical Data: Query rates from the past 1-365 days
- Filtering: Filter by source, currency, and date range
- Health Checks: Built-in
/healthendpoint for monitoring
- Authentication: API key protection for admin endpoints
- CORS: Configurable cross-origin resource sharing
- Logging: Structured JSON logs with configurable levels
- Error Handling: Consistent error responses across all endpoints
- Async/Await: High-performance non-blocking operations
- Automatic Refresh: Tasas actualizadas automáticamente cada 5 minutos
- Cubanomic Daily: Fetch diario a las 00:01 UTC
- Manual Trigger: Endpoint admin para refresh manual
Get TASALO API running in under 5 minutes:
# 1. Clone and setup
git clone https://github.com/tasalo/taso-api.git
cd taso-api
# 2. Create virtual environment
uv venv && source .venv/bin/activate
# 3. Install dependencies
uv pip install -r requirements.txt
# 4. Configure environment
cp .env.example .env
# Edit .env with your ElToque API key
# 5. Initialize database
alembic upgrade head
# 6. Start server
uvicorn src.main:app --reload
# 7. Test it!
curl http://localhost:8040/api/v1/health📚 Interactive API docs: http://localhost:8040/docs
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/v1/health |
❌ | Health check & DB status |
GET |
/api/v1/tasas/latest |
❌ | Tasas combinadas (ElToque, CADECA, BCC, Binance) |
GET |
/api/v1/tasas/eltoque |
❌ | Tasas de ElToque |
GET |
/api/v1/tasas/cadeca |
❌ | Tasas de CADECA (compra/venta) |
GET |
/api/v1/tasas/bcc |
❌ | Tasas de BCC (oficial) |
GET |
/api/v1/tasas/cubanomic |
❌ | Tasas de Cubanomic (USD/EUR/MLC) NUEVO |
GET |
/api/v1/tasas/history |
❌ | Histórico (source, currency, days) |
GET |
/api/v1/tasas/history/cubanomic |
❌ | Histórico Cubanomic (7d-2y) NUEVO |
GET |
/api/v1/tasas/history/local |
❌ | Histórico local (1d-2y) NUEVO |
POST |
/api/v1/images/eltoque/capture |
❌ | Capturar imagen ElToque NUEVO |
GET |
/api/v1/images/eltoque/latest |
❌ | Última imagen capturada NUEVO |
GET |
/api/v1/images/eltoque/{date} |
❌ | Imagen por fecha (YYYY-MM-DD) NUEVO |
GET |
/api/v1/images/eltoque/file/latest |
❌ | Descargar archivo de imagen NUEVO |
GET |
/api/v1/images/alerts/{user_id} |
❌ | Obtener alerta de usuario NUEVO |
POST |
/api/v1/images/alerts |
❌ | Crear/actualizar alerta NUEVO |
DELETE |
/api/v1/images/alerts/{user_id} |
❌ | Eliminar alerta NUEVO |
POST |
/api/v1/images/alerts/{user_id}/disable |
❌ | Desactivar alerta NUEVO |
GET |
/api/v1/images/alerts |
❌ | Obtener alertas activas NUEVO |
GET |
/api/v1/admin/status |
✅ | Scheduler status |
POST |
/api/v1/admin/refresh |
✅ | Trigger manual refresh |
Admin endpoints require the X-API-Key header:
curl http://localhost:8040/api/v1/admin/status \
-H "X-API-Key: your_secret_admin_key"All responses follow a consistent structure:
{
"ok": true,
"data": {
"eltoque": {
"USD": {
"rate": 365.50,
"change": "up",
"prev_rate": 364.00
}
}
},
"updated_at": "2026-03-23T04:15:00Z"
}import httpx
async def get_latest_rates():
async with httpx.AsyncClient() as client:
response = await client.get(
"http://localhost:8040/api/v1/tasas/latest"
)
data = response.json()
usd_rate = data["data"]["eltoque"]["USD"]["rate"]
print(f"USD Rate: {usd_rate}")const axios = require('axios');
async function getLatestRates() {
const response = await axios.get(
'http://localhost:8040/api/v1/tasas/latest'
);
console.log('USD Rate:', response.data.data.eltoque.USD.rate);
}
// Using Fetch API
async function getRates() {
const res = await fetch('http://localhost:8040/api/v1/tasas/latest');
const data = await res.json();
return data;
}# Get latest rates
curl http://localhost:8040/api/v1/tasas/latest
# Get historical data (last 7 days, USD from ElToque)
curl "http://localhost:8040/api/v1/tasas/history?source=eltoque¤cy=USD&days=7"
# Admin: Trigger manual refresh
curl -X POST http://localhost:8040/api/v1/admin/refresh \
-H "X-API-Key: your_admin_key"<?php
$response = file_get_contents('http://localhost:8040/api/v1/tasas/latest');
$data = json_decode($response, true);
echo "USD Rate: " . $data['data']['eltoque']['USD']['rate'];
?>package main
import (
"encoding/json"
"fmt"
"net/http"
)
type RateResponse struct {
Data struct {
Eltoque struct {
USD struct {
Rate float64 `json:"rate"`
} `json:"USD"`
} `json:"eltoque"`
} `json:"data"`
}
func main() {
resp, _ := http.Get("http://localhost:8040/api/v1/tasas/latest")
var data RateResponse
json.NewDecoder(resp.Body).Decode(&data)
fmt.Printf("USD Rate: %f\n", data.Data.Eltoque.USD.Rate)
}- Python: 3.13 or higher
- uv: Recommended package manager
- PostgreSQL: 14+ (for production)
# 1. Clone repository
git clone https://github.com/tasalo/taso-api.git
cd taso-api
# 2. Create virtual environment
uv venv
source .venv/bin/activate # Linux/Mac
# 3. Install dependencies
uv pip install -r requirements.txt
# 4. Configure environment
cp .env.example .env
# Edit .env with your settings
# 5. Initialize database
alembic upgrade head
# 6. Run tests (optional)
pytest -v
# 7. Start server
uvicorn src.main:app --reloadCopy .env.example to .env and configure:
| Variable | Description | Default | Required |
|---|---|---|---|
DATABASE_URL |
Database connection string | sqlite+aiosqlite:///./tasalo.db |
✅ |
ELTOQUE_API_KEY |
ElToque API key | - | ✅ |
ELTOQUE_API_URL |
ElToque API endpoint | https://tasas.eltoque.com/v1/trmi |
✅ |
ADMIN_API_KEY |
Admin API authentication key | - | ✅ |
REFRESH_INTERVAL_MINUTES |
Scheduler refresh interval | 5 |
✅ |
ALLOWED_ORIGINS |
CORS allowed origins | * |
✅ |
PORT |
Server port | 8040 |
❌ |
# Generate secure admin API key
openssl rand -hex 32Redis se usa para cachear datos de Cubanomic y reducir la carga en la API externa.
REDIS_URL=redis://localhost:6379/0
REDIS_TTL_CUBANOMIC=86400 # 24 horas (cache latest)# Ubuntu/Debian
sudo apt install redis-server
sudo systemctl enable redis
sudo systemctl start redis
# Verify
redis-cli ping # Should return: PONG| Endpoint | TTL | Descripción |
|---|---|---|
/api/v1/tasas/cubanomic |
24h | Tasas actuales |
/api/v1/tasas/history/cubanomic?days=X |
1h | Histórico por rango de días |
/api/v1/tasas/history/local?days=X |
— | Histórico local (sin cache) |
The local history endpoint provides historical rate data collected automatically from the 5-minute refresh cycles.
Endpoint: GET /api/v1/tasas/history/local
Query Parameters:
days(optional): Number of days of history (1-730). Default: 1.
Response Format:
{
"ok": true,
"data": [
{
"fetched_at": "2026-03-29T00:00:00Z",
"usd_rate": 517.26,
"eur_rate": 582.36,
"mlc_rate": 394.82
}
],
"count": 1,
"source": "local"
}Notes:
- Data is automatically collected every 5 minutes from the existing refresh job
- Rates are daily averages from all available sources (ElToque, CADECA, BCC)
- Starts with 1 day of data, expands as data accumulates
- No caching - always returns fresh data from database
| Job | Frecuencia | Hora | Descripción |
|---|---|---|---|
refresh_all |
Cada 5 min | — | Refresca tasas de ElToque, CADECA, BCC, Binance |
cubanomic_daily |
Diario | 00:01 UTC | Fetch de Cubanomic (USD/EUR/MLC) |
# Ver status del scheduler
curl http://localhost:8040/api/v1/admin/status \
-H "X-API-Key: your_admin_key"
# Trigger refresh manual
curl -X POST http://localhost:8040/api/v1/admin/refresh \
-H "X-API-Key: your_admin_key"Run TASALO API as a background service with automatic restart:
# /etc/systemd/system/taso-api.service
[Unit]
Description=TASALO API
After=network.target
[Service]
Type=simple
User=tasalo
WorkingDirectory=/opt/taso-api
Environment="PATH=/opt/taso-api/.venv/bin"
ExecStart=/opt/taso-api/.venv/bin/uvicorn src.main:app --host 0.0.0.0 --port 8040
Restart=always
[Install]
WantedBy=multi-user.target# Reload systemd
sudo systemctl daemon-reload
# Enable and start service
sudo systemctl enable taso-api
sudo systemctl start taso-api
# Check status
sudo systemctl status taso-api
# View logs
sudo journalctl -u taso-api -f| Issue | Cause | Solution |
|---|---|---|
aiosqlite install fails |
Python < 3.13 | Upgrade to Python 3.13+ |
| CORS errors | Wrong ALLOWED_ORIGINS |
Set to your frontend domain |
| ElToque timeout | Invalid API key | Regenerate key at eltoque.com |
| SQLite lock | Multiple processes | Close other connections |
Enable detailed logging in .env:
LOG_LEVEL=DEBUG# Check API health
curl http://localhost:8040/api/v1/health
# Test individual scrapers
python scripts/test_scrapers_manual.pyWe welcome contributions! Please see our Contributing Guide for details.
# 1. Fork the repository
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/taso-api.git
# 3. Create a branch
git checkout -b feature/your-feature-name
# 4. Make changes and test
pytest -v --cov=src
# 5. Submit a pull request- Python: 3.13+
- Testing:
pytest,pytest-asyncio,pytest-cov - Linting:
ruff,black,mypy
- Email alerts for rate thresholds
- WebSocket support for real-time updates
- GraphQL API endpoint
- Rate comparison charts endpoint
- Mobile SDK (React Native, Flutter)
- Webhook notifications
- Multi-language API responses
- Advanced analytics endpoint
Have ideas? Submit a feature request
This project is licensed under the MIT License.
✅ You can:
- Use commercially
- Modify and distribute
- Use privately
- Include copyright notice
- Include license text
- GitHub: tasalo/taso-api
- Discussions: GitHub Discussions
- Issues: Bug Reports
- Email: hello@tasalo.app
| Project | Description |
|---|---|
| taso-bot | Telegram bot for rate alerts |
| taso-miniapp | Telegram Mini App UI |
| taso-extension | Browser extension |
Made with ❤️ for Cuba 🇨🇺