Go SDK
The Go client provides typed clients for APIGuard, NIS2 Compass, and CITADEL, plus shared types for all opensecstack SDK & Contracts integration contracts. It requires Go 1.22+ and has zero external dependencies — only the standard library.
Installation
Add the module to your project with go get:
go get github.com/opensecstack/sdk/go/opensecstack@latest
Import the package in your code:
import "github.com/opensecstack/sdk/go/opensecstack"
Client construction
Each platform has a dedicated constructor that takes a base URL and an API key. Clients are safe to reuse across goroutines.
"cm">// APIGuard client apiguard := opensecstack.NewAPIGuardClient( "https:"cm">//apiguard.internal", "ag_key_...", ) "cm">// NIS2 Compass client nis2 := opensecstack.NewNIS2CompassClient( "https:"cm">//nis2compass.internal", "nc_key_...", ) "cm">// CITADEL client(HMAC-SHA256 signed) citadel := opensecstack.NewCITADELClient(opensecstack.CITADELClientOptions{ BaseURL: "https:"cm">//citadel.internal", SharedSecret: "hmac-secret", }) defer citadel.Drain(context.Background()) "cm">// flush in-flight events on shutdown
Running a scan
Start an APIGuard scan against an OpenAPI spec URL, poll until it completes, then retrieve critical findings. Scans run asynchronously on the server — poll GetScan until the status reaches a terminal state.
"cm">// Start scan — simple form scan, err := apiguard.CreateScan(ctx, "https:"cm">//api.example.com/openapi.json") if err != nil { return err } fmt.Println("Scan ID:", scan.ID) "cm">// Poll until complete for { scan, err = apiguard.GetScan(ctx, scan.ID) if err != nil { return err } if scan.Status == opensecstack.ScanStatusCompleted || scan.Status == opensecstack.ScanStatusFailed { break } fmt.Printf(" ... status: %s\n", scan.Status) time.Sleep(5 * time.Second) } "cm">// Retrieve only critical findings findings, err := apiguard.GetFindings(ctx, scan.ID, opensecstack.GetFindingsOptions{ Severity: "critical", }) if err != nil { return err } for _, finding := range findings { fmt.Printf("[%s] %s — %s %s\n", finding.Severity, finding.Title, finding.EndpointMethod, finding.EndpointPath) }
For advanced scan configuration (custom modules, bearer auth, spec path override), use CreateScanFull:
scan, err := apiguard.CreateScanFull(ctx, opensecstack.CreateScanOptions{ SpecURL: "https:"cm">//api.example.com/openapi.json", Target: "https:"cm">//api.example.com", Modules: []string{"owasp-api1", "owasp-api2", "owasp-api3"}, AuthType: "bearer", AuthToken: "my-test-token", })
NIS2 Compass client
Create an organisation, run an assessment, and mark a NIS2 Article 21 control as compliant after gathering evidence from an APIGuard scan.
"cm">// Create organisation org, err := nis2.CreateOrganisation(ctx, opensecstack.CreateOrganisationRequest{ Name: "Acme Corp", Industry: "finance", Country: "AL", Size: "large", EntityType: "essential", }) "cm">// Create assessment — 10 NIS2 Article 21(2) controls(a–j) are seeded automatically assessment, err := nis2.CreateAssessment(ctx, org.ID, opensecstack.CreateAssessmentRequest{ Title: "Q1 2026 NIS2 Assessment", FrameworkVersion: "NIS2-2022/0383", }) "cm">// Upload an evidence artifact(e.g. a SARIF report from APIGuard) artifact, err := nis2.UploadArtifact(ctx, assessment.ID, "/tmp/apiguard-report.sarif", "evidence", "", "APIGuard scan evidence") "cm">// Mark control 'e' (security in network and information systems) as compliant ctrl, err := nis2.PatchControl(ctx, assessment.ID, "e", opensecstack.PatchControlRequest{ Status: "compliant", Notes: "APIGuard scan completed — zero critical findings", }) fmt.Printf("Control %s(%s): %s\n", ctrl.MeasureRef, ctrl.ArticleRef, ctrl.Status) "cm">// Generate a PDF compliance report pdf, err := nis2.GenerateReport(ctx, assessment.ID) if err != nil { return err } os.WriteFile("nis2-report.pdf", pdf, 0644)
CITADEL client
The CITADEL client delivers structured security events to the immutable WORM audit chain via HMAC-SHA256 signed HTTP POST. SendEvent is non-blocking — it enqueues the event and a background goroutine handles delivery.
"cm">// Dispatch an event(non-blocking) citadel.SendEvent(ctx, opensecstack.SecurityEvent{ EventType: "apiguard.scan.completed", Source: "apiguard", ActorID: apiKeyID, ActorType: "api_key", ResourceType: "scan", ResourceID: scan.ID, Severity: "info", Payload: json.RawMessage(`{"total_findings":3}`), }) "cm">// Query the WORM audit chain events, err := citadel.GetEvents(ctx, opensecstack.GetEventsOptions{ Source: "apiguard", EventType: "apiguard.scan.completed", Limit: 50, }) "cm">// Verify the chain integrity locally(TripleHash: SHA-256 + SHA-512 + BLAKE3) err = citadel.VerifyChain(ctx, events)
Error handling
All clients return typed errors. Use errors.As to inspect the specific error type and act accordingly (for example, back off on rate-limit errors).
scan, err := apiguard.CreateScanFull(ctx, opensecstack.CreateScanOptions{ SpecURL: "https:"cm">//api.example.com/openapi.json", }) if err != nil { var rateLimitErr *opensecstack.RateLimitError if errors.As(err, &rateLimitErr) { time.Sleep(rateLimitErr.RetryAfter) "cm">// retry ... } return err }
| Error type | HTTP status | Meaning |
|---|---|---|
*opensecstack.AuthError | 401 | Invalid API key |
*opensecstack.NotFoundError | 404 | Resource not found |
*opensecstack.RateLimitError | 429 | Rate limit hit; has RetryAfter field |
*opensecstack.ServerError | 5xx | Server-side error |
Full documentation
Other SDK language clients: Python SDK, TypeScript SDK, Rust SDK.
The complete Go client reference — including all method signatures, option structs, and type definitions — is available in the SDK repository: