Skip to content

SiftingIO/sdk-go

Repository files navigation

siftingio (Go)

Official Go SDK for the SiftingIO market data API — REST plus a live WebSocket client, idiomatic and context-aware.

  • context.Context everywhere, functional options, typed structs.
  • Resource-mapped. Method names mirror the API docs 1:1.
  • Batteries included. Auto-retry on 429/5xx, transparent gzip, cursor auto-pagination via Go 1.23 iterators, and an auto-reconnecting WebSocket client.
  • One dependencygithub.com/coder/websocket (REST uses only the standard library).

Install

go get github.com/siftingio/sdk-go@latest

Requires Go 1.23+ (for range-over-func pagination).

Quick start

package main

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

	siftingio "github.com/siftingio/sdk-go"
)

func main() {
	client := siftingio.New(siftingio.WithAPIKey(os.Getenv("SIFTING_API_KEY")))
	ctx := context.Background()

	trade, err := client.Last.Trade(ctx, "crypto", "BTCUSD")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(trade.Price, trade.Time)

	profile, _ := client.Stocks.Profile(ctx, "AAPL")
	fmt.Println(profile.Name, profile.SICDescription)

	bars, _ := client.Crypto.Bars(ctx, "BTCUSD", &siftingio.BarsParams{Start: "2024-01-01", Interval: "1h"})
	fmt.Printf("%d bars\n", len(bars.Data))
}

The import path is github.com/siftingio/sdk-go; the package name is siftingio. Add an explicit alias (siftingio "github.com/siftingio/sdk-go") if your tooling wants it.

Configuration

client := siftingio.New(
	siftingio.WithAPIKey("sft_..."),                 // X-API-Key header
	siftingio.WithAPIKeyProvider(func(ctx context.Context) (string, error) { // dynamic alternative
		return fetchToken(ctx)
	}),
	siftingio.WithBaseURL("https://api.sifting.io"), // override for proxies/staging
	siftingio.WithWSURL("wss://stream.sifting.io/ws/v1"),
	siftingio.WithHTTPClient(myHTTPClient),           // custom *http.Client
	siftingio.WithTimeout(30*time.Second),            // per-request timeout (via context)
	siftingio.WithMaxRetries(2),                      // retries for 429 / 5xx
	siftingio.WithHeader("X-Trace", "..."),           // header on every request
)

Resources

Field Endpoints Highlights
client.Last /v1/last/* Trade, Quote, TVL — live snapshots
client.Stocks /v1/fnd/stocks/*, /v1/hist/stocks/* Search, Profile, Filings, Financials, Ratios, Insiders, Events, Screener, Bars, …
client.Filers /v1/fnd/filers/* Holdings — 13F positions
client.Markets /v1/fnd/markets/* List, Status, Hours, Calendar
client.Forex /v1/hist/forex/* Bars
client.Crypto /v1/hist/crypto/* Bars
client.Dex /v1/fnd/dex/* Wallet portfolios
client.EconomicCalendar /v1/fnd/economic-calendar List

Pagination

List endpoints return a *ListResponse[T] with Meta.NextCursor. Stream every page with the AutoPaginate iterator (Go 1.23+):

for filing, err := range siftingio.AutoPaginate(ctx,
	func(ctx context.Context, cursor string) ([]siftingio.Filing, string, error) {
		page, err := client.Stocks.Filings(ctx, "AAPL", &siftingio.FilingsParams{Cursor: cursor, Form: "10-K"})
		if err != nil {
			return nil, "", err
		}
		return page.Data, page.Meta.NextCursor, nil
	},
) {
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(filing.Accession, filing.FiledAt)
}

siftingio.CollectAll(...) gathers all pages into a slice.

Live WebSocket

sock := client.WS() // siftingio.WithAutoReconnect(false) to disable

sock.OnTick(func(t *siftingio.Tick) { fmt.Println(t.Symbol, t.Price) })
sock.OnTVL(func(v *siftingio.TVLUpdate) { fmt.Println(v.Symbol, v.USD) })
sock.OnError(func(e *siftingio.WSError) { log.Println("server error:", e.Code, e.Message) })
sock.OnReconnect(func(attempt int) { log.Println("reconnecting", attempt) })

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

sock.Subscribe(ctx, siftingio.ProductCEX, "BTCUSD", "ETHUSD") // cex|dex|fx|us|tvl
sock.Subscribe(ctx, siftingio.ProductTVL, "eth:WETH-USDC")

<-ctx.Done()

Subscriptions are tracked and replayed automatically on reconnect. Handlers run on the read goroutine — keep them quick or hand work to your own channels/goroutines.

Error handling

trade, err := client.Last.Trade(ctx, "crypto", "BTCUSD")
if err != nil {
	var apiErr *siftingio.APIError
	if errors.As(err, &apiErr) {
		// apiErr.Status, apiErr.Code, apiErr.RetryAfter, apiErr.RequestID, apiErr.Body
	}
	var connErr *siftingio.ConnectionError
	if errors.As(err, &connErr) {
		// connErr.Timeout, connErr.Err
	}
}

The client automatically retries 429 and 5xx up to WithMaxRetries, honoring Retry-After.

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages