Announcing the PermitCore Go SDK
The 7th official PermitCore SDK is live — a zero-dependency Go 1.21+ client with native ECDSA offline verification, a working demo app, and full docs.
Updated for SDK 2.1.1: install the /v2 Go module and configure trusted tenant public keys before using offline caches or persisted offline activation. The quick start below uses the current module path. See the Go reference and offline migration guide for configuration and breaking changes from the original v1 announcement.
We just shipped the 7th official PermitCore SDK: Go. It's a zero-dependency client for Go 1.21+ — no third-party packages, not even for offline license token verification, which is usually the one part of an SDK that needs an external crypto library.
Why Go, and why now
Go was the most-requested gap on our roadmap — a common choice for CLI tools, backend services, and self-hosted agents that need to check a license without pulling in a heavyweight runtime. It was also the SDK we could build with the highest confidence: Go's standard library already covers everything the other SDKs need extra packages for.
What makes this one different
Every PermitCore SDK verifies offline activation tokens the same way — ECDSA P-256/SHA-256, with the server signing a raw 64-byte IEEE P1363 signature (not the ASN.1 DER format most crypto libraries expect). SDKs built on OpenSSL, PHP's openssl_verify(), or Python's cryptography package all have to hand-convert that signature to DER before they can verify it.
Go's crypto/ecdsa package takes the signature's r and s values directly — ecdsa.Verify(pub, hash, r, s) — so the Go SDK skips that conversion step entirely. One less place for a byte-handling bug to hide.
// Pure local verification — no network call, ever. result := permitcore.VerifyOfflineToken(token, publicKeyBase64) if result.IsValid {"{"} fmt.Println("Valid! Product:", result.Payload.ProductName) {"}"}
Quick start
import "github.com/permitCore-spec/permitcore-sdk-go/v2" client := permitcore.New("https://api.permitcore.dev") result := client.Validate("PERMIT-XXXX-XXXX-XXXX-XXXX", "") if !result.IsValid {"{"} log.Fatalf("License invalid: %s", result.Message) {"}"} if result.HasFeature("export") {"{"} enableExport() {"}"}
Validate/Activate never return a Go error — a network failure and a rejected key both come back as *LicenseResult{"{"}IsValid: false{"}"}, one branch to check either way. Everything else — floating checkout/heartbeat/checkin, metered billing, the offline grace-period disk cache — works exactly like the other six SDKs, because they all speak the same wire protocol.
Tested against real traffic, not just written
Before shipping, we ran the Go SDK against all 10 shared cross-SDK cryptographic test vectors every PermitCore SDK is checked against, then went further: spun up a real license through the live Admin API and exercised the entire flow — activate, validate, meter, floating checkout, a genuinely server-issued offline token, and the offline grace-cache fallback with the server pulled offline mid-test. We also downloaded the real SDK+demo zip a customer would get and built it completely standalone, outside the PermitCore repo, to prove the packaging works end to end.
Try it
Grab the SDK and full API reference at /docs/sdks/go, or download a complete working demo app — Task Manager Pro — that gates itself behind a real license and includes a developer console for exercising every SDK call against your own instance.
Update (2026-09-28): the SDK is now a real, tagged Go module — go get github.com/permitCore-spec/permitcore-sdk-go@v1.1.0 works directly, no manual setup. (Go modules are version-control/tag-based rather than served from a central registry like npm or PyPI, so the tagged repo itself is the "registry" here.) The source-ZIP-plus-replace-directive route from this post's original text still works too, if you'd rather vendor the source directly — see the docs page for both options.
Build your first licensed product without building a license server.
Create a free PermitCore account, issue a test license, and validate it from your application.