ZetariumZetariumDex

Python

A complete signed-request client and a few common workflows.

import time
import hmac
import hashlib
import requests
import uuid
from urllib.parse import urlencode

API_KEY = "zd_84444a6e..."
SECRET = "073CuVWk..."
BASE_URL = "https://api.zetariumdex.com"


def sign(secret: str, query_string: str) -> str:
    return hmac.new(secret.encode(), query_string.encode(), hashlib.sha256).hexdigest()


def signed_request(method: str, path: str, params: dict | None = None, body: dict | None = None):
    params = dict(params or {})
    params["timestamp"] = int(time.time() * 1000)

    # Build the canonical query string (sorted, URL-encoded; signature is appended afterwards).
    sorted_items = sorted(params.items())
    query_string = urlencode(sorted_items)
    signature = sign(SECRET, query_string)

    url = f"{BASE_URL}{path}?{query_string}&signature={signature}"
    headers = {"X-API-KEY": API_KEY}
    if body is not None:
        headers["Content-Type"] = "application/json"

    return requests.request(method, url, headers=headers, json=body)


# 1. Read futures balance
resp = signed_request("GET", "/v2/futures/balance")
print(resp.json())

# 2. Place an idempotent LIMIT BUY
client_order_id = str(uuid.uuid4())
resp = signed_request(
    "POST",
    "/v2/orders",
    body={
        "symbol": "BTCUSDT",
        "side": "BUY",
        "type": "LIMIT",
        "quantity": "0.001",
        "price": "30000",
        "clientOrderId": client_order_id,
    },
)
print(resp.json())

# 3. Retry the same order — should be idempotent
resp2 = signed_request(
    "POST",
    "/v2/orders",
    body={
        "symbol": "BTCUSDT",
        "side": "BUY",
        "type": "LIMIT",
        "quantity": "0.001",
        "price": "30000",
        "clientOrderId": client_order_id,
    },
)
assert resp2.json().get("idempotent") is True

# 4. Close an open position
resp = signed_request(
    "POST",
    "/v2/positions/close",
    body={"positionId": "cmod1234..."},
)
print(resp.json())