### Install Clerk Go SDK Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Install the Clerk Go SDK using the go get command. ```bash go get -u github.com/clerk/clerk-sdk-go/v2 ``` -------------------------------- ### v1 Organization Create and List Example Source: https://github.com/clerk/clerk-sdk-go/blob/v2/v2_migration_guide.md Demonstrates creating and listing organizations using the v1 Clerk Go SDK, which organizes operations by service. ```go import ( "github.com/clerkinc/clerk-sdk-go" ) func main() { client, err := clerk.NewClient("sk_live_XXX") if err != nil { // handle error } // Create an organization org, err := client.Organizations().Create(clerk.CreateOrganizationParams{ Name: "Acme Inc", }) if err != nil { if errResp, ok := err.(*clerk.ErrorResponse); ok { // Access the API errors errResp.Errors } } // List all organizations, limit results to one. limit := 1 orgs, err := client.Organizations().ListAll(clerk.ListAllOrganizationsParams{ Limit: &limit, }) if err != nil { // handle the error } if orgs.TotalCount > 0 { // Get the first organization in the list org = orgs.Data[0] } } ``` -------------------------------- ### Install Clerk Go SDK Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Import the Clerk Go SDK package using Go Modules or explicitly with `go get`. ```go import ( "github.com/clerk/clerk-sdk-go/v2" ) ``` ```bash go get -u github.com/clerk/clerk-sdk-go/v2 ``` -------------------------------- ### Initialize and Use Clerk SDK Client Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Demonstrates how to initialize a Clerk SDK client with an API key and perform common operations like Create, Get, Update, Delete, and List. Each operation requires a context.Context. ```go import ( "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/$resource$" ) // Each operation requires a context.Context as the first argument. ctx := context.Background() // Initialize a client with an API key config := &clerk.ClientConfig{} config.Key = "sk_live_XXX" client := $resource$.NewClient(config) // Create resource, err := client.Create(ctx, &$resource$.CreateParams{}) // Get resource, err := client.Get(ctx, id) // Update resource, err := client.Update(ctx, id, &$resource$.UpdateParams{}) // Delete resource, err := client.Delete(ctx, id) // List list, err := client.List(ctx, &$resource$.ListParams{}) for _, resource := range list.$Resource$s { // do something with the resource } ``` -------------------------------- ### Client-Based Configuration: NewClient for Scoped Settings Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Create a new client instance with specific configurations, allowing multiple API keys within the same process. This example demonstrates fetching a user by ID. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/user" ) func main() { config := &clerk.ClientConfig{} config.Key = clerk.String("sk_live_XXX") client := user.NewClient(config) usr, err := client.Get(context.Background(), "user_2abc123") if err != nil { log.Fatal(err) } fmt.Println(usr.ID, usr.EmailAddresses) } ``` -------------------------------- ### Client Initialization and Basic Operations Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Demonstrates how to initialize a Clerk client with an API key and perform basic CRUD operations (Create, Get, Update, Delete) and List operations for a resource. ```APIDOC ## Client Initialization and Basic Operations ### Description This section shows how to set up a client for interacting with Clerk API resources. It covers initializing a client with configuration, setting an API key, and performing common operations like creating, retrieving, updating, deleting, and listing resources. Each operation requires a `context.Context`. ### Usage ```go import ( "context" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/$resource$" ) // Initialize a client with an API key ctx := context.Background() config := &clerk.ClientConfig{} config.Key = "sk_live_XXX" client := $resource$.NewClient(config) // Create a resource resource, err := client.Create(ctx, &$resource$.CreateParams{}) // Get a resource by ID resource, err := client.Get(ctx, id) // Update a resource by ID resource, err := client.Update(ctx, id, &$resource$.UpdateParams{}) // Delete a resource by ID resource, err := client.Delete(ctx, id) // List resources list, err := client.List(ctx, &$resource$.ListParams{}) for _, resource := range list.$Resource$s { // Process each resource } ``` ``` -------------------------------- ### Create Organization Example: Clerk Go SDK v1 vs v2 Source: https://github.com/clerk/clerk-sdk-go/blob/v2/UPGRADING.md Illustrates the difference in creating an organization between v1 and v2 of the Clerk Go SDK, highlighting changes in client initialization, API calls, and parameter handling. ```go // Create an organization, in v1 and v2. Error handling is omitted. - client, err := clerk.NewClient("sk_live_XXX") - org, err := client.Organizations().Create(clerk.CreateOrganizationParams{ - Name: "Acme Inc", - }) + ctx := context.Background() + clerk.SetKey("sk_live_XXX") + org, err := organization.Create(ctx, &organization.CreateParams{ + Name: clerk.String("Acme Inc"), + }) ``` -------------------------------- ### Specific API Examples Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Provides concrete examples for interacting with specific Clerk API resources such as organizations, organization memberships, and users. ```APIDOC ## Specific API Examples ### Description This section provides practical examples of using the Clerk SDK for Go with specific resources like organizations, organization memberships, and users. It demonstrates setting the API key globally and then calling resource-specific functions. ### Examples ```go import ( "context" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/organization" "github.com/clerk/clerk-sdk-go/v2/organizationmembership" "github.com/clerk/clerk-sdk-go/v2/user" ) func main() { ctx := context.Background() // Set the API key globally clerk.SetKey("sk_live_XXX") // Create an organization org, err := organization.Create(ctx, &organization.CreateParams{ Name: clerk.String("Clerk Inc"), }) // Update an organization org, err = organization.Update(ctx, org.ID, &organization.UpdateParams{ Slug: clerk.String("clerk"), }) // List organization memberships with parameters listParams := organizationmembership.ListParams{} listParams.Limit = clerk.Int64(10) memberships, err := organizationmembership.List(ctx, listParams) if memberships.TotalCount < 0 { // Handle error or unexpected count return } membership := memberships[0] // Get a user by ID usr, err := user.Get(ctx, membership.UserID) } ``` ``` -------------------------------- ### Users API: Create, Get, Update, Delete, List Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Provides examples for performing CRUD operations on users, including creating, updating, listing with filters, verifying passwords, banning, unbanning, and deleting users. ```APIDOC ## Users API: `user.Create`, `user.Get`, `user.Update`, `user.Delete`, `user.List` The `user` package provides full CRUD operations plus helpers for banning, locking, MFA management, password verification, and OAuth token listing. `user.List` automatically combines two API calls (results + count) into a single `*clerk.UserList`. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/user" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // Create a user created, err := user.Create(ctx, &user.CreateParams{ EmailAddresses: &[]string{"alice@example.com"}, FirstName: clerk.String("Alice"), LastName: clerk.String("Smith"), Password: clerk.String("S3cur3P@ss!"), PublicMetadata: clerk.JSONRawMessage([]byte(`{"plan":"pro"}`)), }) if err != nil { log.Fatal(err) } fmt.Println("Created:", created.ID) // Update updated, err := user.Update(ctx, created.ID, &user.UpdateParams{ FirstName: clerk.String("Alicia"), }) if err != nil { log.Fatal(err) } fmt.Println("Updated first name:", *updated.FirstName) // List with filters list, err := user.List(ctx, &user.ListParams{ ListParams: clerk.ListParams{Limit: clerk.Int64(5)}, EmailAddresses: []string{"alice@example.com"}, }) if err != nil { log.Fatal(err) } fmt.Printf("Total users: %d\n", list.TotalCount) for _, u := range list.Users { fmt.Println(" -", u.ID) } // Verify password resp, err := user.VerifyPassword(ctx, &user.VerifyPasswordParams{ UserID: created.ID, Password: "S3cur3P@ss!", }) if err != nil { log.Fatal(err) } fmt.Println("Password valid:", resp.Verified) // Ban / Unban user.Ban(ctx, created.ID) user.Unban(ctx, created.ID) // Delete deleted, err := user.Delete(ctx, created.ID) if err != nil { log.Fatal(err) } fmt.Println("Deleted:", deleted.ID) } ``` ``` -------------------------------- ### Specific API Operations with Clerk SDK Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Illustrates specific API operations for organizations, memberships, and users using the Clerk SDK. Includes setting the API key, creating, updating, listing, and getting resources. ```go import ( "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/organization" "github.com/clerk/clerk-sdk-go/v2/organizationmembership" "github.com/clerk/clerk-sdk-go/v2/user" ) func main() { // Each operation requires a context.Context as the first argument. ctx := context.Background() // Set the API key clerk.SetKey("sk_live_XXX") // Create an organization org, err := organization.Create(ctx, &organization.CreateParams{ Name: clerk.String("Clerk Inc"), }) // Update the organization org, err = organization.Update(ctx, org.ID, &organization.UpdateParams{ Slug: clerk.String("clerk"), }) // List organization memberships listParams := organizationmembership.ListParams{} listParams.Limit = clerk.Int64(10) memberships, err := organizationmembership.List(ctx, params) if memberships.TotalCount < 0 { return } membership := memberships[0] // Get a user usr, err := user.Get(ctx, membership.UserID) } ``` -------------------------------- ### Accessing API Response Details Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Shows how to access the `Response` field of an API resource to get details about the HTTP response, such as headers, status, and raw body. Use `Response.Success()` to check for success. ```go dmn, err := domain.Create(context.Background(), &domain.CreateParams{}) if !dmn.Response.Success() { dmn.Response.TraceID } ``` -------------------------------- ### Handle API Errors with clerk.APIErrorResponse in Clerk Go SDK v2 Source: https://github.com/clerk/clerk-sdk-go/blob/v2/UPGRADING.md Example demonstrating how to catch and inspect `clerk.APIErrorResponse` to access detailed error information, including TraceID and raw JSON. ```go // Create an organization, in v1 and v2. Error handling is omitted. - org, err := client.Organizations().Create(clerk.CreateOrganizationParams{ - Name: "Acme Inc", - }) - if err != nil { - if errResp, ok := err.(*clerk.ErrorResponse); ok { - // Access the API errors - errResp.Errors - } - } + ctx := context.Background() + clerk.SetKey("sk_live_XXX") + org, err := organization.Create(ctx, &organization.CreateParams{ + Name: clerk.String("Acme Inc"), + }) + if err != nil { + if apiErr, ok := err.(*clerk.APIErrorResponse); ok { + // Access the API errors and additional information + apiErr.TraceID + apiErr.Error() + apiErr.Response.RawJSON + } + } ``` -------------------------------- ### Accessing API Responses Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Explains how to access the `Response` field within API resource objects to get details about the HTTP response, such as headers, status, and raw body. ```APIDOC ## Accessing API Responses ### Description This section details how to access the `Response` field available in API resource objects returned by SDK operations. This field provides access to underlying HTTP response details, including headers, status codes, and the raw response body, which can be useful for debugging or advanced handling. ### Usage ```go import ( "context" "github.com/clerk/clerk-sdk-go/v2/domain" ) dmn, err := domain.Create(context.Background(), &domain.CreateParams{}) if !dmn.Response.Success() { // Access trace ID for debugging traceID := dmn.Response.TraceID // Other response details can be accessed via dmn.Response } ``` ``` -------------------------------- ### Client-Based Configuration: NewClient Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Illustrates how to create a client with a scoped configuration, allowing for multiple API keys within the same process. ```APIDOC ## Client-Based Configuration: `NewClient` Each resource sub-package exposes `NewClient` for scoped configurations, enabling multiple API keys in one process. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/user" ) func main() { config := &clerk.ClientConfig{} config.Key = clerk.String("sk_live_XXX") client := user.NewClient(config) usr, err := client.Get(context.Background(), "user_2abc123") if err != nil { log.Fatal(err) } fmt.Println(usr.ID, usr.EmailAddresses) } ``` ``` -------------------------------- ### Implement Custom Backend for Testing Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Create and set a custom `Backend` implementation to control Clerk SDK behavior during tests. This allows for fine-grained control over API responses. ```go func TestWithCustomBackend(t *testing.T) { clerk.SetBackend(&customBackend{}) } type customBackend struct {} // Implement the Backend interface func (b *customBackend) Call(ctx context.Context, r *clerk.APIRequest, reader clerk.ResponseReader) error { // Construct a clerk.APIResponse and use the reader's Read method. reader.Read(&clerk.APIResponse{}) } ``` -------------------------------- ### Fetch List of Users: Clerk Go SDK v1 vs v2 Source: https://github.com/clerk/clerk-sdk-go/blob/v2/UPGRADING.md Demonstrates fetching a list of users, showing the updated parameter structure and response format in v2, which includes total count and a slice of resources. ```go // Fetch a list of 10 users. Error handling is omitted. - limit := 10 - users, err := client.Users().ListAll(clerk.ListAllUserParams{ - Limit: &limit, - }) - if len(users) > 0 { - fmt.Println(users[0].ID) - } + params := &user.ListParams{} + params.Limit = clerk.Int64(10) + list, err := user.List(context.Background(), ¶ms) + if list.TotalLength > 0 { + fmt.Println(list.Users[0].ID) + } ``` -------------------------------- ### Mock Clerk SDK with httptest.Server Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Use `httptest.NewServer` to create a mock server for testing Clerk SDK interactions. Provide the server's client and URL to the Clerk backend configuration. ```go func TestWithMockServer(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Write the response. })) defer ts.Close() clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ HTTPClient: ts.Client(), URL: &ts.URL, })) } ``` -------------------------------- ### v2 Usage With Client: Create and List Organizations Source: https://github.com/clerk/clerk-sdk-go/blob/v2/v2_migration_guide.md Demonstrates creating and listing organizations in v2 of the Clerk Go SDK using a dedicated client, useful for managing multiple API keys or requiring more flexibility. ```go import ( "context" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/organization" ) func main() { ctx := context.Background() config := &clerk.ClientConfig{} config.Key = "sk_live_XXX" client := organization.NewClient(config) // Create an organization org, err := client.Create(ctx, &organization.CreateParams{ Name: clerk.String("Acme Inc"), }) if err != nil { if apiErr, ok := err.(*clerk.APIErrorResponse); ok { // Access the API errors and additional information apiErr.TraceID apiErr.Error() apiErr.Response.RawJSON } } // List all organizations, limit results to one. params := &organization.ListParams{} params.Limit = clerk.Int64(1) list, err := organization.List(ctx, params) if err != nil { // handle the error } if list.TotalCount > 0 { // Get the first organization in the list org = list.Organizations[0] } } ``` -------------------------------- ### Create Domain with Pointer Parameters Source: https://github.com/clerk/clerk-sdk-go/blob/v2/v2_migration_guide.md Use helper functions like clerk.String and clerk.Bool to cast values to pointers for API operation parameters in v2. ```go domain.Create(context.Background(), &domain.CreateParams{ Name: clerk.String("clerk.com"), IsSatellite: clerk.Bool(true), }) ``` -------------------------------- ### Configure Clerk API Key and Use SDK without Client Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Set your Clerk API key and perform CRUD operations on resources using the SDK without an explicit client. Requires `context.Context` for each operation. ```go import ( "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/$resource$" ) // Each operation requires a context.Context as the first argument. ctx := context.Background() // Set the API key clerk.SetKey("sk_live_XXX") // Create resource, err := $resource$.Create(ctx, &$resource$.CreateParams{}) // Get resource, err := $resource$.Get(ctx, id) // Update resource, err := $resource$.Update(ctx, id, &$resource$.UpdateParams{}) // Delete resource, err := $resource$.Delete(ctx, id) // List list, err := $resource$.List(ctx, &$resource$.ListParams{}) for _, resource := range list.$Resource$s { // do something with the resource } ``` -------------------------------- ### v2 Usage Without Client: Create and List Organizations Source: https://github.com/clerk/clerk-sdk-go/blob/v2/v2_migration_guide.md Shows how to create and list organizations in v2 of the Clerk Go SDK using the global client pattern, suitable for projects with a single API key. ```go import ( "context" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/organization" ) func main() { ctx := context.Background() clerk.SetKey("sk_live_XXX") // Create an organization org, err := organization.Create(ctx, &organization.CreateParams{ Name: clerk.String("Acme Inc"), }) if err != nil { if apiErr, ok := err.(*clerk.APIErrorResponse); ok { // Access the API errors and additional information apiErr.TraceID apiErr.Error() apiErr.Response.RawJSON } } // List all organizations, limit results to one. params := &organization.ListParams{} params.Limit = clerk.Int64(1) list, err := organization.List(ctx, params) if err != nil { // handle the error } if list.TotalCount > 0 { // Get the first organization in the list org = list.Organizations[0] } } ``` -------------------------------- ### Manage Waitlist Entries with Clerk SDK Go Source: https://context7.com/clerk/clerk-sdk-go/llms.txt The `waitlistentry` package manages a waitlist for controlled onboarding. It supports single and bulk creation, and listing entries with optional filters. Ensure `clerk.SetKey` is called. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/waitlistentry" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // Add a single entry entry, err := waitlistentry.Create(ctx, &waitlistentry.CreateParams{ EmailAddress: "eve@example.com", Notify: clerk.Bool(true), }) if err != nil { log.Fatal(err) } fmt.Println("Entry ID:", entry.ID, "Status:", entry.Status) // Bulk create bulk, err := waitlistentry.BulkCreate(ctx, &waitlistentry.BulkCreateParams{ WaitlistEntries: []*waitlistentry.CreateParams{ {EmailAddress: "f@example.com"}, {EmailAddress: "g@example.com"}, }, }) if err != nil { log.Fatal(err) } fmt.Printf("Added %d entries\n", len(bulk.WaitlistEntries)) // List list, err := waitlistentry.List(ctx, &waitlistentry.ListParams{ Statuses: []string{"pending"}, ListParams: clerk.ListParams{Limit: clerk.Int64(50)}, }) if err != nil { log.Fatal(err) } for _, e := range list.WaitlistEntries { fmt.Println(" -", e.EmailAddress) } } ``` -------------------------------- ### Implement Custom Backend for Clerk Client Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Replace the default Backend with a custom implementation for advanced control over API requests and responses. Ensure the custom Backend implements the Backend interface. ```go func TestWithCustomBackend(t *testing.T) { client := user.NewClient(&clerk.ClientConfig{}) client.Backend = &customBackend{} } type customBackend struct {} // Implement the Backend interface func (b *customBackend) Call(ctx context.Context, r *clerk.APIRequest, reader *clerk.ResponseReader) error { // Construct a clerk.APIResponse and use the reader's Read method. reader.Read(&clerk.APIResponse{}) } ``` -------------------------------- ### Global Configuration: Set Clerk Key and Backend Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Configure the Clerk SDK globally by setting the secret key or a custom HTTP backend with a specific timeout. ```go package main import ( "net/http" "time" "github.com/clerk/clerk-sdk-go/v2" ) func main() { // Simple setup: set the secret key globally. clerk.SetKey("sk_live_XXX") // Advanced setup: custom HTTP client with a longer timeout. clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ HTTPClient: &http.Client{Timeout: 10 * time.Second}, Key: clerk.String("sk_live_XXX"), })) } ``` -------------------------------- ### Global Configuration: clerk.SetKey / clerk.SetBackend Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Demonstrates how to set the Clerk secret key globally or configure a custom HTTP backend for the SDK. ```APIDOC ## Global Configuration: `clerk.SetKey` / `clerk.SetBackend` `clerk.SetKey` sets the Clerk secret key at the package level. `clerk.SetBackend` replaces the default HTTP backend — useful for custom HTTP clients, proxies, or tests. ```go package main import ( "net/http" "time" "github.com/clerk/clerk-sdk-go/v2" ) func main() { // Simple setup: set the secret key globally. clerk.SetKey("sk_live_XXX") // Advanced setup: custom HTTP client with a longer timeout. clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ HTTPClient: &http.Client{Timeout: 10 * time.Second}, Key: clerk.String("sk_live_XXX"), })) } ``` ``` -------------------------------- ### Implement Clerk HTTP Authentication Middleware in Go Source: https://github.com/clerk/clerk-sdk-go/blob/v2/UPGRADING.md Demonstrates how to protect a route using the new http.RequireHeaderAuthorization middleware and access session claims from the request context using clerk.SessionClaimsFromContext. ```diff // Protect a route with Clerk authentication middleware. // Error handling is omitted. mux := http.NewServeMux() - client, err := clerk.NewClient("sk_live_XXX") - mux.Handle("/session", clerk.RequireSessionV2(client)(http.HandlerFunc(handleSession))) + clerk.SetKey("sk_live_XXX") + mux.Handle("/session", http.RequireHeaderAuthorization()(http.HandlerFunc(handleSession))) http.ListenAndServe(":3000", mux) func handleSession(w http.ResponseWriter, r *http.Request) { - sessionClaims, ok := clerk.SessionFromContext(r.Context()) + sessionClaims, ok := clerk.SessionClaimsFromContext(r.Context()) if ok { // claims contain session information } else { // there is no active session (non-authenticated user) } } ``` -------------------------------- ### Manage API Keys with Clerk SDK for Go Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Use this snippet to create, verify, list, and revoke machine-to-machine API keys. Ensure the Clerk SDK is imported and the API key is set. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/apikey" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // Create an API key for a machine user key, err := apikey.Create(ctx, &apikey.CreateParams{ Name: clerk.String("CI Deploy Key"), Subject: clerk.String("machine_2abc"), Scopes: []string{"deployments:write"}, SecondsUntilExpiration: clerk.Int64(86400), // 24h }) if err != nil { log.Fatal(err) } fmt.Println("Key ID:", key.ID) fmt.Println("Secret:", key.Secret) // only shown once on creation // Verify key by secret verified, err := apikey.Verify(ctx, &apikey.VerifyParams{ Secret: key.Secret, }) if err != nil { log.Fatal(err) } fmt.Println("Key valid, subject:", verified.Subject) // List keys for a subject list, err := apikey.List(ctx, &apikey.ListParams{ Subject: clerk.String("machine_2abc"), }) if err != nil { log.Fatal(err) } fmt.Printf("%d active keys\n", len(list.Data)) // Revoke apikey.Revoke(ctx, key.ID, &apikey.RevokeParams{ RevocationReason: clerk.String("key rotated"), }) } ``` -------------------------------- ### Manage Invitations with Clerk SDK Go Source: https://context7.com/clerk/clerk-sdk-go/llms.txt The `invitation` package handles email invitations, including single and bulk creation, revocation, and listing. Ensure `clerk.SetKey` is called with your Clerk API key. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/invitation" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // Create a single invitation inv, err := invitation.Create(ctx, &invitation.CreateParams{ EmailAddress: "bob@example.com", RedirectURL: clerk.String("https://myapp.example.com/accept"), Notify: clerk.Bool(true), ExpiresInDays: clerk.Int64(7), }) if err != nil { log.Fatal(err) } fmt.Println("Invitation ID:", inv.ID) // Bulk create bulk, err := invitation.BulkCreate(ctx, &invitation.BulkCreateParams{ Invitations: []*invitation.CreateParams{ {EmailAddress: "c@example.com", Notify: clerk.Bool(false)}, {EmailAddress: "d@example.com", Notify: clerk.Bool(false)}, }, }) if err != nil { log.Fatal(err) } fmt.Printf("Bulk created: %d invitations\n", len(bulk.Invitations)) // Revoke invitation.Revoke(ctx, inv.ID) // List pending invitations list, err := invitation.List(ctx, &invitation.ListParams{ Statuses: []string{"pending"}, }) if err != nil { log.Fatal(err) } fmt.Printf("Pending: %d\n", list.TotalCount) } ``` -------------------------------- ### Manage User Sessions with Go SDK Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Use the session package to list active sessions for a user, revoke sessions, and create custom JWT tokens from templates. Ensure Clerk API key is set. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/session" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // List active sessions for a user list, err := session.List(ctx, &session.ListParams{ UserID: clerk.String("user_2abc123"), Status: clerk.String("active"), }) if err != nil { log.Fatal(err) } for _, s := range list.Sessions { fmt.Println("Session:", s.ID, "Status:", s.Status) } // Revoke a session revoked, err := session.Revoke(ctx, &session.RevokeParams{ ID: "sess_2abc123", }) if err != nil { log.Fatal(err) } fmt.Println("Revoked:", revoked.ID) // Create a custom token from a JWT template tok, err := session.CreateToken(ctx, &session.CreateTokenParams{ ID: "sess_2abc123", TemplateName: "my-template", }) if err != nil { log.Fatal(err) } fmt.Println("Token:", tok.JWT) } ``` -------------------------------- ### Clerk SDK Pointer Helper Functions Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Illustrates the use of clerk.String, clerk.Int64, and clerk.Bool helper functions to create pointer types for optional parameters, offering a more concise alternative to verbose '&' expressions. ```go import "github.com/clerk/clerk-sdk-go/v2" // Without helpers (verbose) name := "Alice" params := &user.UpdateParams{FirstName: &name} // With helpers (idiomatic) params = &user.UpdateParams{ FirstName: clerk.String("Alice"), Limit: clerk.Int64(10), DeleteSelf: clerk.Bool(false), } ``` -------------------------------- ### Manage Clerk Organizations with Go SDK Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Use the organization package to create, fetch, list, and delete organizations. `GetWithParams` can include member counts. Ensure Clerk API key is set. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/organization" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // Create org, err := organization.Create(ctx, &organization.CreateParams{ Name: clerk.String("Acme Corp"), Slug: clerk.String("acme"), CreatedBy: clerk.String("user_2abc123"), PublicMetadata: clerk.JSONRawMessage([]byte(`{"tier":"enterprise"}`)), }) if err != nil { log.Fatal(err) } fmt.Println("Org ID:", org.ID) // Fetch with member count orgWithCount, err := organization.GetWithParams(ctx, org.ID, &organization.GetParams{ IncludeMembersCount: clerk.Bool(true), }) if err != nil { log.Fatal(err) } fmt.Println("Members:", *orgWithCount.MembersCount) // List organizations list, err := organization.List(ctx, &organization.ListParams{ ListParams: clerk.ListParams{Limit: clerk.Int64(10)}, Query: clerk.String("acme"), }) if err != nil { log.Fatal(err) } for _, o := range list.Data { fmt.Println(" -", o.Slug) } // Delete organization.Delete(ctx, org.ID) } ``` -------------------------------- ### Use httptest.Server with Clerk Client Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Integrate the Clerk client with a httptest.Server for mocking API responses during testing. Ensure to close the server and set the client URL. ```go func TestWithMockServer(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Write the response. })) defer ts.Close() config := &clerk.ClientConfig{} config.HTTPClient = ts.Client() config.URL = &ts.URL client := user.NewClient(config) } ``` -------------------------------- ### Available Middleware Options Source: https://github.com/clerk/clerk-sdk-go/blob/v2/UPGRADING.md Lists the renamed and new available middleware options in v2 of the Clerk Go SDK. ```APIDOC ## Available Middleware Options ### Description Lists the renamed and new available middleware options in v2 of the Clerk Go SDK. ### Method N/A (Conceptual changes) ### Endpoint N/A ### Parameters N/A ### Request Example ```go // Renamed options: // - WithAuthorizedParty(...string) -> AuthorizedPartyMatches(...string) // - WithLeeway(time.Duration) -> Leeway(time.Duration) // - WithJWTVerificationKey(string) -> JSONWebKey(string) // - WithSatelliteDomain(string) -> Satellite(string) // - WithProxyURL(string) -> ProxyURL(string) // - WithCustomClaims(interface{}) -> CustomClaimsConstructor(func(context.Context) any) // New options in v2: // - AuthorizedParty(func(string) bool) // - JWKSClient(*jwks.Client) ``` ### Response N/A ``` -------------------------------- ### Manage Organization Memberships with Go SDK Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Use the organizationmembership package to add, update roles, list, and remove members from organizations. Requires organization and user IDs. Ensure Clerk API key is set. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/organizationmembership" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() orgID := "org_2abc" userID := "user_2xyz" // Add member m, err := organizationmembership.Create(ctx, &organizationmembership.CreateParams{ OrganizationID: orgID, UserID: clerk.String(userID), Role: clerk.String("org:member"), }) if err != nil { log.Fatal(err) } fmt.Println("Member role:", m.Role) // Promote to admin m, err = organizationmembership.Update(ctx, &organizationmembership.UpdateParams{ OrganizationID: orgID, UserID: userID, Role: clerk.String("org:admin"), }) if err != nil { log.Fatal(err) } fmt.Println("Updated role:", m.Role) // List members list, err := organizationmembership.List(ctx, &organizationmembership.ListParams{ OrganizationID: orgID, ListParams: clerk.ListParams{Limit: clerk.Int64(20)}, }) if err != nil { log.Fatal(err) } fmt.Printf("%d members\n", list.TotalCount) // Remove member organizationmembership.Delete(ctx, &organizationmembership.DeleteParams{ OrganizationID: orgID, UserID: userID, }) } ``` -------------------------------- ### Waitlist Entries API Source: https://context7.com/clerk/clerk-sdk-go/llms.txt The `waitlistentry` package manages a waitlist for controlled onboarding, supporting single and bulk creation. ```APIDOC ## Waitlist Entries API: `waitlistentry.Create`, `waitlistentry.BulkCreate`, `waitlistentry.List` The `waitlistentry` package manages a waitlist for controlled onboarding, supporting single and bulk creation. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/waitlistentry" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // Add a single entry entry, err := waitlistentry.Create(ctx, &waitlistentry.CreateParams{ EmailAddress: "eve@example.com", Notify: clerk.Bool(true), }) if err != nil { log.Fatal(err) } fmt.Println("Entry ID:", entry.ID, "Status:", entry.Status) // Bulk create bulk, err := waitlistentry.BulkCreate(ctx, &waitlistentry.BulkCreateParams{ WaitlistEntries: []*waitlistentry.CreateParams{ {EmailAddress: "f@example.com"}, {EmailAddress: "g@example.com"}, }, }) if err != nil { log.Fatal(err) } fmt.Printf("Added %d entries\n", len(bulk.WaitlistEntries)) // List list, err := waitlistentry.List(ctx, &waitlistentry.ListParams{ Statuses: []string{"pending"}, ListParams: clerk.ListParams{Limit: clerk.Int64(50)}, }) if err != nil { log.Fatal(err) } for _, e := range list.WaitlistEntries { fmt.Println(" -", e.EmailAddress) } } ``` ``` -------------------------------- ### Migrate Clerk Go SDK Middleware Options Source: https://github.com/clerk/clerk-sdk-go/blob/v2/UPGRADING.md Shows the renaming of various middleware options from v1 to v2 of the Clerk Go SDK. Some options have new functionalities or parameter types. ```diff - WithAuthorizedParty(...string) + AuthorizedPartyMatches(...string) - WithLeeway(time.Duration) + Leeway(time.Duration) - WithJWTVerificationKey(string) + JSONWebKey(string) - WithSatelliteDomain(string) + Satellite(string) - WithProxyURL(string) + ProxyURL(string) - WithCustomClaims(interface{}) + CustomClaimsConstructor(func(context.Context) any) ``` -------------------------------- ### Mock JWT Generation and Verification Test Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Demonstrates generating a signed JWT with a known key and verifying it using clerktest.GenerateJWT and a controllable clock. This is useful for testing time-sensitive JWT flows. ```go func TestJWTVerification(t *testing.T) { now := time.Now().UTC() clock := clerktest.NewClockAt(now) // Generate a signed JWT with known key token, pubKey := clerktest.GenerateJWT(t, map[string]any{ "sub": "user_2abc", "iss": "https://clerk.example.com", "exp": now.Add(time.Hour).Unix(), "iat": now.Unix(), "sid": "sess_abc", }, "kid_test") jwk, err := clerk.JSONWebKeyFromPublicKey(pubKey) require.NoError(t, err) claims, err := jwt.Verify(context.Background(), &jwt.VerifyParams{ Token: token, JWK: jwk, Clock: clock, Leeway: time.Second, }) require.NoError(t, err) require.Equal(t, "user_2abc", claims.Subject) // Simulate clock advancing past expiry clock.Advance(2 * time.Hour) _, err = jwt.Verify(context.Background(), &jwt.VerifyParams{ Token: token, JWK: jwk, Clock: clock, }) require.Error(t, err) // token expired } ``` -------------------------------- ### Invitations API Source: https://context7.com/clerk/clerk-sdk-go/llms.txt The `invitation` package manages email invitations to a Clerk instance, including bulk creation and revocation. ```APIDOC ## Invitations API: `invitation.Create`, `invitation.BulkCreate`, `invitation.Revoke`, `invitation.List` The `invitation` package manages email invitations to a Clerk instance, including bulk creation and revocation. ```go package main import ( "context" "fmt" "log" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/invitation" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() // Create a single invitation inv, err := invitation.Create(ctx, &invitation.CreateParams{ EmailAddress: "bob@example.com", RedirectURL: clerk.String("https://myapp.example.com/accept"), Notify: clerk.Bool(true), ExpiresInDays: clerk.Int64(7), }) if err != nil { log.Fatal(err) } fmt.Println("Invitation ID:", inv.ID) // Bulk create bulk, err := invitation.BulkCreate(ctx, &invitation.BulkCreateParams{ Invitations: []*invitation.CreateParams{ {EmailAddress: "c@example.com", Notify: clerk.Bool(false)}, {EmailAddress: "d@example.com", Notify: clerk.Bool(false)}, }, }) if err != nil { log.Fatal(err) } fmt.Printf("Bulk created: %d invitations\n", len(bulk.Invitations)) // Revoke invitation.Revoke(ctx, inv.ID) // List pending invitations list, err := invitation.List(ctx, &invitation.ListParams{ Statuses: []string{"pending"}, }) if err != nil { log.Fatal(err) } fmt.Printf("Pending: %d\n", list.TotalCount) } ``` ``` -------------------------------- ### Check Session Permissions and Roles in Go Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Use `SessionClaims.HasPermission` to gate access in handlers. `SessionClaims.HasRole` is less preferred. Claims are populated by middleware or `jwt.Verify`. ```go func handler(w http.ResponseWriter, r *http.Request) { claims, ok := clerk.SessionClaimsFromContext(r.Context()) if !ok { http.Error(w, "unauthorized", http.StatusUnauthorized) return } // Permission check (recommended) if !claims.HasPermission("org:documents:delete") { http.Error(w, "forbidden", http.StatusForbidden) return } // Role check (less preferred) if claims.HasRole("org:admin") { fmt.Fprintln(w, "admin access granted") } fmt.Fprintf(w, "user=%s session=%s org=%s", claims.Subject, claims.SessionID, claims.ActiveOrganizationID) } ``` -------------------------------- ### v2 Generic List Operation Response Structure Source: https://github.com/clerk/clerk-sdk-go/blob/v2/v2_migration_guide.md Illustrates the common response structure for list operations in v2 of the Clerk Go SDK, which includes total count and a slice of resources. ```go import ( "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/$resource$" ) ctx := context.Background() list, err := $resource$.List(ctx, &$resource$.ListParams{}) // If $resource$ was user, the following line would read // fmt.Println(list.TotalCount, list.Users) fmt.Println(list.TotalCount, list.$resource$s) ``` -------------------------------- ### Set API Key in Clerk Go SDK v2 Source: https://github.com/clerk/clerk-sdk-go/blob/v2/UPGRADING.md Update how the API key is set for the Clerk Go SDK. This replaces the client initialization with a global key setting. ```go clerk.SetKey("sk_live_XXX") ``` -------------------------------- ### Mock HTTP Client Transport for Testing Source: https://github.com/clerk/clerk-sdk-go/blob/v2/README.md Stub out the HTTP client's transport to mock Clerk SDK requests in tests. This involves creating a custom `http.RoundTripper`. ```go func TestWithCustomTransport(t *testing.T) { clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ HTTPClient: &http.Client{ Transport: &mockRoundTripper{}, }, })) } type mockRoundTripper struct {} // Implement the http.RoundTripper interface. func (r *mockRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { // Construct and return the http.Response. } ``` -------------------------------- ### Verify and Decode JWTs with Clerk SDK Go Source: https://context7.com/clerk/clerk-sdk-go/llms.txt Use `jwt.Decode` for header inspection and `jwt.Verify` for full cryptographic verification of Clerk session tokens. `Verify` automatically fetches JWKs and supports custom claims and authorized party validation. ```go package main import ( "context" "fmt" "log" "time" "github.com/clerk/clerk-sdk-go/v2" "github.com/clerk/clerk-sdk-go/v2/jwt" ) func main() { clerk.SetKey("sk_live_XXX") ctx := context.Background() rawToken := "eyJhbGciOiJSUzI1NiIsImtpZCI6Imluc18..." // from Authorization header // Decode without verification (for inspecting headers) unverified, err := jwt.Decode(ctx, &jwt.DecodeParams{Token: rawToken}) if err != nil { log.Fatal(err) } fmt.Println("Key ID:", unverified.KeyID) // Fully verify the token claims, err := jwt.Verify(ctx, &jwt.VerifyParams{ Token: rawToken, Leeway: 5 * time.Second, // Custom claims CustomClaimsConstructor: func(_ context.Context) any { return &struct { Plan string `json:"plan"` }{} }, // Validate authorized party AuthorizedPartyHandler: func(azp string) bool { return azp == "https://myapp.example.com" }, }) if err != nil { log.Fatal(err) } fmt.Println("User ID:", claims.Subject) fmt.Println("Session ID:", claims.SessionID) fmt.Println("Org ID:", claims.ActiveOrganizationID) fmt.Println("Has permission:", claims.HasPermission("org:billing:read")) fmt.Println("Custom claims:", claims.Custom) } ```