SDKs

Official SDKs are coming soon. In the meantime, the examples below show how to build a lightweight client wrapper around the REST API.

Official SDKs coming soon

Official Python and JavaScript/TypeScript SDKs are in development and will be released soon. In the meantime, the REST API is fully functional — use the client examples below to get started immediately.

Python client example

A minimal Python class that wraps the most common API calls. Drop this into your project while you wait for the official SDK.

bitpredict_client.py
import os
import requests
import time
from typing import Optional

class BitPredictClient:
    """Unofficial Python client for the BitPredict API."""

    BASE_URL = "https://api.bitpredict.ai/v1"

    def __init__(self, api_key: Optional[str] = None):
        self.api_key = api_key or os.environ["BITPREDICT_API_KEY"]
        self.session = requests.Session()
        self.session.headers.update({"X-API-Key": self.api_key})

    def _get(self, path: str, **params) -> dict:
        r = self.session.get(f"{self.BASE_URL}{path}", params=params)
        r.raise_for_status()
        return r.json()

    def _post(self, path: str, body: dict) -> dict:
        r = self.session.post(f"{self.BASE_URL}{path}", json=body)
        r.raise_for_status()
        return r.json()

    # Account
    def get_me(self) -> dict:
        return self._get("/account/me")

    def get_credits(self) -> dict:
        return self._get("/account/credits")

    # Data
    def get_catalog(self) -> dict:
        return self._get("/data/catalog")

    def get_bars(self, exchange: str, symbol: str, timeframe: str = "1h", **kwargs) -> dict:
        return self._get("/data/bars/time", exchange=exchange, symbol=symbol, timeframe=timeframe, **kwargs)

    # Strategies
    def get_strategies(self, sort_by: str = "sharpe_ratio", sort_dir: str = "desc", **kwargs) -> dict:
        return self._get("/strategies", sort_by=sort_by, sort_dir=sort_dir, **kwargs)

    def get_strategy(self, slug: str) -> dict:
        return self._get(f"/strategies/{slug}")

    def get_strategy_analytics(self, slug: str) -> dict:
        return self._get(f"/strategies/{slug}/analytics")

    # Backtests
    def submit_backtest(self, strategy_slug: str, start_date: str, end_date: str, initial_capital: float = 10000) -> dict:
        return self._post("/backtest/requests", {
            "strategy_slug": strategy_slug,
            "start_date": start_date,
            "end_date": end_date,
            "initial_capital": initial_capital,
        })

    def poll_backtest(self, request_id: int, interval: int = 5, timeout: int = 300) -> dict:
        elapsed = 0
        while elapsed < timeout:
            data = self._get(f"/backtest/requests/{request_id}")
            if data["status"] in ("completed", "failed"):
                return data
            time.sleep(interval)
            elapsed += interval
        raise TimeoutError(f"Backtest #{request_id} did not complete within {timeout}s")

    def get_backtest_analytics(self, request_id: int, strategy_slug: str) -> dict:
        return self._get(f"/backtest/requests/{request_id}/analytics", strategy_slug=strategy_slug)


# Usage
client = BitPredictClient()

# Fetch top strategies
strategies = client.get_strategies(page_size=5)
slug = strategies["data"][0]["slug"]

# Run backtest
job = client.submit_backtest(slug, "2024-01-01", "2026-01-01")
client.poll_backtest(job["request_id"])
analytics = client.get_backtest_analytics(job["request_id"], slug)
print(f"Sharpe: {analytics['sharpe_ratio']:.2f}")

TypeScript client example

A typed TypeScript class for use in Node.js or browser environments.

bitpredict-client.ts
// Unofficial TypeScript/JavaScript client for the BitPredict API

const BASE_URL = "https://api.bitpredict.ai/v1";

export class BitPredictClient {
  private headers: HeadersInit;

  constructor(apiKey?: string) {
    const key = apiKey ?? process.env.BITPREDICT_API_KEY;
    if (!key) throw new Error("BITPREDICT_API_KEY is required");
    this.headers = { "X-API-Key": key, "Content-Type": "application/json" };
  }

  private async get<T>(path: string, params?: Record<string, string>): Promise<T> {
    const url = new URL(`${BASE_URL}${path}`);
    if (params) Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
    const r = await fetch(url.toString(), { headers: this.headers });
    if (!r.ok) throw new Error(`API error ${r.status}: ${await r.text()}`);
    return r.json();
  }

  private async post<T>(path: string, body: unknown): Promise<T> {
    const r = await fetch(`${BASE_URL}${path}`, {
      method: "POST",
      headers: this.headers,
      body: JSON.stringify(body),
    });
    if (!r.ok) throw new Error(`API error ${r.status}: ${await r.text()}`);
    return r.json();
  }

  getMe() { return this.get("/account/me"); }
  getCatalog() { return this.get("/data/catalog"); }

  getBars(exchange: string, symbol: string, timeframe = "1h", extra: Record<string, string> = {}) {
    return this.get("/data/bars/time", { exchange, symbol, timeframe, ...extra });
  }

  getStrategies(sortBy = "sharpe_ratio", sortDir = "desc", pageSize = "20") {
    return this.get("/strategies", { sort_by: sortBy, sort_dir: sortDir, page_size: pageSize });
  }

  submitBacktest(strategySlug: string, startDate: string, endDate: string, initialCapital = 10000) {
    return this.post("/backtest/requests", {
      strategy_slug: strategySlug,
      start_date: startDate,
      end_date: endDate,
      initial_capital: initialCapital,
    });
  }

  async pollBacktest(requestId: number, interval = 5000, timeout = 300000) {
    const start = Date.now();
    while (Date.now() - start < timeout) {
      const data: Record<string, unknown> = await this.get(`/backtest/requests/${requestId}`);
      if (["completed", "failed"].includes(data.status as string)) return data;
      await new Promise(res => setTimeout(res, interval));
    }
    throw new Error("Backtest timed out");
  }
}

// Usage
const client = new BitPredictClient();
const strategies = await client.getStrategies();
const slug = (strategies as { data: { slug: string }[] }).data[0].slug;
const job = await client.submitBacktest(slug, "2024-01-01", "2026-01-01") as { request_id: number };
await client.pollBacktest(job.request_id);

Both examples are illustrative starting points. For production use, add proper error handling, logging, and exponential backoff. See the Rate Limits page for retry guidance.

SDKs & Libraries · BitPredict