For AI agents and LLMs: a structured documentation index is available at /llms.txt. Every page has a Markdown sibling โ€” append .md to any URL.

Skip to content
Docs

Get started with Paddle in Go

Install the Paddle Go SDK, initialize a client, make your first request, and verify webhook signatures.

AI summary

Install the Paddle Go SDK, initialize a sandbox client with context.Context support, make your first API request using the paginated Iter helper, and verify webhook signatures with the built-in WebhookVerifier middleware.

  • โ€ข Use paddle.NewSandbox() for sandbox and paddle.New() for production โ€” sandbox keys contain _sdbx and are separate from live keys, which return a forbidden error if used against the wrong API.
  • โ€ข The paginated Iter method on collection responses walks through all pages lazily, respecting context cancellation from the parent context.Context.
  • โ€ข WebhookVerifier.Middleware() wraps your handler and rejects unverified requests before they reach your logic โ€” return 200 quickly and process the event asynchronously.
Latest: v5.2.0 ยท 2026-03-30

This quickstart walks through installing the Paddle Go SDK, initializing a client, making your first read-only API call, and verifying webhook signatures. The Go SDK is built around context.Context throughout, useful for backends that need cancellation, timeouts, and request-scoped values.

Before you begin

You'll need:

Install the SDK

Add the SDK to your Go module:

Shell
go get github.com/PaddleHQ/paddle-go-sdk/v5

View the Go SDK on GitHub

Initialize the client

For sandbox, use paddle.NewSandbox(). For production, use paddle.New().

Go
package main
import (
"log"
"os"
paddle "github.com/PaddleHQ/paddle-go-sdk/v5"
)
func main() {
client, err := paddle.NewSandbox(os.Getenv("PADDLE_API_KEY"))
if err != nil {
log.Fatal(err)
}
_ = client
}

For production, swap NewSandbox for New:

Go
client, err := paddle.New(os.Getenv("PADDLE_API_KEY"))

Make your first request

List products to confirm the client is wired up. The SDK returns a paginated collection. Use Iter to walk through results.

Go
package main
import (
"context"
"fmt"
"log"
"os"
paddle "github.com/PaddleHQ/paddle-go-sdk/v5"
)
func main() {
client, err := paddle.NewSandbox(os.Getenv("PADDLE_API_KEY"))
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
products, err := client.ListProducts(ctx, &paddle.ListProductsRequest{
IncludePrices: true,
})
if err != nil {
log.Fatal(err)
}
err = products.Iter(ctx, func(p *paddle.Product) (bool, error) {
fmt.Printf("%s %s\n", p.ID, p.Name)
return true, nil
})
if err != nil {
log.Fatal(err)
}
}

Pass a cancellable context.Context through your call chain so the SDK can abort in-flight requests when the parent context is cancelled.

Verify webhooks

You can use webhooks to keep your app in sync with Paddle. For example, you can provision access when a subscription is created, or revoke access when a subscription is cancelled.

The Go SDK's WebhookVerifier ships with a Middleware helper that wraps your handler and rejects unverified requests automatically.

Go
package main
import (
"log"
"net/http"
"os"
paddle "github.com/PaddleHQ/paddle-go-sdk/v5"
)
func main() {
verifier := paddle.NewWebhookVerifier(os.Getenv("PADDLE_WEBHOOK_SECRET"))
handler := verifier.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Request is verified. Decode and dispatch the event.
// Best practice: store the event in a queue or DB and return 200 fast.
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(`{"success":true}`))
}))
http.Handle("/webhooks", handler)
log.Fatal(http.ListenAndServe(":3000", nil))
}

If you'd rather verify manually, call Verify directly:

Go
ok, err := verifier.Verify(r)
if err != nil || !ok {
http.Error(w, "invalid signature", http.StatusBadRequest)
return
}

For the full webhook setup flow, including creating notification destinations, picking events, and retry behavior, see Verify webhook signatures.

Next steps

Was this page helpful?