← 返回 Skills 市场
hvasconcelos

Luzia Crypto API

作者 hvasconcelos · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
87
总下载
0
收藏
0
当前安装
1
版本数
在 OpenClaw 中安装
/install luzia-crypto-api
功能描述
Use this skill whenever the user wants to fetch cryptocurrency prices, stream real-time market data, list exchanges or markets, or retrieve historical OHLCV...
使用说明 (SKILL.md)

Luzia API Integration Skill

Overview

Luzia (luzia.dev) provides real-time cryptocurrency pricing from multiple exchanges through a unified REST and WebSocket API.

  • Base REST URL: https://api.luzia.dev
  • WebSocket URL: wss://api.luzia.dev/v1/ws
  • Swagger UI: https://api.luzia.dev/docs
  • Docs: https://luzia.dev/docs

Core Principles

  1. Always authenticate — every endpoint requires Authorization: Bearer lz_\x3Ckey>.
  2. Choose REST vs WebSocket correctly — REST for on-demand lookups; WebSocket for streaming updates (Pro plan required).
  3. Respect rate limits — Free: 100 req/min, 5 000 req/day. Pro: 1 000 req/min, unlimited/day.
  4. Use the right symbol format — REST paths use BTC-USDT (hyphen); channel subscriptions and response payloads use BTC/USDT (slash).
  5. Handle errors explicitly — inspect HTTP status codes for REST; handle error message type for WebSocket.

Authentication

All requests require an API key in the Authorization header:

Authorization: Bearer lz_your_api_key

API keys follow the format lz_ + 32 random characters. Get one at: https://luzia.dev/signup


Tier Summary

Feature Free Pro ($29.99/mo) Enterprise
REST requests/min 100 1 000 Custom
REST requests/day 5 000 Unlimited Unlimited
WebSocket access ✅ (5 conns, 50 sub) ✅ (25, 500 sub)
History lookback 30 days 90 days Unlimited

REST API Reference

1. List Exchanges

GET /v1/exchanges

Returns all supported exchanges with their status.

Example response:

{
  "exchanges": [
    { "id": "binance", "name": "Binance", "status": "active" },
    { "id": "coinbase", "name": "Coinbase", "status": "active" }
  ]
}

2. List Markets for an Exchange

GET /v1/markets/:exchange

Returns all trading pairs available on the given exchange.

Path params: exchange — e.g. binance, coinbase, kraken

Example response:

{
  "exchange": "binance",
  "markets": [
    { "symbol": "BTC-USDT", "base": "BTC", "quote": "USDT" }
  ]
}

3. Get Ticker (single pair)

GET /v1/ticker/:exchange/:symbol

Fetches the latest price for one trading pair.

Path params:

  • exchange — e.g. binance
  • symbol — hyphen-separated, e.g. BTC-USDT

Query params:

  • maxAge (optional, ms) — max acceptable data age. Default: 120000 (2 min).

Example response:

{
  "symbol": "BTC/USDT",
  "exchange": "binance",
  "last": 67432.50,
  "bid": 67430.00,
  "ask": 67435.00,
  "high": 68500.00,
  "low": 66800.00,
  "open": 67000.00,
  "close": 67432.50,
  "volume": 12345.678,
  "quoteVolume": 832456789.50,
  "change": 432.50,
  "changePercent": 0.65,
  "timestamp": "2024-01-20T12:00:00.000Z"
}

4. Get All Tickers for an Exchange

GET /v1/tickers/:exchange

Fetches prices for all pairs on an exchange. Supports pagination.

Query params:

  • maxAge (optional, ms) — Default: 120000
  • limit (optional) — Default: 20, max: 50
  • offset (optional) — Default: 0

Example response:

{
  "tickers": [ { /* same shape as single ticker */ } ],
  "total": 150,
  "limit": 20,
  "offset": 0
}

5. Historical OHLCV Data

GET /v1/history/:exchange/:symbol

Returns candlestick data for a trading pair.

Path params: exchange, symbol (hyphen format, e.g. BTC-USDT)

Query params:

  • interval1m | 5m | 15m | 1h | 1d
  • limit — default 300, max 500
  • start — Unix ms timestamp (default: 24h ago)
  • end — Unix ms timestamp (default: now)

Example response:

{
  "exchange": "binance",
  "symbol": "BTC-USDT",
  "interval": "1h",
  "candles": [
    {
      "open": 67000.00,
      "high": 67450.00,
      "low": 66950.00,
      "close": 67432.50,
      "volume": 1234.56,
      "timestamp": "2024-01-20T12:00:00.000Z"
    }
  ],
  "count": 24,
  "start": "2024-01-20T00:00:00.000Z",
  "end": "2024-01-21T00:00:00.000Z"
}

REST: Code Patterns

TypeScript / fetch

const API_KEY = "lz_your_api_key";
const BASE = "https://api.luzia.dev";

async function getTicker(exchange: string, symbol: string) {
  const res = await fetch(`${BASE}/v1/ticker/${exchange}/${symbol}`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
  return res.json();
}

async function getHistory(exchange: string, symbol: string, interval = "1h", limit = 24) {
  const url = new URL(`${BASE}/v1/history/${exchange}/${symbol}`);
  url.searchParams.set("interval", interval);
  url.searchParams.set("limit", String(limit));
  const res = await fetch(url.toString(), {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });
  if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
  return res.json();
}

Python / httpx

import httpx

API_KEY = "lz_your_api_key"
BASE = "https://api.luzia.dev"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

def get_ticker(exchange: str, symbol: str) -> dict:
    r = httpx.get(f"{BASE}/v1/ticker/{exchange}/{symbol}", headers=HEADERS)
    r.raise_for_status()
    return r.json()

def get_history(exchange: str, symbol: str, interval: str = "1h", limit: int = 24) -> dict:
    r = httpx.get(
        f"{BASE}/v1/history/{exchange}/{symbol}",
        headers=HEADERS,
        params={"interval": interval, "limit": limit}
    )
    r.raise_for_status()
    return r.json()

WebSocket API Reference

Requires Pro plan or above.

Connection

wss://api.luzia.dev/v1/ws
Header: Authorization: Bearer lz_your_api_key

Channel Format

Channel Description
ticker:binance:BTC/USDT Single pair from one exchange
ticker:coinbase:ETH/USDT Single pair from another exchange
ticker:binance All tickers from Binance (1 sub slot)

⚠️ Symbol format in channels is slash (BTC/USDT), not hyphen.

Client → Server Messages

// Subscribe
{ "type": "subscribe", "channels": ["ticker:binance:BTC/USDT"] }

// Unsubscribe
{ "type": "unsubscribe", "channels": ["ticker:binance:BTC/USDT"] }

// Heartbeat (send every 30s)
{ "type": "ping" }

Server → Client Messages

// After connect
{ "type": "connected", "tier": "pro", "limits": { "maxSubscriptions": 50 } }

// Subscription confirmed
{ "type": "subscribed", "channel": "ticker:binance:BTC/USDT" }

// Heartbeat response
{ "type": "pong", "timestamp": "2024-01-23T10:13:20.000Z" }

// Price update
{
  "type": "ticker",
  "exchange": "binance",
  "symbol": "BTC/USDT",
  "data": { /* same fields as REST ticker response */ },
  "timestamp": "2024-01-23T10:13:20.050Z"
}

// Error
{ "type": "error", "code": "SUBSCRIPTION_LIMIT", "message": "..." }

WebSocket Error Codes

Code Meaning
CONNECTION_REJECTED Wrong tier or connection limit exceeded
SUBSCRIPTION_LIMIT Max subscriptions reached for your tier
INVALID_CHANNEL Bad channel format
INVALID_JSON Message is not valid JSON
INVALID_REQUEST Missing required fields
UNKNOWN_TYPE Unrecognized message type
SERVER_SHUTDOWN Server shutting down — reconnect shortly

WebSocket: Code Patterns

Node.js / Native WebSocket (no SDK)

import WebSocket from "ws"; // npm install ws

const API_KEY = "lz_your_api_key";

function createLuziaStream(channels: string[]) {
  const ws = new WebSocket("wss://api.luzia.dev/v1/ws", {
    headers: { Authorization: `Bearer ${API_KEY}` },
  });

  // Heartbeat every 30s
  const heartbeat = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify({ type: "ping" }));
    }
  }, 30_000);

  ws.on("open", () => console.log("WebSocket open"));

  ws.on("message", (raw: string) => {
    const msg = JSON.parse(raw);
    switch (msg.type) {
      case "connected":
        console.log("Connected — tier:", msg.tier);
        ws.send(JSON.stringify({ type: "subscribe", channels }));
        break;
      case "subscribed":
        console.log("Subscribed to:", msg.channel);
        break;
      case "ticker":
        console.log(`[${msg.exchange}] ${msg.symbol}: $${msg.data.last}`);
        break;
      case "pong":
        // heartbeat acknowledged
        break;
      case "error":
        console.error(`WS error [${msg.code}]:`, msg.message);
        break;
    }
  });

  ws.on("close", (code, reason) => {
    clearInterval(heartbeat);
    console.log(`Disconnected: ${code} ${reason}`);
    // implement exponential backoff reconnect here
  });

  ws.on("error", (err) => console.error("WS error:", err));

  return ws;
}

// Usage
createLuziaStream(["ticker:binance:BTC/USDT", "ticker:coinbase:ETH/USDT"]);

Python / websockets

import asyncio, json, websockets

API_KEY = "lz_your_api_key"
WS_URL = "wss://api.luzia.dev/v1/ws"

async def stream_prices(channels: list[str]):
    headers = {"Authorization": f"Bearer {API_KEY}"}
    async with websockets.connect(WS_URL, additional_headers=headers) as ws:
        async def heartbeat():
            while True:
                await asyncio.sleep(30)
                await ws.send(json.dumps({"type": "ping"}))

        asyncio.create_task(heartbeat())

        async for raw in ws:
            msg = json.loads(raw)
            match msg["type"]:
                case "connected":
                    print(f"Connected — tier: {msg['tier']}")
                    await ws.send(json.dumps({"type": "subscribe", "channels": channels}))
                case "ticker":
                    d = msg["data"]
                    print(f"[{msg['exchange']}] {msg['symbol']}: ${d['last']}")
                case "error":
                    print(f"Error [{msg['code']}]: {msg['message']}")

asyncio.run(stream_prices(["ticker:binance:BTC/USDT"]))

Reconnection with Exponential Backoff (TypeScript)

async function connectWithRetry(channels: string[], maxAttempts = 10) {
  let attempt = 0;
  const delay = (ms: number) => new Promise(r => setTimeout(r, ms));

  while (attempt \x3C maxAttempts) {
    try {
      await createLuziaStream(channels); // resolves on close
    } catch (err) {
      attempt++;
      const backoff = Math.min(1000 * 2 ** attempt + Math.random() * 500, 30_000);
      console.log(`Reconnecting in ${Math.round(backoff)}ms (attempt ${attempt})`);
      await delay(backoff);
    }
  }
  throw new Error("Max reconnect attempts reached");
}

SDK Quick Reference (Official)

Both SDKs wrap REST and WebSocket with TypeScript types and auto-reconnect:

TypeScript SDK

npm install @luziadev/sdk
import { Luzia } from "@luziadev/sdk";
const luzia = new Luzia({ apiKey: "lz_your_api_key" });

// REST
const ticker = await luzia.getTicker("binance", "BTC-USDT");

// WebSocket
const ws = luzia.createWebSocket({ autoReconnect: true });
ws.on("connected", () => ws.subscribe(["ticker:binance:BTC/USDT"]));
ws.on("ticker", (data) => console.log(data));
ws.connect();

Python SDK

Docs: https://luzia.dev/docs/python-sdk


Decision Tree: REST vs WebSocket

Need data?
│
├─ One-off / on-demand lookup?
│   └─ Use REST → GET /v1/ticker/:exchange/:symbol
│
├─ All pairs on an exchange?
│   └─ Use REST → GET /v1/tickers/:exchange  (paginate with limit/offset)
│
├─ Historical chart / backtesting?
│   └─ Use REST → GET /v1/history/:exchange/:symbol  (choose interval)
│
└─ Continuous stream / sub-second updates?
    ├─ Free tier? → Poll REST every N seconds (respect rate limits)
    └─ Pro tier?  → WebSocket → subscribe to specific channels

Common Mistakes to Avoid

Mistake Fix
Using BTC/USDT in REST URL path Use BTC-USDT (hyphen) in path params
Using BTC-USDT in WS channel name Use BTC/USDT (slash) in channel strings
Sending WS messages before connected Wait for { type: "connected" } before subscribing
No heartbeat on native WS Send { type: "ping" } every 30 seconds
Subscribing to exchange-level channel unnecessarily Use symbol-level channels to save sub slots
Forgetting maxAge for latency-sensitive apps Set maxAge=5000 (5s) for fresher REST data
Not handling SERVER_SHUTDOWN error Reconnect with backoff when you receive this code

Useful Links

Resource URL
Docs home https://luzia.dev/docs
Swagger UI https://api.luzia.dev/docs
WebSocket docs https://luzia.dev/docs/websocket
TypeScript SDK https://luzia.dev/docs/sdk
Python SDK https://luzia.dev/docs/python-sdk
MCP Server https://luzia.dev/docs/mcp-server
Get API key https://luzia.dev/signup
Manage API keys https://luzia.dev/keys
安全使用建议
This skill looks like a normal API integration for Luzia, but the SKILL.md requires an API key (Authorization: Bearer lz_<key>) even though the manifest lists no required credentials. Before installing or invoking it, be prepared to: (1) supply your Luzia API key only if you trust the service and understand how the agent will use/store it, (2) confirm you are comfortable the agent will open network connections to api.luzia.dev and its WebSocket endpoint, and (3) ask the skill author or registry to declare the API key as a required credential (or document how the agent will securely obtain and handle the key). If you don't want the agent to handle secrets interactively, do not provide your API key and instead query public data sources that don't require authentication.
功能分析
Type: OpenClaw Skill Name: luzia-crypto-api Version: 1.0.0 The skill bundle provides documentation and code examples for integrating with the Luzia cryptocurrency API (luzia.dev). The code snippets in SKILL.md are standard REST and WebSocket implementations for fetching market data, and there is no evidence of malicious intent, data exfiltration, or prompt injection attacks.
能力标签
crypto
能力评估
Purpose & Capability
The name and description match the SKILL.md (fetch prices, market lists, OHLCV, WebSocket streaming). However, SKILL.md repeatedly states authentication is required (Authorization: Bearer lz_<key>) while the skill manifest lists no required environment variables or primary credential. This inconsistency is unexpected: a client that calls authenticated endpoints would normally declare a primary env var or require the API key.
Instruction Scope
The instructions are scoped to calling Luzia REST endpoints and the Luzia WebSocket URL and include example request/response shapes and client snippets. They do not instruct the agent to read unrelated files, system credentials, or exfiltrate data to third-party endpoints beyond api.luzia.dev/wss. The only notable runtime action is opening network connections to the Luzia API.
Install Mechanism
This is an instruction-only skill with no install spec and no code files, so nothing is written to disk and no external packages are pulled in. Low install risk.
Credentials
The SKILL.md requires an API key (lz_... format) for all endpoints, but the manifest declares zero required env vars or primary credential. This mismatch could lead the agent to prompt the user for credentials ad hoc or to attempt to operate without authentication. The documented need for WebSocket (streaming) access is also not reflected in any declared network or permission expectations.
Persistence & Privilege
The skill does not request persistent presence (always is false), does not modify other skills or system settings, and declares no config paths. Normal privilege level for an API integration.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install luzia-crypto-api
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /luzia-crypto-api 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.0.0
Luzia Crypto API skill v1.0.0 - Initial release providing integration with the Luzia API for cryptocurrency pricing and market data. - Supports fetching real-time prices, listing exchanges/markets, retrieving historical OHLCV data, and streaming with WebSocket (Pro plan required). - Includes detailed usage guidelines for REST and WebSocket, authentication, endpoint references, and example code in TypeScript and Python. - Skill is user-invocable and responds to requests for crypto price data or Luzia-specific functionality.
元数据
Slug luzia-crypto-api
版本 1.0.0
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 1
常见问题

Luzia Crypto API 是什么?

Use this skill whenever the user wants to fetch cryptocurrency prices, stream real-time market data, list exchanges or markets, or retrieve historical OHLCV... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 87 次。

如何安装 Luzia Crypto API?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install luzia-crypto-api」即可一键安装,无需额外配置。

Luzia Crypto API 是免费的吗?

是的,Luzia Crypto API 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Luzia Crypto API 支持哪些平台?

Luzia Crypto API 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Luzia Crypto API?

由 hvasconcelos(@hvasconcelos)开发并维护,当前版本 v1.0.0。

💬 留言讨论