SDKs Go

FlashAlpha Go SDK

Official Go 1.21+ SDK. Stdlib-only, context-aware, with endpoint-specific functional options that keep the API strongly typed at compile time.

Install
go get github.com/FlashAlpha-lab/flashalpha-go@latest
Version
0.3.0 · Go 1.21+
GitHub pkg.go.dev Stdlib-only 30s timeout

What the SDK gives you

Full endpoint coverage

All REST endpoints — market data, exposure, volatility, pricing, screener, account — exposed as methods on *Client.

Stdlib-only

No external dependencies. Just net/http and encoding/json. Your go.sum stays clean.

context.Context first

Every method takes a context.Context — deadlines and cancellations propagate to the HTTP request.

Endpoint-specific options

Functional options are typed per endpoint: WithExpiration for Gex, WithDexExpiration for Dex, etc. No invalid combos at compile time.

Typed errors

Use errors.As to pattern-match on *TierRestrictedError, *RateLimitError, *AuthenticationError, etc.

Strongly typed screener

Use ScreenerRequest for type safety, or ScreenerRaw with any interface{} for maximum flexibility.

Install

go get github.com/FlashAlpha-lab/flashalpha-go@latest

Quick start

package main

import (
    "context"
    "fmt"
    "log"

    flashalpha "github.com/FlashAlpha-lab/flashalpha-go"
)

func main() {
    client := flashalpha.NewClient("YOUR_API_KEY")
    ctx := context.Background()

    // All methods return map[string]interface{}
    gex, err := client.Gex(ctx, "SPY")
    if err != nil { log.Fatal(err) }
    fmt.Println(gex["net_gex"], gex["gamma_flip"])

    // Key support / resistance levels
    lv, err := client.ExposureLevels(ctx, "SPY")
    if err != nil { log.Fatal(err) }
    key := lv["levels"].(map[string]interface{})
    fmt.Println(key["call_wall"], key["put_wall"])

    // BSM greeks (complex params use a struct, not functional options)
    g, err := client.Greeks(ctx, flashalpha.GreeksParams{
        Spot: 655, Strike: 660, Dte: 7, Sigma: 0.18, Type: "call",
    })
    if err != nil { log.Fatal(err) }
    fmt.Println(g["delta"], g["gamma"], g["theta"])
}
Response shape: every method returns (map[string]interface{}, error). For strong typing, json.Marshal then Unmarshal into your own struct — see the recipes below.

Live options screener

limit := 10
screen, err := client.Screener(ctx, flashalpha.ScreenerRequest{
    Filters: flashalpha.ScreenerGroup{
        Op: "and",
        Conditions: []interface{}{
            flashalpha.ScreenerLeaf{Field: "regime",        Operator: "eq",  Value: "positive_gamma"},
            flashalpha.ScreenerLeaf{Field: "harvest_score", Operator: "gte", Value: 65},
        },
    },
    Sort:   []flashalpha.ScreenerSort{{Field: "harvest_score", Direction: "desc"}},
    Select: []string{"symbol", "price", "harvest_score"},
    Limit:  &limit,
})
if err != nil { log.Fatal(err) }

rows := screen["data"].([]interface{})
for _, r := range rows {
    row := r.(map[string]interface{})
    fmt.Println(row["symbol"], row["harvest_score"])
}

Endpoint-specific functional options

Each option constructor is tied to a single endpoint at compile time. You can't pass a Dex option to Gex by mistake.

EndpointOption constructors
GexWithExpiration, WithMinOI
DexWithDexExpiration
VexWithVexExpiration
ChexWithChexExpiration
ZeroDteWithStrikeRange
ExposureHistoryWithDays
OptionQuoteWithOptionExpiry, WithStrike, WithOptionType
HistoricalOptionQuoteWithHistTime, WithHistExpiry, WithHistStrike, WithHistType

Common recipes

Decode into your own struct

import "encoding/json"

type GexSummary struct {
    NetGex    float64 `json:"net_gex"`
    GammaFlip float64 `json:"gamma_flip"`
}

raw, err := client.Gex(ctx, "SPY")
if err != nil { log.Fatal(err) }

b, _ := json.Marshal(raw)
var s GexSummary
json.Unmarshal(b, &s)
fmt.Println(s.NetGex, s.GammaFlip)

Request with deadline

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

gex, err := client.Gex(ctx, "SPY", flashalpha.WithExpiration("2026-04-10"))
if err != nil { log.Fatal(err) }
_ = gex

Raw screener payload

// ScreenerRaw accepts any value that round-trips through encoding/json
out, err := client.ScreenerRaw(ctx, map[string]interface{}{
    "filters": map[string]interface{}{
        "field":    "atm_iv",
        "operator": "gte",
        "value":    25,
    },
    "sort":   []map[string]string{{"field": "atm_iv", "direction": "desc"}},
    "select": []string{"symbol", "atm_iv"},
    "limit":  20,
})
_ = out

Method catalog

CategoryMethodsTier
Market dataStockQuote, OptionQuote, StockSummary, SurfaceFree / Growth
Historical replay (point-in-time)HistoricalStockQuote, HistoricalOptionQuote, plus the full live API mirrored on historical.flashalpha.com via flashalpha.NewClient(apiKey, flashalpha.WithBaseURL("https://historical.flashalpha.com")) with at paramAlpha
Exposure (basic)Gex, ExposureLevelsFree+ (equities); Basic+ for ETFs & indexes
Exposure (Greeks)Dex, Vex, Chex, MaxPainBasic+
Exposure (Growth)ExposureSummary, Narrative, ZeroDte, ExposureHistoryGrowth+
PricingGreeks, IV, KellyFree / Growth
VolatilityVolatility, AdvVolatilityGrowth / Alpha
ScreenerScreener, ScreenerRawGrowth+
ReferenceTickers, Options, SymbolsFree+
AccountAccount, HealthFree+

Error handling

import "errors"

_, err := client.Narrative(ctx, "SPY")
if err != nil {
    var tierErr  *flashalpha.TierRestrictedError
    var rateErr  *flashalpha.RateLimitError
    var notFound *flashalpha.NotFoundError
    switch {
    case errors.As(err, &tierErr):
        fmt.Printf("Upgrade from %s to %s\n",
            tierErr.CurrentPlan, tierErr.RequiredPlan)
    case errors.As(err, &rateErr):
        fmt.Printf("Retry after %ds\n", rateErr.RetryAfter)
    case errors.As(err, &notFound):
        fmt.Println("Symbol not found")
    default:
        fmt.Printf("API error: %v\n", err)
    }
}
HTTPError typeFields
401*AuthenticationError
403*TierRestrictedErrorCurrentPlan, RequiredPlan
404*NotFoundError
429*RateLimitErrorRetryAfter
5xx*ServerErrorStatusCode
other*APIErrorStatusCode

Client configuration

// Default base URL
client := flashalpha.NewClient("YOUR_API_KEY")

// Custom base URL (useful for tests)
client := flashalpha.NewClientWithURL(
    "YOUR_API_KEY",
    "https://lab.flashalpha.com",
)
// Timeout is fixed at 30 seconds.

Links

Ready to build?

Get your free API key and start pulling live options data in 30 seconds.