Backpack Exchange API: ED25519 auth, 70 endpoints, and the official Rust SDK
Backpack Exchange offers a full REST and WebSocket API backed by ED25519 keypair signing. The official SDK is Rust-only; community Python clients cover all 70 endpoints. Here is the complete developer picture: auth, market data, order management, capital, and real-time streams.
devrels.xyz/a/119short linkBackpack Exchange is a Solana-native exchange built by the team behind the Anchor framework, the xNFT standard, and the Backpack wallet. Unlike most centralised exchanges, Backpack's API uses ED25519 keypair authentication — the same cryptographic primitive as Solana itself. There is no API secret string to leak; there is a private key you sign requests with and a public key the server verifies against. The official documentation is at docs.backpack.exchange and the official Rust client at github.com/backpack-exchange/bpx-api-client.

Authentication
All state-mutating requests require four headers. The signature covers the instruction string (method + path + body parameters, sorted) plus timestamp and window, signed with your ED25519 private key.
import { Keypair } from "@solana/web3.js";
import nacl from "tweetnacl";
const keypair = Keypair.generate(); // or load from file
const publicKey = Buffer.from(keypair.publicKey.toBytes()).toString("base64");
function signRequest(
method: string,
path: string,
params: Record<string, string>,
timestamp: number,
window = 5000
): string {
// Build the instruction string
const sorted = Object.entries(params)
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `${k}=${v}`)
.join("&");
const instruction = [`instruction=${method}${path}`, sorted, `timestamp=${timestamp}`, `window=${window}`]
.filter(Boolean)
.join("&");
const sig = nacl.sign.detached(
Buffer.from(instruction),
keypair.secretKey
);
return Buffer.from(sig).toString("base64");
}
// Request headers
const headers = {
"X-API-Key": publicKey,
"X-Signature": signRequest("GET", "/api/v1/capital", {}, Date.now()),
"X-Timestamp": Date.now().toString(),
"X-Window": "5000", // ms — replay attack window
};The X-Window parameter sets how long a signed request remains valid (default 5000ms, maximum 60000ms). Requests arriving outside the window are rejected, preventing replay attacks. Public endpoints — market data, assets, tickers — require no headers.
REST endpoints
The REST base URL is https://api.backpack.exchange/. Endpoints split into two host prefixes: /api/v1/ for trading operations and /wapi/v1/ for capital management (deposits, withdrawals).
# ── Market data (public, no auth) ──────────────────────────────────
GET /api/v1/assets # all tradeable assets
GET /api/v1/markets # all markets with specs
GET /api/v1/ticker?symbol= # single ticker
GET /api/v1/tickers # all tickers
GET /api/v1/depth?symbol= # order book (default 1000 levels per side)
GET /api/v1/klines?symbol=&interval= # OHLCV candles
GET /api/v1/fundingRates # perpetual funding
GET /api/v1/markPrices # mark + index prices
# ── Orders (authenticated) ──────────────────────────────────────────
GET /api/v1/order?symbol=&orderId= # single open order
POST /api/v1/order # execute order
DELETE /api/v1/order # cancel order
GET /api/v1/orders?symbol= # all open orders
DELETE /api/v1/orders # cancel all open orders
POST /api/v1/orders # batch order submit
# ── Capital (authenticated) ─────────────────────────────────────────
GET /api/v1/capital # balances
GET /wapi/v1/capital/deposits # deposit history
GET /wapi/v1/capital/deposit/address # deposit address
GET /wapi/v1/capital/withdrawals # withdrawal history
POST /wapi/v1/capital/withdrawals # request withdrawal
# ── Futures (authenticated) ─────────────────────────────────────────
GET /api/v1/futures/position # open futures positions
# ── Borrow / Lend (authenticated) ───────────────────────────────────
GET /api/v1/borrow-lend/positions # lending positions
# ── RFQ — Request for Quote (authenticated) ─────────────────────────
POST /api/v1/rfq # create RFQ
GET /api/v1/rfq/quote # get quote
POST /api/v1/rfq/accept # accept quote
POST /api/v1/rfq/cancel # cancel RFQ
POST /api/v1/rfq/refresh # refresh quote
# ── Vault (authenticated) ───────────────────────────────────────────
POST /api/v1/vault/mint # mint vault tokens
POST /api/v1/vault/redeem # redeem vault tokensOrder execution
Backpack processes all orders through a single linear command stream into one matching engine, regardless of how many API clients are connected. Order IDs are now randomly generated (changed June 2025 from timestamp-derived). Orders support stop-loss and take-profit fields natively.
// Execute a limit order
const payload = {
symbol: "SOL_USDC",
side: "Bid", // "Bid" | "Ask"
orderType: "Limit",
price: "145.50",
quantity: "1.0",
timeInForce: "GTC", // GTC | IOC | FOK
// Optional: stop-loss and take-profit
stopLossPrice: "140.00",
takeProfitPrice: "155.00",
};
const res = await fetch("https://api.backpack.exchange/api/v1/order", {
method: "POST",
headers: { ...authHeaders, "Content-Type": "application/json" },
body: JSON.stringify(payload),
});WebSocket streams
Real-time data streams from wss://ws.backpack.exchange/. Subscribe to multiple channels in one connection.
const ws = new WebSocket("wss://ws.backpack.exchange/");
ws.onopen = () => {
// Public streams — no auth needed
ws.send(JSON.stringify({
method: "SUBSCRIBE",
params: [
"ticker.SOL_USDC", // real-time ticker
"depth.SOL_USDC", // order book updates
"trade.SOL_USDC", // trade feed
"kline.SOL_USDC.1m", // 1-minute candles
],
}));
// Private streams — signed subscription
ws.send(JSON.stringify({
method: "SUBSCRIBE",
params: ["account.orderUpdate"], // requires auth headers
signature: [...], // ED25519 signed subscription
}));
};
ws.onmessage = (msg) => {
const data = JSON.parse(msg.data);
// data.stream: "ticker.SOL_USDC" | "depth.SOL_USDC" | ...
};The Rust SDK
The official client at github.com/backpack-exchange/bpx-api-client is Rust-only. It wraps all REST and WebSocket endpoints with typed request/response structs, handles ED25519 signing internally, and requires only your base64-encoded secret key to initialise.
use bpx_api_client::{BACKPACK_API_BASE_URL, BpxClient};
#[tokio::main]
async fn main() {
let client = BpxClient::init(
BACKPACK_API_BASE_URL.to_string(),
"your_base64_secret_key",
None, // optional extra headers
).expect("failed to init client");
// Market data — no auth needed
let markets = client.get_markets().await.unwrap();
println!("markets: {}", markets.len());
// Open orders for a symbol
let orders = client.get_open_orders(Some("SOL_USDC")).await.unwrap();
println!("open orders: {:?}", orders);
// Account balances
let balances = client.get_balances().await.unwrap();
println!("balances: {:?}", balances);
// Execute an order
let order = client.execute_order(ExecuteOrderPayload {
symbol: "SOL_USDC".into(),
side: Side::Bid,
order_type: OrderType::Limit,
price: Some("145.50".into()),
quantity: "1.0".into(),
..Default::default()
}).await.unwrap();
}
// Build from source
// cd rust && just build
// cargo add bpx-api-clientPython SDK (community)
The community backpack-exchange-sdk on PyPI covers all 70 endpoints including REST and WebSocket and is the fastest path if you are not working in Rust.
pip install backpack-exchange-sdkfrom backpack_exchange_sdk.authenticated import AuthenticationClient
client = AuthenticationClient(
public_key="your_base64_public_key",
secret_key="your_base64_secret_key"
)
# Balances
balances = client.get_balances()
# Place order
order = client.execute_order(
symbol="SOL_USDC",
side="Bid",
order_type="Limit",
price="145.50",
quantity="1.0",
time_in_force="GTC"
)
# Cancel all open orders for a symbol
client.cancel_open_orders("SOL_USDC")Rate limits
Limits are applied per sub-account: 2000 requests per minute across standard REST endpoints, 30 requests per minute for historical market data endpoints. WebSocket connections are not rate-limited by request count but are subject to connection-level limits.
# Check current rate limit headers on any response:
# X-RateLimit-Limit: 2000
# X-RateLimit-Remaining: 1998
# X-RateLimit-Reset: 1719600000000Keep reading
Superstate ships tokenized Treasuries (USTB) and crypto carry (USCC) on Solana as Token-2022, plus Opening Bell equities and FundOS for asset managers. For builders: public NAV/yield endpoints, signed partner APIs, Solana allowlist thaw, and onboarding that returns a partially signed SVM transaction.
Sanctum has 200+ LSTs and two developer products: a swap API at sanctum-api.ironforge.network (stake, unstake, swap any LST with slippage control and route filtering) and Gateway at gateway.sanctum.so (buildGatewayTransaction + sendTransaction — routes through Jito, SWQoS, Paladin, and refunds Jito tips if the tx lands via RPC).
npm i -g @alchemy/cli then alchemy auth. From there: balances, ERC-20 tokens, NFTs, swap, bridge, simulate, solana send, solana rpc, webhooks, app management — all from the terminal. --json and --no-interactive make every command pipeline-safe.
Get new articles in your inbox
Technical deep-dives on Solana tooling, infrastructure, and ecosystem. No noise.
