> For the complete documentation index, see [llms.txt](https://docs.k9.io/key9-identity/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.k9.io/key9-identity/jsonair/3-using-the-api/3.3-golang-examples.md).

# 3.3 Golang Examples

The following examples use only the Go standard library. No third-party HTTP client is required.

***

## Authentication — Get a Bearer Token

```go
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

type tokenResponse struct {
    AccessToken string `json:"access_token"`
    ExpiresIn   int    `json:"expires_in"`
}

func getToken(baseURL, pat string) (string, error) {
    body, err := json.Marshal(map[string]string{"token": pat})
    if err != nil {
        return "", err
    }

    resp, err := http.Post(
        baseURL+"/api/v1/jsonair/auth/token",
        "application/json",
        bytes.NewReader(body),
    )
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return "", fmt.Errorf("auth failed: HTTP %d", resp.StatusCode)
    }

    var tr tokenResponse
    if err := json.NewDecoder(resp.Body).Decode(&tr); err != nil {
        return "", err
    }

    return tr.AccessToken, nil
}
```

***

## Fetch Configuration Data

```go
func getConfig(baseURL, token, configType, configName string) (string, error) {
    body, err := json.Marshal(map[string]interface{}{
        "type":   configType,
        "name":   configName,
        "decode": false,
    })
    if err != nil {
        return "", err
    }

    req, err := http.NewRequest(http.MethodGet,
        baseURL+"/api/v1/jsonair/config",
        bytes.NewReader(body),
    )
    if err != nil {
        return "", err
    }
    req.Header.Set("Authorization", "Bearer "+token)
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    if resp.StatusCode == http.StatusUnauthorized {
        return "", fmt.Errorf("token expired")
    }
    if resp.StatusCode != http.StatusOK {
        return "", fmt.Errorf("request failed: HTTP %d", resp.StatusCode)
    }

    var buf bytes.Buffer
    if _, err := buf.ReadFrom(resp.Body); err != nil {
        return "", err
    }

    return buf.String(), nil
}
```

***

## Putting It Together — Poll with Re-Authentication

This pattern mirrors what the JSONAir agent does: authenticate once, poll on an interval, and re-authenticate automatically when the JWT expires.

```go
package main

import (
    "encoding/base64"
    "fmt"
    "log"
    "time"
)

func main() {
    const (
        baseURL    = "https://jsonair.example.com"
        pat        = "your-plain-text-pat"
        configType = "myapp"
        configName = "prod.yaml"
        interval   = 30 * time.Second
    )

    token, err := getToken(baseURL, pat)
    if err != nil {
        log.Fatalf("initial auth failed: %v", err)
    }

    for {
        data, err := getConfig(baseURL, token, configType, configName)

        if err != nil && err.Error() == "token expired" {
            log.Println("JWT expired, re-authenticating...")
            token, err = getToken(baseURL, pat)
            if err != nil {
                log.Fatalf("re-auth failed: %v", err)
            }
            data, err = getConfig(baseURL, token, configType, configName)
        }

        if err != nil {
            log.Printf("error fetching config: %v", err)
        } else {
            decoded, err := base64.StdEncoding.DecodeString(data)
            if err != nil {
                log.Printf("base64 decode error: %v", err)
            } else {
                fmt.Printf("config: %s\n", decoded)
            }
        }

        time.Sleep(interval)
    }
}
```

***

## Fetch the Reload Key

```go
func getReload(baseURL, token, configType, configName string) (string, error) {
    body, _ := json.Marshal(map[string]string{
        "type": configType,
        "name": configName,
    })

    req, _ := http.NewRequest(http.MethodGet,
        baseURL+"/api/v1/jsonair/reload",
        bytes.NewReader(body),
    )
    req.Header.Set("Authorization", "Bearer "+token)
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    var result struct {
        Reload string `json:"reload"`
    }
    json.NewDecoder(resp.Body).Decode(&result)
    return result.Reload, nil
}
```
