bitget

package module
v1.0.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: MIT Imports: 22 Imported by: 0

README

Bitget Go SDK

Bitget Golang SDK

Go Version License Go Reference Tests Codecov CodeQL

A clean, idiomatic Go SDK for the Bitget Unified Trading Account (UTA) API v3. Built for developers who want reliable market data, account management, and trading — without wrestling with raw HTTP signatures or silently losing precision to float64.

📖 Full documentation available on Wiki

A matching PHP/Laravel SDK lives at tigusigalpa/bitget-php if you also run services in that ecosystem.


Why this SDK?

Bitget's API is powerful, but building against raw HTTP can be tedious: signature schemes, subtle parameter encoding, reconnecting WebSockets, and the eternal problem of floating-point rounding in financial data. This package handles the boilerplate so you can focus on your trading logic.

It is intentionally dependency-light and Go-idiomatic:

  • context.Context is the first argument on every network call, so cancellation and timeouts behave the way you expect in Go.
  • You can inject your own *http.Client for proxies, custom transports, or test doubles.
  • Prices, quantities, PnL, and fees are returned as string, so you never lose a satoshi to float64 rounding.
  • Every endpoint returns a typed models.BitgetResponse[T] envelope instead of interface{}.
  • WebSockets reconnect automatically with exponential backoff and resubscribe to your channels.
  • Errors are plain Go sentinel errors (errors.Is) plus a typed *BitgetError (errors.As) for detailed API messages.
  • Only one required runtime dependency: gorilla/websocket. stretchr/testify is test-only.

Installation

go get github.com/tigusigalpa/bitget-go

Requires Go 1.21 or newer.


Quick start

1. Get your API credentials

Log in to the Bitget console, create an API key, and save:

  • BITGET_API_KEY
  • BITGET_SECRET_KEY
  • BITGET_PASSPHRASE

For your own safety, start with a Demo API key. You can switch to production later by changing the credentials and removing demo mode.

2. Make your first call
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	bitget "github.com/tigusigalpa/bitget-go"
	"github.com/tigusigalpa/bitget-go/models"
)

func main() {
	client := bitget.NewRestClient(
		os.Getenv("BITGET_API_KEY"),
		os.Getenv("BITGET_SECRET_KEY"),
		os.Getenv("BITGET_PASSPHRASE"),
	)

	tickers, err := client.Market.GetTickers(context.Background(), models.CategorySpot, "BTCUSDT")
	if err != nil {
		log.Fatal(err)
	}

	if len(tickers) > 0 {
		fmt.Printf("BTC/USDT last price: %s\n", tickers[0].LastPrice)
	}
}

That's it — the SDK signs the request, sets the right headers, parses the response envelope, and gives you typed data.


Configuration

NewRestClient accepts functional options so you can tune behavior without breaking the simple constructor:

Option Description Default
WithHTTPClient(*http.Client) Inject a custom HTTP client (proxy, custom TLS, tracing, etc.) &http.Client{Timeout: 15s}
WithBaseURL(string) Override the REST base URL https://api.bitget.com
WithDemoTrading() Send paptrading: 1 on every request. Use with a Demo API key. disabled
WithTimeout(time.Duration) Timeout for the internally built HTTP client 15s
WithLogger(Logger) Structured logger. Keys and signatures are never logged. no-op
WithLocale(string) locale header value en-US

Example with a custom HTTP client:

client := bitget.NewRestClient(
	os.Getenv("BITGET_API_KEY"),
	os.Getenv("BITGET_SECRET_KEY"),
	os.Getenv("BITGET_PASSPHRASE"),
	bitget.WithHTTPClient(&http.Client{
		Timeout:   30 * time.Second,
		Transport: myProxyTransport,
	}),
	bitget.WithDemoTrading(),
)

REST API coverage (Phase 1)

Category Methods Official docs
Market (public) GetInstruments, GetTickers, GetOrderBook Instruments · Tickers · OrderBook
Account (private) GetAssets, GetSettings, SetLeverage Get-Account · Get-Account-Setting · Change-Leverage
Trade (private) PlaceOrder, ModifyOrder, CancelOrder, GetOpenOrders, GetOrderHistory, GetPositions Place-Order · Modify-Order · Cancel-Order · Get-Order-Pending · Get-Order-History · Get-Position

For the exact HTTP methods, paths, and query/body parameters, see docs/endpoints.md.

A note about demo trading

If you set WithDemoTrading(), every REST request carries the paptrading: 1 header. Make sure you are using Demo API credentials — mixing demo mode with production credentials will fail. The trading example in examples/rest/main.go is gated behind both BITGET_DEMO=1 and BITGET_ENABLE_TRADING=1 so it cannot accidentally place a live order.


WebSocket

Real-time data is where Go really shines. The SDK gives you a streaming channel and handles reconnection behind the scenes.

Public channels
ws := bitget.NewPublicWSClient()

if err := ws.Connect(ctx); err != nil {
	log.Fatal(err)
}
defer ws.Close()

pushes, err := ws.Subscribe(ctx, models.WSArg{
	InstType: "SPOT",
	Topic:    "ticker",
	Symbol:   "BTCUSDT",
})
if err != nil {
	log.Fatal(err)
}

for push := range pushes {
	fmt.Println(string(push.Data))
}
Private channels

Use NewPrivateWSClient(apiKey, secretKey, passphrase). Authentication happens automatically during Connect.

ws := bitget.NewPrivateWSClient(
	os.Getenv("BITGET_API_KEY"),
	os.Getenv("BITGET_SECRET_KEY"),
	os.Getenv("BITGET_PASSPHRASE"),
)

On an unexpected disconnect, the client:

  1. Backs off exponentially from 1 second up to a 60-second cap.
  2. Reconnects.
  3. Resubscribes every channel you previously opened.

Implemented private channel: fast-fill. Other channels use the same Subscribe/WSPush.Data shape; check docs/endpoints.md to see which payloads are already typed and which you should decode from push.Data yourself.


Error handling

The SDK returns plain errors you can check with the standard library:

_, err := client.Account.GetAssets(ctx)
if err != nil {
	if errors.Is(err, bitget.ErrUnauthorized) {
		// Most likely the API key, secret, or passphrase is wrong.
		log.Println("authentication failed — check your credentials")
		return
	}

	var bitgetErr *bitget.Error
	if errors.As(err, &bitgetErr) {
		// Bitget returned a business-level error.
		log.Printf("Bitget error %s: %s", bitgetErr.Code, bitgetErr.Message)
		return
	}

	// Network or timeout issue.
	log.Printf("request failed: %v", err)
}

Common errors.Is checks include network timeouts and context cancellation, because the SDK propagates those transparently.


Running the tests

# Unit tests — fast, offline, backed by httptest
go test ./...

# Integration tests against Bitget demo environment.
# Requires BITGET_API_KEY, BITGET_SECRET_KEY, and BITGET_PASSPHRASE to be set.
go test -tags=integration ./...

We strongly recommend running integration tests with demo credentials before you point any code at a live account.


Examples

Two runnable examples are included:

Copy them, set your environment variables, and run:

BITGET_API_KEY=xxx BITGET_SECRET_KEY=xxx BITGET_PASSPHRASE=xxx go run examples/rest/main.go

A few practical tips

  1. Use strings for money. All numeric financial fields are string in the SDK. Use math/big.Rat or a decimal library of your choice; avoid strconv.ParseFloat when precision matters.
  2. Start on demo. Even experienced traders should validate new code against demo keys first. Markets move fast; a bug in order size or symbol formatting can be expensive.
  3. Respect rate limits. The SDK does not throttle for you. Bitget publishes rate-limit headers; if you need heavy polling, consider WebSockets instead of REST.
  4. Pass contexts with deadlines. This is especially important for trading endpoints where a slow request may no longer be relevant by the time it completes.
  5. Check errors by type. Use errors.Is for known sentinel errors and errors.As for *BitgetError to avoid fragile string matching.

Contributing

Contributions, bug reports, and suggestions are welcome. Please see CONTRIBUTING.md for the workflow, code style, and how to add new endpoints or channels.

A good first issue is often adding a missing endpoint model or improving test coverage.


Security

Found something that should not be public? Please email sovletig@gmail.com directly rather than opening a public issue. We will investigate and fix it as quickly as possible.

The SDK itself never logs API keys, secrets, or signatures, regardless of the logger you inject.


License

MIT. See LICENSE.


Author

Igor Sazonov — @tigusigalpasovletig@gmail.com


Not affiliated with Bitget. Trade carefully, test on demo first, and never commit API credentials to source control.

Documentation

Overview

Package bitget is an idiomatic Go SDK for the Bitget Unified Trading Account (UTA) API v3.

Docs: https://www.bitget.com/api-doc/uta/intro

Index

Constants

View Source
const (
	DefaultPublicWSURL  = "wss://ws.bitget.com/v3/ws/public"
	DefaultPrivateWSURL = "wss://ws.bitget.com/v3/ws/private"
	DemoPublicWSURL     = "wss://wspap.bitget.com/v3/ws/public"
	DemoPrivateWSURL    = "wss://wspap.bitget.com/v3/ws/private"
)

Public/private WebSocket endpoints.

Docs: https://www.bitget.com/api-doc/uta/guide

View Source
const DefaultBaseURL = "https://api.bitget.com"

DefaultBaseURL is Bitget's production UTA v3 REST endpoint.

Docs: https://www.bitget.com/api-doc/uta/guide

View Source
const DefaultTimeout = 15 * time.Second

DefaultTimeout is applied to the internal *http.Client when none is supplied via WithHTTPClient.

Variables

View Source
var (
	ErrUnauthorized      = errors.New("bitget: unauthorized: invalid API credentials")
	ErrInvalidSignature  = errors.New("bitget: invalid signature")
	ErrInvalidTimestamp  = errors.New("bitget: invalid or expired timestamp")
	ErrPermissionDenied  = errors.New("bitget: permission denied for this API key")
	ErrRateLimited       = errors.New("bitget: rate limit exceeded")
	ErrInvalidParameter  = errors.New("bitget: invalid request parameter")
	ErrInsufficientFunds = errors.New("bitget: insufficient balance")
	ErrOrderNotFound     = errors.New("bitget: order not found")
	ErrInternalServer    = errors.New("bitget: internal server error")
)

Sentinel errors that callers can match with errors.Is, wrapped alongside the detailed *Error (retrievable via errors.As) on every failed call.

Functions

func MapErrorCode

func MapErrorCode(code string) error

MapErrorCode maps a Bitget API response "code" to a sentinel error so callers can use errors.Is without parsing raw codes themselves. Unknown codes return nil (caller should fall back to the raw *Error).

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the low-level authenticated HTTP transport shared by every service under RestClient. Most callers should construct a *RestClient via NewRestClient instead of using Client directly.

func NewClient

func NewClient(apiKey, secretKey, passphrase string, opts ...Option) *Client

NewClient creates a low-level Client. apiKey/secretKey/passphrase are the credentials generated for an API key in the Bitget web console (https://www.bitget.com/api-doc/uta/guide). Most callers want NewRestClient instead, which additionally wires up all API services.

type Error added in v1.0.4

type Error struct {
	Code    string
	Message string
	Raw     []byte
}

Error represents a structured error returned by the Bitget UTA API, preserving the exact code/message pair sent back in the response envelope.

Docs: https://www.bitget.com/api-doc/uta/guide

func (*Error) Error added in v1.0.4

func (e *Error) Error() string

type Logger

type Logger interface {
	Debug(msg string, args ...any)
	Info(msg string, args ...any)
	Warn(msg string, args ...any)
	Error(msg string, args ...any)
}

Logger is a minimal structured-logging interface. Pass an adapter (see NewSlogLogger) or your own implementation via WithLogger; the default is a no-op logger.

func NewSlogLogger

func NewSlogLogger(l *slog.Logger) Logger

NewSlogLogger wraps l so it can be passed to WithLogger. A nil logger uses the same no-op behavior as a client without an explicitly configured logger.

type Option

type Option func(*Client)

Option configures a Client at construction time.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL overrides the REST base URL, e.g. for Bitget's Lo-La (VIP/institutional) endpoint or a test server.

func WithDemoTrading

func WithDemoTrading() Option

WithDemoTrading enables Bitget's simulated-trading mode by sending the "paptrading: 1" header on every request. Use together with a Demo API key; see https://www.bitget.com/api-doc/uta/guide.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient injects a custom *http.Client (for proxies, custom transports, or test doubles). The client is used as-is; DefaultTimeout is not applied when this option is used.

func WithLocale

func WithLocale(locale string) Option

WithLocale sets the "locale" header sent on every request (e.g. "en-US", "zh-CN"). Defaults to "en-US".

func WithLogger

func WithLogger(l Logger) Option

WithLogger sets a structured logger for request/response diagnostics. Never logs ACCESS-KEY, ACCESS-SIGN, or ACCESS-PASSPHRASE values.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the timeout of the internally constructed *http.Client. Ignored if WithHTTPClient is also used.

type RestClient

type RestClient struct {
	*Client

	// Market provides public, unauthenticated market-data endpoints.
	Market *market.Client
	// Account provides private account/balance/leverage endpoints.
	Account *account.Client
	// Trade provides private order-placement and position endpoints.
	Trade *trade.Client
}

RestClient is the main entry point for the REST API, grouping every service under one struct. Construct it with NewRestClient.

func NewRestClient

func NewRestClient(apiKey, secretKey, passphrase string, opts ...Option) *RestClient

NewRestClient creates a fully wired Bitget UTA v3 REST client. apiKey, secretKey, and passphrase come from the API key created in the Bitget web console; see https://www.bitget.com/api-doc/uta/guide.

Public endpoints (RestClient.Market) work even with empty credentials.

type WSClient

type WSClient struct {
	// contains filtered or unexported fields
}

WSClient is a reconnecting WebSocket client for Bitget's public or private UTA v3 streams. Create one with NewPublicWSClient or NewPrivateWSClient.

Docs: https://www.bitget.com/api-doc/uta/websocket/private/Fast-Fill-Channel

func NewPrivateWSClient

func NewPrivateWSClient(apiKey, secretKey, passphrase string, opts ...WSOption) *WSClient

NewPrivateWSClient creates a client for Bitget's private WebSocket streams (order fills, positions, etc.), authenticating automatically on Connect.

func NewPublicWSClient

func NewPublicWSClient(opts ...WSOption) *WSClient

NewPublicWSClient creates a client for Bitget's public market-data WebSocket streams (no authentication).

func (*WSClient) Close

func (c *WSClient) Close() error

Close terminates the connection and stops all background loops. Safe to call multiple times.

func (*WSClient) Connect

func (c *WSClient) Connect(ctx context.Context) error

Connect dials the WebSocket endpoint, logs in (for private clients), and starts the background read/ping/reconnect loops. Connect blocks until the initial connection (and, for private clients, login) succeeds or ctx is done.

func (*WSClient) Subscribe

func (c *WSClient) Subscribe(ctx context.Context, arg models.WSArg) (<-chan models.WSPush, error)

Subscribe subscribes to a channel and returns a buffered channel of data pushes. The subscription is automatically restored after a reconnect.

func (*WSClient) Unsubscribe

func (c *WSClient) Unsubscribe(arg models.WSArg) error

Unsubscribe removes a channel subscription and closes its data channel.

type WSOption

type WSOption func(*WSClient)

WSOption configures a WSClient at construction time.

func WithWSAutoReconnect

func WithWSAutoReconnect(enabled bool) WSOption

WithWSAutoReconnect toggles automatic reconnection with exponential backoff on unexpected disconnects. Enabled by default.

func WithWSLogger

func WithWSLogger(l Logger) WSOption

WithWSLogger sets a structured logger for connection lifecycle events.

func WithWSURL

func WithWSURL(url string) WSOption

WithWSURL overrides the WebSocket endpoint, e.g. for Bitget's demo/paper trading WS or the Lo-La VIP endpoint.

Directories

Path Synopsis
examples
rest command
Command rest_example demonstrates public market data plus an optional, explicitly gated authenticated call.
Command rest_example demonstrates public market data plus an optional, explicitly gated authenticated call.
websocket command
Command websocket_example demonstrates connecting to Bitget's public WebSocket, subscribing to a channel, and handling reconnects.
Command websocket_example demonstrates connecting to Bitget's public WebSocket, subscribing to a channel, and handling reconnects.
Package models contains typed request/response structures for the Bitget UTA v3 API.
Package models contains typed request/response structures for the Bitget UTA v3 API.
rest
account
Package account implements Bitget UTA v3's private account endpoints.
Package account implements Bitget UTA v3's private account endpoints.
market
Package market implements Bitget UTA v3's public market-data endpoints.
Package market implements Bitget UTA v3's public market-data endpoints.
trade
Package trade implements Bitget UTA v3's private order and position endpoints.
Package trade implements Bitget UTA v3's private order and position endpoints.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL