Browse documentation
SDKsGo SDK

Go SDK

Integrate Go applications with nRouter using our official Go SDK or OpenAI Go client. Access typed helpers, automatic cost tracking, and resilient routing.

Last updated

The nRouter Go SDK provides high-performance, idiomatic Go bindings for interacting with the nRouter unified AI gateway (https://api.nrouter.ai/v1). Verified on pkg.go.dev, it features typed response parsing, automated x-nr-* header extraction, real-time cost calculation, and low-allocation streaming.

In addition to the official SDK, nRouter is 100% wire-compatible with the official OpenAI Go SDK (github.com/openai/openai-go). Pointing either library at the nRouter edge proxy provides immediate enterprise safeguards: server-side prompt injection filtering, organization-level rate limits, transparent model failover, and exact list-price billing.

Prerequisites & Installation

The SDK requires Go 1.21 or higher.

Install the versioned v3 package:

go get github.com/nRouterGateway/nrouter-sdk/sdks/go/v3@v3.0.0

Package documentation is available on pkg.go.dev/github.com/nRouterGateway/nrouter-sdk/sdks/go/v3.

2. OpenAI Go Client (Alternative)

If your existing codebase uses the official OpenAI Go module:

go get github.com/openai/openai-go

Setup & Configuration

Store your nRouter virtual API key in your environment:

export NROUTER_API_KEY="sk-nrouter-your-virtual-key"

Initializing the Official Client

package main

import (
    "log"
    nrouter "github.com/nRouterGateway/nrouter-sdk/sdks/go/v3"
)

func main() {
    // Reads NROUTER_API_KEY from environment and targets https://api.nrouter.ai/v1
    client, err := nrouter.NewFromEnv()
    if err != nil {
        log.Fatalf("Failed to initialize nRouter client: %v", err)
    }
    _ = client
}

Configuration Parameters

Configure custom HTTP transports, connection timeouts, and routing headers:

ParameterTypeDefaultDescription
BaseURLstringhttps://api.nrouter.ai/v1Unified gateway base URL. Must include /v1.
APIKeystringEnvironmentnRouter virtual key (sk-nrouter-...).
Timeouttime.Duration60sMaximum HTTP client timeout for completion requests.
HTTPClient*http.Clienthttp.DefaultClientCustom transport configured with connection pooling.
DefaultHeadersmap[string]stringnilHeaders attached to every outgoing request, such as x-nr-routing.
package main

import (
    "net/http"
    "time"

    nrouter "github.com/nRouterGateway/nrouter-sdk/sdks/go/v3"
)

func createCustomClient(apiKey string) (*nrouter.Client, error) {
    customTransport := &http.Transport{
        MaxIdleConns:        100,
        MaxIdleConnsPerHost: 20,
        IdleConnTimeout:     90 * time.Second,
        TLSHandshakeTimeout: 10 * time.Second,
    }

    httpClient := &http.Client{
        Transport: customTransport,
        Timeout:   45 * time.Second,
    }

    return nrouter.NewClient(
        apiKey,
        nrouter.WithBaseURL("https://api.nrouter.ai/v1"),
        nrouter.WithHTTPClient(httpClient),
        nrouter.WithHeader("x-nr-routing", "latency"),
    )
}

Implementation Patterns

1. Chat Completion (Official SDK)

Execute a structured request and access real-time cost telemetry:

package main

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

    nrouter "github.com/nRouterGateway/nrouter-sdk/sdks/go/v3"
)

func main() {
    client, err := nrouter.NewFromEnv()
    if err != nil {
        log.Fatal(err)
    }

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

    res, err := client.ChatCompletions(ctx, map[string]any{
        "model": "gpt-5.4-mini",
        "messages": []any{
            map[string]any{"role": "system", "content": "You are a distributed systems architect."},
            map[string]any{"role": "user", "content": "Explain raft consensus in three sentences."},
        },
    })
    if err != nil {
        log.Fatalf("Chat completion failed: %v", err)
    }

    fmt.Printf("Choices: %v\n", res.Body["choices"])

    // Inspect real-time gateway spend
    if res.Meta.Cost != nil {
        fmt.Printf("Cost: $%v (Status: %s)\n", *res.Meta.Cost, res.Meta.CostStatus)
    }
    fmt.Printf("Request ID: %s | Model: %s\n", res.Meta.RequestID, res.Meta.Model)
}

2. Using the OpenAI Go SDK

Point github.com/openai/openai-go to nRouter using WithBaseURL:

package main

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

    "github.com/openai/openai-go"
    "github.com/openai/openai-go/option"
)

func main() {
    client := openai.NewClient(
        option.WithAPIKey(os.Getenv("NROUTER_API_KEY")),
        option.WithBaseURL("https://api.nrouter.ai/v1"),
    )

    response, err := client.Chat.Completions.New(context.Background(),
        openai.ChatCompletionNewParams{
            Model: openai.String("gpt-5.4-mini"),
            Messages: openai.F([]openai.ChatCompletionMessageParamUnion{
                openai.UserMessage("Hello, nRouter from Go!"),
            }),
        },
    )
    if err != nil {
        log.Fatalf("Request error: %v", err)
    }

    fmt.Println(response.Choices[0].Message.Content)
}

3. Server-Sent Events (SSE) Streaming

Stream tokens asynchronously using Go channels or stream readers:

package main

import (
    "context"
    "fmt"
    "log"

    nrouter "github.com/nRouterGateway/nrouter-sdk/sdks/go/v3"
)

func main() {
    client, err := nrouter.NewFromEnv()
    if err != nil {
        log.Fatal(err)
    }

    stream, err := client.ChatCompletionsStream(context.Background(), map[string]any{
        "model": "claude-haiku-4-5-20251001",
        "messages": []any{
            map[string]any{"role": "user", "content": "Write a concurrent worker pool in Go."},
        },
        "stream": true,
    })
    if err != nil {
        log.Fatalf("Stream init failed: %v", err)
    }
    defer stream.Close()

    for stream.Next() {
        chunk := stream.Current()
        fmt.Print(chunk.DeltaContent)
    }

    if err := stream.Err(); err != nil {
        log.Printf("Stream terminated with error: %v", err)
    }
    fmt.Println()
}

4. Per-Request Gateway Overrides

To pass prompt templates or bypass caching, attach parameters directly to the request payload:

{
  "model": "gpt-5.5",
  "messages": [{"role": "user", "content": "Summarize Q1 earnings"}],
  "nrouter_prompt_template_id": "tmpl_financial_brief_v1",
  "nrouter_prompt_variables": {"unit": "millions"},
  "nrouter_cache": false
}

Production Best Practices

Deterministic Routing & Fallbacks

Support mission-critical service reliability with fallback chains and latency routing:

res, err := client.ChatCompletions(ctx, map[string]any{
    // Primary model with automatic fallback
    "model": "gpt-5.4-mini,claude-haiku-4-5-20251001",
    "messages": []any{
        map[string]any{"role": "user", "content": "Process transaction verification."},
    },
})
  • x-nr-routing: latency: Directs traffic to the lowest-latency active provider deployment.
  • x-nr-routing: cost: Prioritizes the most cost-effective deployment matching the model specification.
  • Model Fallback Chain: If the primary provider experiences capacity limits or elevated 5xx responses, nRouter fails over instantly without leaking errors to your client goroutines.

Connection Pooling & Goroutine Safety

  1. Singleton Client: The *nrouter.Client is thread-safe and designed to be shared across thousands of concurrent goroutines.
  2. Context Propagation: Always pass request-scoped contexts (context.WithTimeout) to prevent hanging network calls during upstream provider degradation.
  3. Stream Cleanup: Always defer stream.Close() when streaming completions to release underlying HTTP connections back to the connection pool.

Observability & FinOps Integration

Extract header fields from res.Meta:

  • RequestID: Edge-generated UUID for distributed request tracing.
  • Cost: Exact USD cost charged for the call.
  • Model: Actual provider deployment that served the request.
  • CostStatus: exact or unpriced.

Troubleshooting & Error Handling

Errors returned by nRouter map directly to HTTP status codes.

Common Error Codes

StatusCodeCauseRecommended Action
400guardrail_blockedInput rejected by server-side content or injection guardrailsVerify prompt safety; review guardrail settings in nRouter dashboard.
401authentication_errorMissing, incorrect, or expired virtual API keyCheck NROUTER_API_KEY environment variable.
402insufficient_creditsZero organization balance or key spending limit reachedAdd funds in dashboard or update key ceiling.
429rate_limit_exceededClient exceeded RPM/TPM quotaImplement exponential backoff; check retry headers.
500 / 503service_unavailableDownstream provider error or network disruptionUse fallback model lists (model1,model2).

Error Handling Example

package main

import (
    "context"
    "errors"
    "log"

    nrouter "github.com/nRouterGateway/nrouter-sdk/sdks/go/v3"
)

func executeWithRecovery(client *nrouter.Client) {
    _, err := client.ChatCompletions(context.Background(), map[string]any{
        "model": "gpt-5.4-mini",
        "messages": []any{map[string]any{"role": "user", "content": "Execute task"}},
    })
    if err != nil {
        var nErr *nrouter.APIError
        if errors.As(err, &nErr) {
            switch nErr.StatusCode {
            case 400:
                log.Printf("Bad request / guardrail violation: %s", nErr.Message)
            case 401:
                log.Printf("Authentication failed: Check NROUTER_API_KEY")
            case 402:
                log.Printf("Insufficient balance: Virtual key budget reached")
            case 429:
                log.Printf("Rate limit hit: Apply exponential backoff")
            default:
                log.Printf("Gateway error [%d]: %s", nErr.StatusCode, nErr.Message)
            }
            return
        }
        log.Printf("Network transport error: %v", err)
    }
}

Next Steps

Was this page helpful?