--- title: "Go SDK" canonical: "https://admiral.io/docs/reference/go-sdk" description: "Integrate Admiral into Go apps with the official SDK: a typed client for the Admiral API for building tools, operators, and integrations that manage resources." --- # Go SDK The Admiral Go SDK provides a typed client for the Admiral API. Use it to build tools, operators, and integrations that manage Admiral resources programmatically. > **Note:** The SDK is under active development. The API surface may change between releases. This page covers the stable client setup and a basic usage example. ## Installation [#installation] ```bash go get go.admiral.io/sdk ``` Requires Go 1.26+. ## Client setup [#client-setup] ```go package main import ( "context" "log" "os" "go.admiral.io/sdk/client" ) func main() { ctx := context.Background() c, err := client.New(ctx, client.Config{ AuthToken: os.Getenv("ADMIRAL_API_KEY"), AuthScheme: client.AuthSchemeToken, }) if err != nil { log.Fatal(err) } defer c.Close() } ``` `HostPort` defaults to `api.admiral.io:443`. API keys are sent with the `Token` scheme; `Bearer` is for the session tokens the CLI's browser login produces. `ADMIRAL_API_KEY` is the same variable the [CLI](https://admiral.io/docs/reference/cli.md) and the [Terraform provider](https://admiral.io/docs/reference/terraform-provider.md) read. ### Configuration options [#configuration-options] | Field | Type | Default | Description | | ------------------------------------------------ | ------------------- | ----------------------- | --------------------------------------------------------------------- | | `HostPort` | `string` | `api.admiral.io:443` | Admiral API server address (`host:port`) | | `AuthToken` | `string` | none (required) | API key (`admp_…` personal, `adms_…` service) or session token | | `AuthScheme` | `AuthScheme` | `AuthSchemeBearer` | `AuthSchemeToken` for API keys, `AuthSchemeBearer` for session tokens | | `TokenValidator` | `TokenValidator` | `DefaultTokenValidator` | Validates the token format before connecting | | `Logger` | `Logger` | no-op | Logger implementation | | `ConnectionOptions.Insecure` | `bool` | `false` | Use plaintext (no TLS) | | `ConnectionOptions.TLSConfig` | `*tls.Config` | TLS 1.2 minimum | Custom TLS configuration (ignored when `Insecure` is set) | | `ConnectionOptions.DialTimeout` | `time.Duration` | `30s` | Connection establishment timeout | | `ConnectionOptions.DialOptions` | `[]grpc.DialOption` | none | Additional gRPC dial options | | `ConnectionOptions.EnableKeepAliveCheck` | `bool` | `false` | Enable client keepalive pings | | `ConnectionOptions.KeepAliveTime` | `time.Duration` | `30s` | Keepalive ping interval | | `ConnectionOptions.KeepAliveTimeout` | `time.Duration` | `90s` | Keepalive ping response timeout | | `ConnectionOptions.KeepAlivePermitWithoutStream` | `bool` | `false` | Send pings even with no active streams | ### Logging [#logging] The SDK ships with three logger implementations: ```go // Silent (default) client.NewNoOpLogger() // Standard library writer client.NewStdLogger(os.Stderr, client.LevelInfo) // slog integration client.NewSlogLogger(slog.Default()) ``` ## Usage example [#usage-example] This example creates an application, reads it back, and then cleans up: ```go package main import ( "context" "fmt" "log" "os" "go.admiral.io/sdk/client" applicationv1 "go.admiral.io/sdk/proto/admiral/api/application/v1" ) func main() { ctx := context.Background() c, err := client.New(ctx, client.Config{ AuthToken: os.Getenv("ADMIRAL_API_KEY"), AuthScheme: client.AuthSchemeToken, }) if err != nil { log.Fatal(err) } defer c.Close() // Create an application createResp, err := c.Application().CreateApplication(ctx, &applicationv1.CreateApplicationRequest{ Name: "my-service", Description: "Example application", Labels: map[string]string{ "team": "platform", }, }, ) if err != nil { log.Fatal(err) } fmt.Printf("Created: %s (ID: %s)\n", createResp.Application.Name, createResp.Application.Id, ) // Read it back getResp, err := c.Application().GetApplication(ctx, &applicationv1.GetApplicationRequest{ ApplicationId: createResp.Application.Id, }, ) if err != nil { log.Fatal(err) } fmt.Printf("Retrieved: %s\n", getResp.Application.Name) // Clean up _, err = c.Application().DeleteApplication(ctx, &applicationv1.DeleteApplicationRequest{ ApplicationId: createResp.Application.Id, }, ) if err != nil { log.Fatal(err) } fmt.Println("Deleted application") } ``` ## Error handling [#error-handling] The SDK returns standard gRPC errors. Use the `status` package to inspect error codes: ```go resp, err := c.Application().GetApplication(ctx, req) if err != nil { st, ok := status.FromError(err) if ok { switch st.Code() { case codes.NotFound: log.Println("resource does not exist") case codes.Unauthenticated: log.Println("invalid or expired token") case codes.PermissionDenied: log.Println("insufficient permissions") default: log.Fatalf("API error (%s): %s", st.Code(), st.Message()) } } } ``` The `codes` and `status` packages come from `google.golang.org/grpc/codes` and `google.golang.org/grpc/status`. Refer to the [API reference](https://admiral.io/docs/api.md) for details on request and response types for each service.