GoGo SDK
Plain structs, contexts and errors.Is.
Module github.com/datasportsapi/datasportsapi-go, package datasportsapi. Every call takes a context, every response is a typed struct, and errors match with errors.Is and errors.As like the rest of your code.
- Package
- github.com/datasportsapi/datasportsapi-go
- Runs on
- Go 1.23+ · context everywhere
- Key
- DATASPORTSAPI_API_KEY
- Status
- Not published yet
- Install
- $ go get github.com/datasportsapi/datasportsapi-go
The install line goes live with the first release; nothing is on a public registry yet. Everything on this page describes the client as it will ship.
Install
Add the module to your go.mod. The import path ends in -go; the package inside is plain datasportsapi.
shell$ go get github.com/datasportsapi/datasportsapi-goAuthenticate
NewClient reads DATASPORTSAPI_API_KEY when no key option is given. WithAPIKey takes precedence when you load the key yourself.
client.goimport datasportsapi "github.com/datasportsapi/datasportsapi-go" client := datasportsapi.NewClient() // reads DATASPORTSAPI_API_KEY // or explicitly client = datasportsapi.NewClient(datasportsapi.WithAPIKey(key))First calls
Path parameters are arguments after the context; query parameters ride in a typed Params struct, with Ptr for the optional ones. Each method returns the envelope as a struct.
first_calls.golive, err := client.Livescores.List(ctx, &datasportsapi.LivescoresListParams{ Sport: datasportsapi.Ptr("football"), }) if err != nil { log.Fatal(err) } for _, f := range live.Data { fmt.Println(f.Home.Name, *f.HomeScore.Current, "-", *f.AwayScore.Current, f.Away.Name) } table, err := client.Leagues.Standings(ctx, 17, &datasportsapi.LeaguesStandingsParams{Season: 76986})Errors
One sentinel per HTTP status for errors.Is, and an *APIError with Status, Code, Message and RetryAfter for errors.As. Switch on Code when one status covers several cases.
errors.go_, err := client.Fixtures.WinProbability(ctx, 480112, nil) var apiErr *datasportsapi.APIError switch { case errors.Is(err, datasportsapi.ErrForbidden): // 403: endpoint_not_in_plan, history_not_in_plan, … showUpgradeHint() case errors.Is(err, datasportsapi.ErrNotFound): // 404: not_found, no_data, not_supported hidePanel() case errors.As(err, &apiErr): log.Printf("%d %s (retry in %ds)", apiErr.Status, apiErr.Code, apiErr.RetryAfter) }Go error type for each HTTP status, and the codes each status can carry Status Sentinel (errors.Is) error.code 400 ErrBadRequest bad_request401 ErrUnauthorized unauthorized403 ErrForbidden endpoint_not_in_planhistory_not_in_planws_not_availableorigin_not_allowedip_not_allowed404 ErrNotFound not_foundno_datanot_supported429 ErrTooManyRequests rate_limitedquota_exceeded500 ErrInternal internal_error503 ErrUnavailable upstream_unavailablePaging
Paged endpoints get a …Pages method that returns a range-over-func iterator: each step yields a page and an error, and the loop ends after the last page.
paging.goparams := &datasportsapi.TeamsFixturesParams{Type: datasportsapi.Ptr("recent")} for page, err := range client.Teams.FixturesPages(ctx, 42, params) { if err != nil { log.Fatal(err) } archive(page.Data) }WebSocket stream
Businessclient.Stream gets a single-use ticket on its own, subscribes, reconnects and replays missed frames, folding each delta into the fixtures it tracks. Frames arrive on a channel; cancel the context or call Close to stop.
stream.gos, err := client.Stream(ctx, []string{"livescores", "fixture:480112"}, nil) if err != nil { log.Fatal(err) } defer s.Close() for frame := range s.Frames() { if d, ok := frame.Value.(*datasportsapi.WsDelta); ok { fmt.Println("delta", d.ID) } inPlay, _ := s.Fixtures("livescores") // merged state, any time _ = inPlay }Channels, frames and replay rules are in the WebSocket guide. Without a Business key the stream answers 403 ws_not_available.
Options
Functional options, all optional. 429 rate_limited and 503 are retried after Retry-After, twice by default; 429 quota_exceeded comes straight back as an error.
options.goclient := datasportsapi.NewClient( datasportsapi.WithAPIKey(key), // default: DATASPORTSAPI_API_KEY datasportsapi.WithBaseURL("https://api.datasportsapi.com"), // default: DATASPORTSAPI_BASE_URL datasportsapi.WithTimeout(30*time.Second), // per attempt datasportsapi.WithMaxRetries(2), // rate_limited and 503 only )Base URL resolution: the option or flag first, then
DATASPORTSAPI_BASE_URL, thenhttps://api.datasportsapi.com.
From the endpoint pages
Every endpoint shows its Go call.
- GET
/v2/livescoresres, err := client.Livescores.List(ctx, &datasportsapi.LivescoresListParams{}) - GET
/v2/fixtures/{id}res, err := client.Fixtures.Get(ctx, id) - GET
/v2/fixtures/{id}/lineupsres, err := client.Fixtures.Lineups(ctx, id) - GET
/v2/leagues/{id}/standingsres, err := client.Leagues.Standings(ctx, id, &datasportsapi.LeaguesStandingsParams{Season: season}) - GET
/v2/teams/{id}/fixturesres, err := client.Teams.Fixtures(ctx, id, &datasportsapi.TeamsFixturesParams{})
Other clients
Your key is one form away.
1,000 free requests a day during the beta. No card, no sales call.