> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xinsider.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Go client

> go get github.com/0xinsider/0xinsider-go: a typed WithResponse method per API operation, a sandbox base URL that needs no key, and a deadline on every request.

`github.com/0xinsider/0xinsider-go` is the official Go client, generated from the [OpenAPI document](https://0xinsider.com/api/v1/openapi.json). Every operation has a typed `...WithResponse` method. Source at [`0xinsider/0xinsider-go`](https://github.com/0xinsider/0xinsider-go).

```bash theme={null}
go get github.com/0xinsider/0xinsider-go@v0.3.0
```

Go 1.26.5 or newer, one dependency (`github.com/oapi-codegen/runtime`). This page is written against v0.3.0, which implements all 67 operations.

## Run it without a key

```go theme={null}
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	oxinsider "github.com/0xinsider/0xinsider-go"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	client, err := oxinsider.New(oxinsider.WithBaseURL("https://0xinsider.com/sandbox"))
	if err != nil {
		log.Fatal(err)
	}

	limit := 5
	resp, err := client.ListLeaderboardWithResponse(ctx, &oxinsider.ListLeaderboardParams{Limit: &limit})
	if err != nil {
		log.Fatal(err)
	}
	if resp.JSON200 == nil {
		log.Fatalf("HTTP %d: %s", resp.StatusCode(), resp.Body)
	}

	for _, entry := range resp.JSON200.Data {
		grade := "ungraded"
		if entry.Grade != nil {
			grade = *entry.Grade
		}
		fmt.Println(entry.Address, grade)
	}
}
```

No credential, no account. `WithBaseURL("https://0xinsider.com/sandbox")` sends every operation to the sandbox, which answers with its documented example. [Start without a key](/sandbox) has the rules, including `sandbox_status` for error branches.

## Then live data

```go theme={null}
client, err := oxinsider.New(oxinsider.WithBearerToken(os.Getenv("OXINSIDER_API_KEY")))
```

That one line is the whole change. `WithBearerToken` takes an API key (`oxi_sk_live_...`) or an OAuth 2.1 access token (`oxi_at_...`), and the base URL defaults to `oxinsider.DefaultServer`, `https://api.0xinsider.com`.

The client reads no environment variable on its own, so name it `OXINSIDER_API_KEY` to match the [Python client](/integrations/python-client), the [CLI](/integrations/cli), and the [MCP server](/integrations/mcp). A live key needs an account with an active Pro subscription. See [Authentication](/authentication).

A client built without `WithBearerToken` still reads the 6 [public routes](/authentication#what-needs-a-key).

## Keep financial values exact

The trader and positions responses keep their display-safe numeric fields and add exact decimal atoms when their source values are verified. Parse the atom's `value` into `math/big.Rat` or another decimal-safe type; do not convert it through `float64`.

```go theme={null}
import (
	"fmt"
	"math/big"
)

func exactRat(value string) (*big.Rat, error) {
	rat, ok := new(big.Rat).SetString(value)
	if !ok {
		return nil, fmt.Errorf("invalid exact decimal %q", value)
	}
	return rat, nil
}

// After a successful typed get-trader or list-positions call:
// rat, err := exactRat(atom.Value)
// total := new(big.Rat).Add(rat, new(big.Rat).SetInt64(1))
// fmt.Println(total.FloatString(6))
```

Each atom also carries `Unit`, `Scale`, and `Basis`. The exact block or an optional member can be absent when its source is unavailable; an absent value is not zero.

## Deadlines

A client from `oxinsider.New` bounds every ordinary request: `DefaultRequestTimeout` (30 seconds) end to end, `DefaultDownloadTimeout` (5 minutes) for the export download, over a transport that also bounds the dial, the TLS handshake, and the wait for response headers. A call you gave no deadline is still bounded.

```go theme={null}
client, err := oxinsider.New(
	oxinsider.WithBearerToken(os.Getenv("OXINSIDER_API_KEY")),
	oxinsider.WithRequestTimeout(5*time.Second),
)
```

A deadline the client applied comes back as `*oxinsider.RequestTimeoutError`, which carries `Deadline`, `Method`, and `URL`, unwraps to `context.DeadlineExceeded`, and reports `Timeout() bool`. You can tell it from a deadline of your own.

A context deadline you pass always wins, so keep passing one for the call that deserves a tighter bound than 30 seconds. `WithRequestTimeout(0)` removes the total bound and leaves the connection-level ones in place.

`GET /api/v1/stream` is excluded, and is bounded by `OpenStream`'s start and idle timeouts instead: a healthy stream that has nothing to say is never cut after 30 seconds, while one that stops producing frames still fails in finite time.

<Note>
  v0.2.0 and earlier added no timeout of their own, and `net/http` has none by default: a call with `context.Background()` against a stalled connection waited forever. Upgrading to v0.3.0 is how you get the bound.
</Note>

## Reading a response

`JSON200`, `JSON201`, and the other status fields hold the decoded body for that status and are `nil` for any other. `Body` keeps the raw bytes and `StatusCode()` the status, so a branch on `JSON200 == nil` is how you notice an error.

```go theme={null}
if resp.JSON200 == nil {
	log.Fatalf("HTTP %d: %s", resp.StatusCode(), resp.Body)
}
```

Optional fields are pointers, because the API omits a field it has no value for. A `nil` `Grade` means the wallet has no grade, not an F. Never dereference without the check.

## Credential safety

| Rule                          | Behavior                                                                                                                             |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Transport                     | The token goes over `https://` only, or `http://` to a loopback host for a backend you run.                                          |
| A base URL that would leak it | Every credentialed request fails with `*InsecureTransportError` before it is sent. The error names the destination, never the token. |
| A downgrading redirect        | Refused the same way, with `Redirect` set.                                                                                           |

## Which document a release implements

```go theme={null}
oxinsider.Version        // "0.3.0"
oxinsider.OperationCount // 67
oxinsider.OpenAPISHA256  // the document bytes it was generated from
oxinsider.AppCommit      // the app commit that last changed that document
```

Compare `OpenAPISHA256` with `shasum -a 256` of `https://0xinsider.com/api/v1/openapi.json` to see whether your release is behind the API.

## What this client does not do

* Place an order or hold a Polymarket key. Every operation is a read except your own webhook and export calls.
* Read a key from the environment. You pass it to `WithBearerToken`.
* Retry a failed request. A `429` or a `503` comes straight back to you.
* Round anything. Money and price fields keep the API's precision.
* Treat a `nil` pointer as `0`. Missing means the provider did not report that value.

## Go next

<CardGroup cols={2}>
  <Card title="Start without a key" icon="play" href="/sandbox">
    Everything that works without a key.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/quickstart">
    The same 5 reads in `curl`, Python, and Go.
  </Card>

  <Card title="Authentication" icon="key" href="/authentication">
    Where a key belongs, and OAuth for an app with users.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/errors">
    Every code a non-2xx body carries.
  </Card>
</CardGroup>
