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

# Go SDK

> Official Go SDK for the Grantex delegated authorization protocol

## Installation

Current published release: **`v0.1.10`** (verified July 12, 2026).

```bash theme={null}
go get github.com/mishrasanjeev/grantex-go@v0.1.10
```

The unpinned `go get github.com/mishrasanjeev/grantex-go` command follows Go's
module-version resolution. Keep the exact version above in reproducible builds.
See [Release Status](/release-status) before upgrading.

## Requirements

* **Go 1.26.1+**, matching this module's `go.mod` directive

## Configuration

```go theme={null}
import grantex "github.com/mishrasanjeev/grantex-go"

// Default configuration (reads GRANTEX_API_KEY is not used here — pass key directly)
client := grantex.NewClient("your-api-key")

// With options
client := grantex.NewClient("your-api-key",
    grantex.WithBaseURL("https://your-instance.example.com"),
    grantex.WithTimeout(60 * time.Second),
    grantex.WithHTTPClient(customHTTPClient),
)
```

| Option              | Default                   | Description           |
| ------------------- | ------------------------- | --------------------- |
| `WithBaseURL(url)`  | `https://api.grantex.dev` | API base URL          |
| `WithTimeout(d)`    | `30s`                     | HTTP request timeout  |
| `WithHTTPClient(c)` | `http.DefaultClient`      | Custom `*http.Client` |

## Known v0.1.10 limitations

* Registration returns `agentId`, while `Agent.ID` expects `id`; derive the ID from the returned DID.
* Registration sends optional zero values; updates cannot set `status` or send an explicit empty `scopes` array. Provide registration fields explicitly and use REST for those updates.
* The typed audit payload omits required fields; use the [REST or CLI audit-write workaround](/sdks/go/audit#log).
* `AuditEntry` omits `DeveloperID`, and the SDK advertises `Since`, `Until`, `Page`, and `PageSize` audit filters that the API ignores.
* Agent and audit list structs expose `Total`, `Page`, and `PageSize`, but the API returns only `agents` or `entries`; use the slice length for this release.
* List helpers do not URL-encode reserved characters in filter values; avoid them or issue a REST request with a `net/url`-encoded query.

<Info>
  Repository source on `main` corrects all documented `v0.1.10` Agent/Audit contract gaps, removes unsupported audit filters, and URL-encodes query values, with API-shaped regression coverage.
  No corrected module tag has been published. The pinned `v0.1.10` install and workarounds remain the supported public-release guidance.
</Info>

## Quick Start

<Warning>
  In `v0.1.10`, the API's `agentId` response does not populate `Agent.ID`
  because that SDK field expects `id`. This example derives the ID from the
  returned `did:grantex:<agentId>` value. Remove the workaround only after
  upgrading to a release that corrects the response mapping.
</Warning>

```go theme={null}
package main

import (
    "context"
    "fmt"
    "log"
    "strings"

    grantex "github.com/mishrasanjeev/grantex-go"
)

func main() {
    ctx := context.Background()
    client := grantex.NewClient("your-api-key")

    // 1. Register an agent
    agent, err := client.Agents.Register(ctx, grantex.RegisterAgentParams{
        Name:        "Email Assistant",
        Description: "Reads and sends emails on behalf of users",
        Scopes:      []string{"read:email", "send:email"},
    })
    if err != nil {
        log.Fatal(err)
    }
    const didPrefix = "did:grantex:"
    if !strings.HasPrefix(agent.DID, didPrefix) {
        log.Fatal("unexpected agent DID")
    }
    agentID := strings.TrimPrefix(agent.DID, didPrefix)
    fmt.Printf("Agent registered: %s (DID: %s)\n", agentID, agent.DID)

    // 2. Create authorization request
    authReq, err := client.Authorize(ctx, grantex.AuthorizeParams{
        AgentID:     agentID,
        PrincipalID: "user-123",
        Scopes:      []string{"read:email", "send:email"},
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Consent URL: %s\n", authReq.ConsentURL)

    // 3. Exchange authorization code for token (after user consents)
    tokenResp, err := client.Tokens.Exchange(ctx, grantex.ExchangeTokenParams{
        Code:    "authorization-code-from-callback",
        AgentID: agentID,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Grant token: %s\n", tokenResp.GrantToken)

    // 4. Verify the token
    verified, err := client.Tokens.Verify(ctx, tokenResp.GrantToken)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Token valid: %v, scopes: %v\n", verified.Valid, verified.Scopes)
}
```

## Available Resources

| Service                    | Description                                                               |
| -------------------------- | ------------------------------------------------------------------------- |
| `client.Agents`            | Register, list, update, delete agents                                     |
| `client.Tokens`            | Exchange, refresh, verify, revoke tokens                                  |
| `client.Grants`            | List, revoke, delegate grants                                             |
| `client.Audit`             | Log and query audit entries                                               |
| `client.Webhooks`          | Manage webhook endpoints                                                  |
| `client.Billing`           | Subscription and checkout management                                      |
| `client.Policies`          | Access policy CRUD                                                        |
| `client.Compliance`        | Compliance reports and evidence packs                                     |
| `client.Anomalies`         | Anomaly detection and management                                          |
| `client.SCIM`              | SCIM 2.0 user provisioning                                                |
| `client.SSO`               | SSO configuration                                                         |
| `client.PrincipalSessions` | End-user dashboard sessions                                               |
| `client.Passports`         | Issue, list, get, and revoke MPP agent passports                          |
| `client.Vault`             | Store, list, get, delete, and exchange service credentials                |
| `client.Budgets`           | Per-grant spending budgets and transactions                               |
| `client.Events`            | SSE event streaming                                                       |
| `client.Usage`             | Usage metering and history                                                |
| `client.Domains`           | Custom domain verification                                                |
| `client.WebAuthn`          | FIDO2/WebAuthn passkey management                                         |
| `client.Credentials`       | Verifiable Credentials and SD-JWT                                         |
| `client.Commerce`          | Commerce V1/OACP merchant discovery, catalog, checkout, webhooks, and ops |
| `client.DPDP`              | DPDP Act 2023 compliance — consent, grievances, erasure, exports          |

## Standalone Functions

| Function                           | Description                                                  |
| ---------------------------------- | ------------------------------------------------------------ |
| `grantex.VerifyGrantToken()`       | Local JWT verification with a JWKS fetch per standalone call |
| `grantex.GeneratePKCE()`           | Generate PKCE S256 challenge pair                            |
| `grantex.VerifyWebhookSignature()` | Verify HMAC-SHA256 webhook signatures                        |
| `grantex.Signup()`                 | Register a new developer (no API key needed)                 |

## Error Handling

```go theme={null}
agent, err := client.Agents.Get(ctx, "agent-id")
if err != nil {
    switch e := err.(type) {
    case *grantex.AuthError:
        fmt.Printf("Authentication failed: %d\n", e.StatusCode)
    case *grantex.APIError:
        fmt.Printf("API error %d: %s (code: %s)\n", e.StatusCode, e.Message, e.Code)
    case *grantex.NetworkError:
        fmt.Printf("Network error: %s\n", e.Message)
    default:
        fmt.Printf("Unexpected error: %v\n", err)
    }
}
```
