Bybit Golang SDK

August 29, 2026 ยท View on GitHub

Bybit Golang SDK

CI Tests Go vet CodeQL codecov Go Report Card Go Reference Go version License

A small Go client for the Bybit V5 API. It makes it easier to get started with the REST API, demo trading, WebSocket streams, and TradFi instruments without imposing an application architecture on your project.

๐Ÿ“š Looking for the deeper dive? Explore the bybit-go Wiki for guides, endpoint notes, and extended documentation.

Trading involves risk. Test both the integration and your strategy in the demo environment first, use narrowly scoped API-key permissions, and never commit keys to a repository.

Contents

Features

  • REST methods for market data, orders, accounts, and positions;
  • HMAC-SHA256 and RSA-SHA256 signing for REST requests;
  • demo mode plus regional REST and WebSocket endpoints;
  • public and private WebSocket subscriptions;
  • convenience helpers for TradFi instruments (forex, metals, stocks, and indices);
  • standalone working examples in examples/.

Installation

Go 1.21 or later is required.

go get github.com/tigusigalpa/bybit-go
import bybit "github.com/tigusigalpa/bybit-go"

Configuration

Create one client and reuse it for the lifetime of your application. The default HTTP client has a 30-second timeout. You may provide your own *http.Client when you need a proxy, custom transport, observability, or different timeout settings.

ClientConfig fieldDefaultDescription
APIKeyโ€”API key for signed endpoints.
APISecretโ€”API secret for HMAC signing.
DemofalseRoutes REST requests to the Bybit demo environment.
RegionglobalEndpoint region: global, nl, tr, kz, ge, or ae. demo also selects the demo REST endpoint.
RecvWindow5000Bybit receive window in milliseconds.
SignaturehmacSignature algorithm: hmac or rsa.
RSAPrivateKeyโ€”PEM private key, required when Signature is rsa.
HTTPClient30 s timeoutOptional custom HTTP client.
httpClient := &http.Client{Timeout: 10 * time.Second}
client, err := bybit.NewClient(bybit.ClientConfig{
	APIKey:     os.Getenv("BYBIT_API_KEY"),
	APISecret:  os.Getenv("BYBIT_API_SECRET"),
	Demo:       true,
	RecvWindow: 5_000,
	HTTPClient: httpClient,
})

Demo: true takes precedence over Region. Use demo credentials that belong to the demo environment; do not expect production credentials or balances to work there.

Quick start

Public requests use the same client and do not require an API key.

package main

import (
	"fmt"
	"log"

	bybit "github.com/tigusigalpa/bybit-go"
)

func main() {
	client, err := bybit.NewClient(bybit.ClientConfig{Demo: true})
	if err != nil {
		log.Fatal(err)
	}

	tickers, err := client.GetTickers(map[string]interface{}{
		"category": "linear",
		"symbol":   "BTCUSDT",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%+v\n", tickers["result"])
}

For account operations, pass credentials through environment variables:

client, err := bybit.NewClient(bybit.ClientConfig{
	APIKey:    os.Getenv("BYBIT_API_KEY"),
	APISecret: os.Getenv("BYBIT_API_SECRET"),
	Demo:      true,
	Region:    "global", // also: nl, tr, kz, ge, ae
})

REST API

Methods return the decoded Bybit response as map[string]interface{}. This deliberately leaves the full V5 request surface available: pass the exact fields documented by Bybit in the params map.

Market data

orderbook, err := client.GetOrderbook(map[string]interface{}{
	"category": "spot",
	"symbol":   "BTCUSDT",
	"limit":    50,
})

klines, err := client.GetKline(map[string]interface{}{
	"category": "linear",
	"symbol":   "BTCUSDT",
	"interval": "60",
	"limit":    200,
})

trades, err := client.GetRecentTrades(map[string]interface{}{
	"category": "linear",
	"symbol":   "BTCUSDT",
})

Available market helpers include GetServerTime, GetTickers, GetKline, GetOrderbook, GetRPIOrderbook, GetOpenInterest, GetRecentTrades, GetFundingRateHistory, GetHistoricalVolatility, GetInsurance, and GetRiskLimit.

Account and positions

wallet, err := client.GetWalletBalance(map[string]interface{}{
	"accountType": "UNIFIED",
})
positions, err := client.GetPositions(map[string]interface{}{
	"category": "linear",
	"symbol":   "BTCUSDT",
})

The client also provides helpers for account info, transaction logs, open and closed positions, trading stops, margin, leverage, and risk-limit operations. Refer to the official V5 documentation for endpoint-specific required fields and account-mode rules.

Orders and positions

API parameters are passed through directly, so you can use newly added Bybit fields without waiting for an SDK release.

order, err := client.CreateOrder(map[string]interface{}{
	"category":    "linear",
	"symbol":      "BTCUSDT",
	"side":        "Buy",
	"orderType":   "Limit",
	"qty":         "0.001",
	"price":       "30000",
	"timeInForce": "GTC",
})
if err != nil {
	log.Fatal(err)
}
fmt.Println(order)

For a higher-level order helper, PlaceOrder can calculate a derivatives quantity from margin, price, and leverage. Use it only when that calculation matches your instrument's quantity rules; for precise production order sizing, retrieve instrument constraints and submit CreateOrder yourself.

SetLeverage rejects a non-positive leverage value and accepts Buy or Sell when changing one side only. Passing no side changes both buy and sell leverage.

Demo trading

NewDemoClient creates a DemoClient with Demo enabled. It exposes the usual order and account helpers as well as demo-specific operations such as funding requests.

demo, err := bybit.NewDemoClient(bybit.ClientConfig{
	APIKey:    os.Getenv("BYBIT_DEMO_API_KEY"),
	APISecret: os.Getenv("BYBIT_DEMO_API_SECRET"),
})
if err != nil {
	log.Fatal(err)
}

result, err := demo.ApplyForDemoFundsSimple("USDT", "10000")

Errors and response handling

There are two error layers to handle:

  1. Transport, request-construction, HTTP-status, signature, and JSON decoding failures are returned as Go errors.
  2. A Bybit business error, represented by a non-zero retCode, usually arrives with HTTP 200. It is returned in the response map and must be checked by the caller.
response, err := client.CreateOrder(params)
if err != nil {
	var httpErr *bybit.HTTPError
	if errors.As(err, &httpErr) {
		log.Printf("Bybit HTTP failure: status=%d body=%s", httpErr.StatusCode, httpErr.Body)
	}
	log.Fatal(err)
}

if code, ok := response["retCode"].(float64); !ok || code != 0 {
	log.Fatalf("Bybit rejected request: code=%v message=%v", response["retCode"], response["retMsg"])
}

For public calls, an empty API key produces an empty HMAC signature. Bybit may ignore these headers for public endpoints, but authenticated operations require valid credentials. Treat API responses as untrusted input: check types before using nested values from the decoded map.

RSA signatures

For an RSA API key, provide its PEM-encoded private key. Signature: "rsa" requires a private key, and unsupported signature types are rejected when creating the client.

client, err := bybit.NewClient(bybit.ClientConfig{
	APIKey:        os.Getenv("BYBIT_API_KEY"),
	Signature:     "rsa",
	RSAPrivateKey: os.Getenv("BYBIT_RSA_PRIVATE_KEY"),
})

WebSocket

ws := bybit.NewWebSocket(bybit.WebSocketConfig{Demo: true})
defer ws.Close()

ws.OnMessage(func(message map[string]interface{}) {
	fmt.Printf("%+v\n", message)
})

if err := ws.SubscribeTicker("BTCUSDT"); err != nil {
	log.Fatal(err)
}
if err := ws.Listen(); err != nil {
	log.Fatal(err)
}

The package's public WebSocket connects to the spot endpoint. For private streams, set IsPrivate together with APIKey and APISecret; the client authenticates after connecting.

HelperTopic
SubscribeOrderbook("BTCUSDT", 50)orderbook.50.BTCUSDT
SubscribeTrade("BTCUSDT")publicTrade.BTCUSDT
SubscribeTicker("BTCUSDT")tickers.BTCUSDT
SubscribeKline("BTCUSDT", "1")kline.1.BTCUSDT
SubscribePosition, SubscribeOrder, SubscribeExecution, SubscribeWalletPrivate account topics

Call Unsubscribe with the exact topics when they are no longer needed. Your application owns the connection lifecycle and should reconnect after an error; on reconnect, subscribe again using GetSubscriptions as your source of truth.

TradFi

The package includes lists of popular instruments and focused helper methods:

tickers, err := client.GetTradFiTicker("XAUUSD")
positions, err := client.GetTradFiPositions("XAUUSD")
order, err := client.PlaceTradFiOrder(bybit.TradFiOrderParams{
	Symbol: "XAUUSD", Side: "Buy", OrderType: "Market", Qty: "1",
})

Instrument availability and trading conditions vary by account and region. Call GetTradFiInstruments to retrieve the current list before placing an order.

Examples, testing, and contributing

See the examples directory for basic client, market data, orders, positions, demo trading, TradFi, and WebSocket programs. Examples may make network calls or require credentials, so read their source before running them.

go test ./...
go vet ./...

CI runs these checks on Go 1.21 and the current stable Go release. Pull requests are welcome: please add a test when changing behavior, and never include real API keys or personal data.

The repository's GitHub Actions workflow additionally runs the test suite with Go's race detector. Before opening a pull request, format changed Go files with gofmt and keep go.mod and go.sum tidy.

Documentation and license