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.