Go SDK

Coming Soon Go 1.21+ Context-aware

Coming Soon — The Go SDK is under development. In the meantime, you can use the REST API directly with net/http.

The Go SDK (github.com/xident/xident-go) is an idiomatic Go client with full context.Context support, structured errors, and functional options.

Installation

go get github.com/xident/xident-go

Quick Start

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/xident/xident-go"
)

func main() {
    client := xident.NewClient(os.Getenv("XIDENT_SECRET_KEY"))

    result, err := client.VerificationTokens.Verify(context.Background(), "tok_xxx")
    if err != nil {
        log.Fatal(err)
    }

    if result.Verified {
        fmt.Printf("Age bracket: %d\n", result.AgeBracket)
        fmt.Printf("Session: %s\n", result.SessionID)
    }
}

HTTP Handler Example

package main

import (
    "net/http"
    "os"

    "github.com/xident/xident-go"
)

var xidentClient = xident.NewClient(os.Getenv("XIDENT_SECRET_KEY"))

func verificationCallback(w http.ResponseWriter, r *http.Request) {
    token := r.URL.Query().Get("token")
    status := r.URL.Query().Get("status")

    if status != "success" || token == "" {
        http.Redirect(w, r, "/verification-cancelled", http.StatusFound)
        return
    }

    result, err := xidentClient.VerificationTokens.Verify(r.Context(), token)
    if err != nil {
        http.Redirect(w, r, "/verification-error", http.StatusFound)
        return
    }

    if result.Verified && result.AgeBracket >= 18 {
        // Store in session/cookie
        http.Redirect(w, r, "/content", http.StatusFound)
        return
    }

    http.Redirect(w, r, "/too-young", http.StatusFound)
}

Gin Example

import (
    "github.com/gin-gonic/gin"
    "github.com/xident/xident-go"
)

func setupRoutes(r *gin.Engine) {
    client := xident.NewClient(os.Getenv("XIDENT_SECRET_KEY"))

    r.GET("/verified", func(c *gin.Context) {
        token := c.Query("token")
        status := c.Query("status")

        if status != "success" || token == "" {
            c.Redirect(302, "/verification-cancelled")
            return
        }

        result, err := client.VerificationTokens.Verify(c.Request.Context(), token)
        if err != nil {
            c.Redirect(302, "/verification-error")
            return
        }

        if result.Verified && result.AgeBracket >= 18 {
            c.Redirect(302, "/content")
            return
        }

        c.Redirect(302, "/too-young")
    })
}

Planned API Surface

client := xident.NewClient("sk_live_xxx")

// Token verification
result, err := client.VerificationTokens.Verify(ctx, token)
result, err := client.VerificationTokens.Issue(ctx, &xident.IssueTokenParams{
    AccountID:  "acc_xxx",
    AgeBracket: 18,
    TenantID:   "ten_xxx",
})
err := client.VerificationTokens.Revoke(ctx, token)

// Usage & billing
usage, err := client.Usage.Get(ctx, &xident.UsageParams{
    From: "2026-01-01",
    To:   "2026-01-31",
})

// Webhook signature verification
valid := client.Webhooks.VerifySignature(payload, signature, secret)

Types

type VerificationResult struct {
    Verified   bool              `json:"verified"`
    AgeBracket int               `json:"age_bracket"`  // 12, 15, 18, 21, or 25
    SessionID  string            `json:"session_id"`
    UserID     string            `json:"user_id,omitempty"`
    Metadata   map[string]string `json:"metadata,omitempty"`
    VerifiedAt time.Time         `json:"verified_at"`
}

type ClientOption func(*Client)

func WithBaseURL(url string) ClientOption    // Default: https://api.xident.io
func WithTimeout(d time.Duration) ClientOption // Default: 10s
func WithHTTPClient(c *http.Client) ClientOption

Error Handling

result, err := client.VerificationTokens.Verify(ctx, token)
if err != nil {
    var apiErr *xident.Error
    if errors.As(err, &apiErr) {
        fmt.Println(apiErr.Code)    // "TOKEN_EXPIRED", "TOKEN_USED", "INVALID_TOKEN"
        fmt.Println(apiErr.Message) // Human-readable message
        fmt.Println(apiErr.Status)  // HTTP status code
    }
}

Using the REST API Directly

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

func verifyToken(token string) (*VerificationResult, error) {
    body, _ := json.Marshal(map[string]string{"token": token})

    req, _ := http.NewRequest("POST",
        "https://api.xident.io/api/v1/verification-tokens/verify",
        bytes.NewReader(body))

    req.Header.Set("X-API-Key", os.Getenv("XIDENT_SECRET_KEY"))
    req.Header.Set("Content-Type", "application/json")

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

    var result struct {
        Success bool               `json:"success"`
        Data    VerificationResult `json:"data"`
    }
    json.NewDecoder(resp.Body).Decode(&result)
    return &result.Data, nil
}

Related