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:
- A Paddle sandbox account.
- A sandbox API key with permission to read and write products.
- Go 1.21 or later.
Install the SDK
Add the SDK to your Go module:
go get github.com/PaddleHQ/paddle-go-sdk/v5View the Go SDK on GitHub
Initialize the client
For sandbox, use paddle.NewSandbox(). For production, use paddle.New().
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:
client, err := paddle.New(os.Getenv("PADDLE_API_KEY"))Sandbox API keys contain _sdbx. Sandbox and live keys are separate โ using one against the other API returns a forbidden error.
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.
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.
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:
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
- Use the webhook simulator to test webhook events.
- Browse the API reference to see every endpoint Paddle exposes.
- View the Go SDK reference for the full SDK reference.