# 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
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.k9.io/key9-identity/jsonair/3-using-the-api/3.3-golang-examples.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
