Developers

Seeds API v1

A Binance-shaped REST API on a non-custodial exchange. Your bot trades directly from a wallet you control — there is no exchange balance to fund and no exchange balance to lose. Point an existing Binance-style client at this base URL and most calls work unchanged.

What's different from a normal exchange

  • No deposits. Balances live in your own wallet. The /account response returns your addresses and your live trading authorizations instead of exchange credits.
  • Authorizations gate trading. A bot can only trade assets you have authorized, up to the cap you set, until the expiry you chose. When the expiry hits, the delegated key is destroyed.
  • API keys can never withdraw. There is no withdrawal endpoint. Scopes are read and trade only; withdrawals happen in the signed-in UI. A stolen key cannot move funds off-chain to an attacker.
  • Fills settle on-chain. A match triggers a real transfer between the two wallets. /myTrades returns each settlement leg with its txid and confirmation count.
  • Streams are SSE, not WebSocket. The edge runtime has no long-lived sockets. SSE gives you the same push semantics over plain HTTP.

Authentication

Signed endpoints use HMAC-SHA256 exactly like Binance. Send your key ID in the X-SEEDS-APIKEY header, append timestamp (unix ms) and optionally recvWindow (default 5000ms, max 60000ms), then append signature as the last parameter.

The signed payload is the query string with signature removed, concatenated with the raw request body if there is one.

import crypto from "node:crypto";

const KEY = process.env.SEEDS_KEY;      // seeds_xxxxxxxx
const SECRET = process.env.SEEDS_SECRET;
const BASE = "https://seeds.honest.money";

function signed(path, params) {
  const qs = new URLSearchParams({ ...params, timestamp: Date.now() }).toString();
  const sig = crypto.createHmac("sha256", SECRET).update(qs).digest("hex");
  return `${BASE}${path}?${qs}&signature=${sig}`;
}

// Place an order
const res = await fetch(signed("/api/public/v1/order", {
  symbol: "TXCUSDC", side: "BUY", type: "LIMIT",
  timeInForce: "GTC", price: "0.25", quantity: "100",
}), { method: "POST", headers: { "X-SEEDS-APIKEY": KEY } });

console.log(await res.json());

Endpoints

MethodPathWeightNotes
GET/api/public/v1/ping1Connectivity check.
GET/api/public/v1/time1Server time in unix ms — sync before signing.
GET/api/public/v1/exchangeInfo10Symbols, filters, precision, rate limits.
GET/api/public/v1/depth5Aggregated order book. `symbol`, `limit` (max 1000).
GET/api/public/v1/trades5Recent public trades. `symbol`, `limit`.
GET/api/public/v1/klines5OHLCV candles. `symbol`, `interval`, `limit`.
GET/api/public/v1/ticker/24hr524h stats for one symbol or all.
GET/api/public/v1/ticker/price2Last price for one symbol or all.
GET/api/public/v1/stream—SSE stream: ticker, depth, trade events.
GET/api/public/v1/account10SIGNED. Addresses + live trading authorizations.
GET/api/public/v1/openOrders6SIGNED. Working orders.
GET/api/public/v1/allOrders10SIGNED. Order history.
GET/api/public/v1/myTrades10SIGNED. Fills with on-chain settlement legs and txids.
POST/api/public/v1/order20SIGNED, trade scope. New LIMIT/GTC order.
DELETE/api/public/v1/order4SIGNED, trade scope. Cancel by `orderId`.
GET/api/public/cmc—CoinMarketCap-format market data.

Symbols and filters

Symbols are concatenated, Binance style: TXCUSDC, TXCTSD, LTCTSD. Underscore, slash and dash forms are accepted too. Fetch /exchangeInfo at startup for the live symbol list, tick size, lot size and minimum notional per market.

Rate limits

1200 request weight per key per minute, plus per-endpoint weights shown above. Exceeding it returns HTTP 429 with code -1003. Back off, don't hammer. Optional IP allowlists per key add a second layer of protection.

Streaming (SSE)

curl -N "https://seeds.honest.money/api/public/v1/stream?symbol=TXCUSDC&streams=ticker,depth,trade"

event: ticker
data: {"symbol":"TXCUSDC","lastPrice":"0.25000000", ...}

Connections close after 10 minutes; reconnect (EventSource does it automatically). Events: open, ticker, depth, trade, close, error.

Errors

Errors return a numeric code and message, so bots branch on the code, not the text.

{"code":-1022,"msg":"Signature for this request is not valid"}

-1003 rate limit exceeded      -1021 timestamp outside recvWindow
-1004 IP not in allowlist      -1022 bad signature
-1102 missing parameter        -1121 invalid symbol
-2010 order rejected           -2011 cancel rejected
-2013 no such order            -2015 invalid or disabled API key