cdn.zeroclick.io/sdks/sellers-go) implements the ZeroClick billing guard for Go backends. It verifies that a request really came from ZeroClick and checks that the buyer can pay before your handler runs. It returns the refusals ZeroClick expects and reports what was used. The usual integration is one middleware on each billable route.
This page takes a net/http service from go get to guarded. The quickstart covers the full setup, including the dashboard side, and integrate your API describes the contract the SDK implements.
Install
go-jose) belongs to the optional jwe subpackage for encrypted request bodies. Unless you import that package, Go’s module graph pruning keeps it out of your go.sum and your binary.
What you need first
Two credentials from your dashboard:- A signing secret: a secret value (
zcsec_…) and its key id (hsec_…), called thekid. The SDK uses it to verify thezc-signatureheader on every forwarded request. - An API key (
zc_…) with theusage:readandusage:writescopes. The read scope covers allowance checks; the write scope covers usage reporting.
APIKey carries both scopes. To follow least privilege, pass two scoped keys instead and omit APIKey: UsageReadKey for allowance checks and UsageWriteKey for usage reporting. The split is handy when a separate worker reports usage. A scoped key falls back to APIKey when it is not set, so either form works. See keys and secrets for scopes and rotation.
The dashboard shows each secret once, when you create it. SecretsFromEnv() reads signing secrets from one environment variable of <kid>:<secret> pairs, comma-separated:
The whole integration
This example guards/v1/product-watch for a service product-watch with a meter requests, and leaves /health open. Substitute your own slugs.
main.go
Meter verifies the zc-signature header over the raw bytes, checks that the buyer’s allowance covers one requests unit, and only then calls your handler. When a request fails either step, the middleware refuses it before your code runs, with the exact response ZeroClick expects: a 401 for a bad signature, a priced 402 for a business denial. When the handler responds 2xx, the middleware attaches the zc-usage header so the request settles. A 4xx or 5xx bills nothing.
Inside the handler, r.Body reads normally: verification consumed it, and the middleware put it back. sellers.FromContext returns the verified buyer: AgentID (agt_…) and RequestID (zcreq_…), the id that correlates this request across ZeroClick’s logs and your own.
Test the guard locally: it must refuse a plain request with no ZeroClick headers.
402 challenge, the payment, the forwarded request), deploy the route where ZeroClick can reach it and follow the verification step in the quickstart.
Framework fit
Meter (and its free counterpart Identify) returns a plain func(http.Handler) http.Handler, the standard middleware shape, so it composes with any router built on net/http:
Apply the middleware per billable route, not globally: health probes and other free endpoints should stay unguarded, and each metered route declares its own charge.
For a backend not built on
net/http at all, every decision also flows through the SDK’s framework-neutral Request and Response types. See the API reference.
Next steps
Middleware
What Meter and Identify do on every request, streaming support, and variable usage.
Configuration
Every Config field: keys, signing secrets, body limits, and the outage policy.
API reference
The full public surface, including Guard and the framework-neutral types.
Errors
Decisions versus errors, error codes, and outage classification.