SDKs and examples for the MetaRates API
Single-file clients with no dependencies, MIT licensed. Copy the file into your project or download it with the commands below.
Python
curl -O https://metarates.online/s/sdk/metarates.py
from metarates import MetaRates
mr = MetaRates("mr_live_...")
rates = mr.rates("UAH")
print(rates["best_buy"], rates["best_sell"], rates["cross_exchange_spread_pct"])
# live order book filtered by payment method
for ad in mr.orderbook("Binance", side="BUY", rows=5, payment_method="monobank")["ads"]:
print(ad["price"], ad["payment_methods"])
# arbitrage routes for 10 000 UAH after a 1 USDT transfer fee (Pro)
print(mr.arbitrage("UAH", amount=10000)["opportunities"][0])
JavaScript (Node 18+ or browser)
curl -O https://metarates.online/s/sdk/metarates.mjs
import { MetaRates } from "./metarates.mjs";
const mr = new MetaRates("mr_live_...");
const { best_buy } = await mr.rates("UAH");
console.log(best_buy.price, best_buy.exchange);
Real-time stream (Pro)
# Python
for event, data in mr.stream("UAH"):
if event == "rates":
print(data["best_buy"])
// JavaScript
for await (const { event, data } of mr.stream("UAH")) {
if (event === "rates") console.log(data.best_buy);
}
The stream sends an event right away and again whenever fresh data is collected (about every 5 minutes). The connection closes after an hour, so reconnect in a loop.
Webhooks (Pro)
hook = mr.create_webhook("https://example.com/hooks/metarates", event="spread", threshold=2.5, amount=10000)
print(hook["secret"]) # shown once: store it
Each delivery is a signed JSON POST. Headers: X-MetaRates-Event, X-MetaRates-Timestamp, X-MetaRates-Signature (sha256= HMAC of <timestamp>.<raw body>). Respond with a 2xx status; after 10 failures in a row the webhook is disabled.
# Flask
from flask import Flask, request, abort
from metarates import verify_webhook
app = Flask(__name__)
SECRET = "whsec_..."
@app.post("/hooks/metarates")
def hook():
ok = verify_webhook(SECRET, request.headers["X-MetaRates-Timestamp"], request.headers["X-MetaRates-Signature"], request.get_data())
if not ok:
abort(401)
event = request.get_json()
print(event["event"], event["data"])
return "", 204
// Express
import express from "express";
import { verifyWebhook } from "./metarates.mjs";
const app = express();
app.post("/hooks/metarates", express.raw({ type: "application/json" }), async (req, res) => {
const ok = await verifyWebhook(process.env.SECRET, req.get("X-MetaRates-Timestamp"), req.get("X-MetaRates-Signature"), req.body);
if (!ok) return res.sendStatus(401);
const event = JSON.parse(req.body);
console.log(event.event, event.data);
res.sendStatus(204);
});
curl
curl -H "X-API-Key: mr_live_..." "https://metarates.online/api/v1/rates?fiat=UAH"
curl -N -H "X-API-Key: mr_live_..." "https://metarates.online/api/v1/stream?fiat=UAH"
Google Sheets
Extensions → Apps Script, paste, save, then use =METARATES_BUY("UAH") in a cell. Cells refresh when the sheet recalculates (the API is cached for a minute, so use a trigger every few minutes instead of many cells).
const KEY = "mr_live_...";
function METARATES_BUY(fiat) {
const r = UrlFetchApp.fetch("https://metarates.online/api/v1/rates?fiat=" + (fiat || "UAH"), { headers: { "X-API-Key": KEY } });
return JSON.parse(r.getContentText()).best_buy.price;
}
Errors and limits
Errors return {"detail": {"code": "...", "message": "..."}}. Every response carries X-RateLimit-*, RateLimit-* and X-Quota-* headers; 429 includes Retry-After. Both clients retry short per-minute limits automatically. Full schema: API reference, manage keys in the dashboard.