Go SDK
Talos generates a Go HTTP client from its OpenAPI spec with OpenAPI Generator and ships it in
the internal/client/generated package.
The client lives in an internal/ package, so external Go modules can't import it. Talos uses it for its own integration tests.
To use a Go client in your own application, generate one from the OpenAPI spec at api/talos.openapi-v3.json.
Generate your own client
openapi-generator generate \
-i api/talos.openapi-v3.json \
-g go \
-o generated/go-client
The examples below use the internal client's types. A client you generate from the spec has the same API shape.
For a complete, runnable program that exercises every operation shown below, see
tools/doctest/examples/go_sdk/main.go.
go build -o .bin/doctest-go-sdk ./tools/doctest/examples/go_sdk
./.bin/doctest-go-sdk
Initialize the client
cfg := client.NewConfiguration()
cfg.Servers = client.ServerConfigurations{
{URL: talosURL},
}
c := client.NewAPIClient(cfg)
Issue an API key
issueResp, _, err := c.ApiKeysAPI.
AdminIssueApiKey(ctx).
IssueApiKeyRequest(client.IssueApiKeyRequest{
Name: new("my-service"),
ActorId: new("user_123"),
Scopes: []string{"read", "write"},
Ttl: new("720h"),
}).
Execute()
if err != nil {
return fmt.Errorf("issue key: %w", err)
}
// Secret is only available at creation time
issuedKey := issueResp.GetIssuedApiKey()
fmt.Println("Key ID:", issuedKey.GetKeyId())
fmt.Println("Secret:", issueResp.GetSecret())
Verify a credential
verifyResp, _, err := c.ApiKeysAPI.
AdminVerifyApiKey(ctx).
VerifyApiKeyRequest(client.VerifyApiKeyRequest{
Credential: new(secret),
}).
Execute()
if err != nil {
return fmt.Errorf("verify key: %w", err)
}
if verifyResp.GetIsValid() {
fmt.Println("Key is valid, owner:", verifyResp.GetActorId())
} else {
fmt.Println("Key is invalid:", verifyResp.GetErrorMessage())
}
Batch verify
batchResp, _, err := c.ApiKeysAPI.
AdminBatchVerifyApiKeys(ctx).
BatchVerifyApiKeysRequest(client.BatchVerifyApiKeysRequest{
Requests: []client.VerifyApiKeyRequest{
{Credential: new(secret)},
{Credential: new("invalid-key-for-testing")},
},
}).
Execute()
if err != nil {
return fmt.Errorf("batch verify: %w", err)
}
for i, result := range batchResp.GetResults() {
fmt.Printf("Key %d: is_valid=%v\n", i, result.GetIsValid())
}
Revoke a key
Enum fields use typed constants, not raw strings:
reason := client.REVOCATIONREASON_REVOCATION_REASON_KEY_COMPROMISE
_, _, err = c.ApiKeysAPI.
AdminRevokeIssuedApiKey(ctx, keyID).
AdminRevokeIssuedApiKeyBody(client.AdminRevokeIssuedApiKeyBody{
Reason: &reason,
}).
Execute()
if err != nil {
return fmt.Errorf("revoke key: %w", err)
}
fmt.Println("Key revoked successfully")
Derive a JWT token
algorithm := client.TOKENALGORITHM_TOKEN_ALGORITHM_JWT
deriveResp, _, err := c.ApiKeysAPI.
AdminDeriveToken(ctx).
DeriveTokenRequest(client.DeriveTokenRequest{
Credential: new(secret),
Algorithm: &algorithm,
Ttl: new("1h"),
Scopes: []string{"read"},
}).
Execute()
if err != nil {
return fmt.Errorf("derive token: %w", err)
}
derivedToken := deriveResp.GetToken()
fmt.Println("JWT:", derivedToken.GetToken())
Error handling
The SDK returns an error for every non-2xx response. The error wraps a
google.rpc.Status body. Read it through the typed
GenericOpenAPIError to get the canonical gRPC code, the message, and any ErrorInfo details.
_, httpResp, err := c.ApiKeysAPI.
AdminGetIssuedApiKey(ctx, "nonexistent-id").
Execute()
if err != nil {
var apiErr *client.GenericOpenAPIError
if errors.As(err, &apiErr) {
var status struct {
Code int32 `json:"code"`
Message string `json:"message"`
Details []struct {
Type string `json:"@type"`
Reason string `json:"reason"`
Domain string `json:"domain"`
Metadata map[string]string `json:"metadata"`
} `json:"details"`
}
if jsonErr := json.Unmarshal(apiErr.Body(), &status); jsonErr == nil {
fmt.Println("gRPC code:", status.Code) // 5 = NOT_FOUND
fmt.Println("HTTP status:", httpResp.StatusCode) // 404
fmt.Println("Message:", status.Message)
for _, d := range status.Details {
if strings.HasSuffix(d.Type, "ErrorInfo") {
fmt.Println("Reason:", d.Reason) // Stable; switch on this
}
}
}
}
}
Match on details[*].reason from the ErrorInfo detail. It's the stable, machine-readable identifier. The message field is for
logs and can change between releases.
A failed verification is not an SDK error: the verify endpoint returns 200 OK with is_valid: false. Branch on
verifyResp.GetIsValid() and inspect verifyResp.GetErrorCode() instead.
Regenerating the client
To regenerate the bundled Go client, run:
make generate-sdk
This reads the OpenAPI spec from api/talos.openapi-v3.json and writes to internal/client/generated/.
