DEV Community

Cover image for Getting started with the Waveleta API in Python and JavaScript
Waveleta
Waveleta

Posted on Originally published at waveleta.com

Getting started with the Waveleta API in Python and JavaScript

Originally published on waveleta.com.

This is a hands-on quickstart for the Waveleta Developer API: one request in curl, then working examples in Python and JavaScript for crypto prices, FX reference rates and commodities, along with clean error handling. If you haven't read it yet, the Waveleta API overview explains pricing (prepaid, €0.002 per call, €20 minimum top-up).

Before you start

You need an API key. Sign up at waveleta.com/developer/join, confirm your email, top up €20 and create a key. Keys look like wl_…. Keep it out of your source code: store it in an environment variable.

export WAVELETA_API_KEY="wl_your_key_here"
Enter fullscreen mode Exit fullscreen mode

The base URL is https://api.waveleta.com. Authenticate with either header:

  • Authorization: Bearer wl_…
  • X-Api-Key: wl_…

Your first request (curl)

curl -s -H "Authorization: Bearer $WAVELETA_API_KEY" \
  "https://api.waveleta.com/v1/crypto/tickers?limit=3"
Enter fullscreen mode Exit fullscreen mode

The response is JSON with an ok flag, a count, the data list and a billing object that shows what the call cost and your remaining balance:

{
  "ok": true,
  "count": 3,
  "tickers": [
    {"symbol": "…", "last_price": 0.0, "bid": 0.0, "ask": 0.0, "observed_epoch": 0}
  ],
  "billing": {"request_id": "…", "charged_eur": 0.002, "balance_eur": 19.998}
}
Enter fullscreen mode Exit fullscreen mode

You can check that the service is up for free, without a key:

curl -s https://api.waveleta.com/v1/health
Enter fullscreen mode Exit fullscreen mode

Python

No SDK needed. This uses requests (pip install requests):

import os
import requests

BASE = "https://api.waveleta.com"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['WAVELETA_API_KEY']}"

def get(path, **params):
    r = session.get(f"{BASE}{path}", params=params, timeout=30)
    if r.status_code == 402:
        raise RuntimeError("Waveleta balance too low: top up at waveleta.com/developer/join")
    if r.status_code == 429:
        raise RuntimeError("Rate limited: wait a few seconds and retry")
    r.raise_for_status()
    return r.json()

# 1) Crypto prices (600+ markets, refreshed every minute)
data = get("/v1/crypto/tickers", limit=10)
for t in data.get("tickers", []):
    print(t.get("symbol"), t.get("last_price"))

# 2) FX daily reference rates (refreshed each business day)
fx = get("/v1/fx/rates", limit=20)
for rate in fx.get("rates", []):
    print(rate.get("pair"), rate.get("rate"), rate.get("as_of_date"))

# 3) Commodities: WTI, Brent and natural gas (weekly)
com = get("/v1/commodities")
for c in com.get("commodities", []):
    print(c.get("instrument_id"), c.get("price"), c.get("observed_at"))

print("Balance left:", data["billing"]["balance_eur"], "EUR")
Enter fullscreen mode Exit fullscreen mode

Each get() call above is one billable call, so this script costs €0.006.

JavaScript (Node 18+)

const BASE = "https://api.waveleta.com";
const KEY = process.env.WAVELETA_API_KEY;

async function get(path, params = {}) {
  const url = new URL(path, BASE);
  Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
  const res = await fetch(url, { headers: { Authorization: `Bearer ${KEY}` } });
  if (res.status === 402) throw new Error("Waveleta balance too low: top up first");
  if (res.status === 429) throw new Error("Rate limited: retry in a few seconds");
  if (!res.ok) throw new Error(`Waveleta API error ${res.status}`);
  return res.json();
}

const crypto = await get("/v1/crypto/tickers", { limit: 10 });
crypto.tickers.forEach(t => console.log(t.symbol, t.last_price));

const fx = await get("/v1/fx/rates", { limit: 20 });
fx.rates.forEach(r => console.log(r.pair, r.rate, r.as_of_date));

console.log("Balance left:", crypto.billing.balance_eur, "EUR");
Enter fullscreen mode Exit fullscreen mode

Run it as an ES module (node quickstart.mjs). Never call the API directly from front-end code: your key would be visible to anyone who opens the browser's developer tools. Call it from your server, a serverless function or a build step, and serve the result to your page.

Look up a single market

Pass symbol to the tickers endpoint to get one market instead of a list. Use the symbol exactly as it appears in the tickers list:

btc = get("/v1/crypto/tickers", symbol="<symbol from the list>")
Enter fullscreen mode Exit fullscreen mode

For US equities history (early access), symbol is required:

bars = get("/v1/equities/history", symbol="AAPL", limit=50)
Enter fullscreen mode Exit fullscreen mode

Keep your bill small: cache

At €0.002 a call, cost is about how often you call, not how much data you get back. A few habits:

  • Cache responses. Crypto prices refresh every minute, so there's no point calling more often than that. FX reference rates change once per business day, and commodities once a week, so cache those for hours.
  • Use limit. Ask for the rows you need in one call instead of one call per market.
  • Handle 402 and 429. Back off on 429 and alert yourself on 402, so a script doesn't loop.

Example: refreshing a 50-market crypto table once a minute, 24/7, is 43,200 calls a month, about €86. Refreshing it every 10 minutes is about €8.60.

Generate a client from the OpenAPI spec

The spec is public at https://api.waveleta.com/openapi.json (OpenAPI 3.1). Feed it to your favourite generator, or import it into Postman or Insomnia to try requests.

Not a coder? Use WordPress

The Waveleta WordPress plugin wraps all of this in shortcodes, blocks and Elementor widgets. See the Waveleta WordPress guide.

FAQ

Is there an official Waveleta SDK?
You don't need one. The API is plain JSON over HTTPS, and the OpenAPI spec lets you generate a client in most languages.

Which header should I use, Bearer or X-Api-Key?
Either works. Pick one and use it consistently.

Does a failed request cost money?
Requests rejected for an invalid key (401) or a low balance (402) aren't billed.

Can I call the API from the browser?
Technically yes, but don't: it exposes your key. Call it server-side.

Create your Waveleta API key →

Informational only, not financial advice. Waveleta is not a broker.

Top comments (0)