├── .github └── workflows │ ├── ci.yml │ └── semgrep.yml ├── .gitignore ├── CHANGELOG.md ├── CODEOWNERS ├── LICENSE ├── README.md ├── UPGRADING.md ├── actor_token.go ├── actortoken ├── actor_token_test.go ├── api.go └── client.go ├── allowlist_identifier.go ├── allowlistidentifier ├── allowlist_identifier_test.go ├── api.go └── client.go ├── blocklist_identifier.go ├── blocklistidentifier ├── api.go ├── client.go └── client_test.go ├── clerk.go ├── clerk_test.go ├── clerktest └── clerktest.go ├── client.go ├── client ├── api.go ├── client.go └── client_test.go ├── cmd └── gen │ └── main.go ├── deleted_resource.go ├── domain.go ├── domain ├── api.go ├── client.go └── domain_test.go ├── email_address.go ├── emailaddress ├── api.go ├── client.go └── client_test.go ├── go.mod ├── go.sum ├── http ├── middleware.go ├── middleware_test.go └── response.go ├── instance_settings.go ├── instancesettings ├── api.go ├── client.go └── client_test.go ├── invitation.go ├── invitation ├── api.go ├── client.go └── invitation_test.go ├── jwk.go ├── jwks ├── api.go ├── client.go └── jwk_test.go ├── jwt.go ├── jwt ├── jwt.go └── jwt_test.go ├── jwt_template.go ├── jwt_test.go ├── jwttemplate ├── api.go ├── client.go └── client_test.go ├── oauth_access_token.go ├── oauth_application.go ├── oauthapplication ├── api.go ├── client.go └── client_test.go ├── organization.go ├── organization ├── api.go ├── client.go └── client_test.go ├── organization_domain.go ├── organization_invitation.go ├── organization_membership.go ├── organizationdomain ├── api.go ├── client.go └── client_test.go ├── organizationinvitation ├── api.go ├── client.go └── client_test.go ├── organizationmembership ├── api.go ├── client.go └── client_test.go ├── phone_number.go ├── phonenumber ├── api.go ├── client.go └── client_test.go ├── proxy_check.go ├── proxycheck ├── api.go ├── client.go └── client_test.go ├── redirect_url.go ├── redirecturl ├── api.go ├── client.go └── client_test.go ├── saml_connection.go ├── samlconnection ├── api.go ├── client.go └── client_test.go ├── session.go ├── session ├── api.go ├── client.go └── client_test.go ├── session_reverification.go ├── session_token.go ├── sign_in_token.go ├── signintoken ├── api.go ├── client.go └── sign_in_tokens_test.go ├── svix_webhook.go ├── svixwebhook ├── api.go ├── client.go └── client_test.go ├── template.go ├── template ├── api.go ├── client.go └── client_test.go ├── testing_token.go ├── testingtoken ├── api.go ├── client.go └── client_test.go ├── totp.go ├── user.go ├── user ├── api.go ├── client.go └── client_test.go ├── v2_migration_guide.md ├── waitlist_entries.go └── waitlistentry ├── api.go ├── client.go └── waitlistentry_test.go /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - $default-branch 8 | - v2 9 | 10 | jobs: 11 | lint: 12 | name: Lint 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Setup go 17 | uses: actions/setup-go@v4 18 | with: 19 | go-version: "1.21" 20 | - name: Format 21 | run: diff -u <(echo -n) <(gofmt -d -s .) 22 | - name: Vet 23 | run: go vet ./... 24 | - name: Run linter 25 | uses: golangci/golangci-lint-action@v3 26 | test: 27 | name: "Test: go v${{ matrix.go-version }}" 28 | strategy: 29 | matrix: 30 | go-version: 31 | - "1.19" 32 | - "1.20" 33 | - "1.21" 34 | runs-on: ubuntu-latest 35 | steps: 36 | - uses: actions/checkout@v4 37 | - name: Setup go 38 | uses: actions/setup-go@v4 39 | with: 40 | go-version: ${{ matrix.go-version }} 41 | - name: Run tests 42 | run: go test -v -race ./... 43 | -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | name: Semgrep 2 | on: 3 | workflow_dispatch: {} 4 | pull_request: {} 5 | push: 6 | branches: 7 | - main 8 | - v2 9 | paths: 10 | - .github/workflows/semgrep.yml 11 | schedule: 12 | # random HH:MM to avoid a load spike on GitHub Actions at 00:00 13 | - cron: '28 3 * * *' 14 | jobs: 15 | semgrep: 16 | name: semgrep/ci 17 | runs-on: ubuntu-22.04 18 | env: 19 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 20 | container: 21 | image: returntocorp/semgrep 22 | if: (github.actor != 'dependabot[bot]') 23 | steps: 24 | - uses: actions/checkout@v3 25 | - run: semgrep ci 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac 2 | .DS_Store 3 | 4 | # IDEs 5 | .vscode 6 | .idea 7 | 8 | # Go 9 | coverage.out -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Next release 4 | 5 | ## 2.3.1 6 | 7 | - Fix parsing the org claims in the new JWT session token version. 8 | 9 | ## 2.3.0 10 | 11 | - Add support for the OAuth Applications API. Added the oauthapplication package for API operations and a clerk.OAuthApplication type. 12 | - Add support for multiple invitation templates with the `TemplateSlug` field in `invitation.Create`. 13 | - Add support for listing and creating waitlist entries with the `waitlistentry.List` and `waitlistentry.Create` methods. 14 | - Add support for fetching an organization with its members count, via a new `organizations.GetWithParams` method. 15 | - Add support for session reverification with `SessionClaims.NeedsReverification()`, `SessionReverificationPolicy`, predefined policies like `SessionReverificationStrict`, and middleware via `http.NeedsSessionReverification()`. 16 | - Handles new JWT session token version 17 | 18 | ## 2.2.0 19 | 20 | - Add support for bulk invitation creation with the `invitation.BulkCreate` method. 21 | - Add `NameQuery` to `user.ListParams`. 22 | 23 | ## 2.1.1 24 | 25 | - Add `EmailAddressQuery`, `PhoneNumberQuery` and `UsernameQuery` to `user.ListParams`. 26 | - Add support for `missing_member_with_elevated_permissions` checks to the `organization.List` method. 27 | 28 | ## 2.1.0 29 | 30 | - Add support for sign in tokens API operations. 31 | - Add `LegalAcceptedAt` to `User` and the ability to `SkipLegalChecks` when creating or updating a `User`. 32 | - Add `EmailAddressQuery`, `PhoneNumberQuery` and `UsernameQuery` to `user.ListParams`. 33 | - Add `RoleName` field to `OrganizationInvitation` and `OrganizationMembership`. 34 | - Add support for deleting a user's external account via the `user.DeleteExternalAccount` method. 35 | - Add support for listing all organization invitations for a user with the `user.ListOrganizationInvitations` method. 36 | - Add support for listing all organization invitations for an instance with the `organizationinvitation.ListFromInstance` method. 37 | - Add `RequestingUserID` parameter to `organizationinvitation.RevokeParams`. 38 | - Update go-jose dependency to v3.0.3. 39 | 40 | ## 2.0.9 41 | 42 | ## 2.0.4 43 | 44 | - Add `IgnoreDotsForGmailAddresses` field to `InstanceRestrictions` and `instancesettings.UpdateRestrictionsParams` (#293). 45 | 46 | ## 2.0.0 47 | 48 | - Initial version for changelog. 49 | - Complete rewrite, new library API. 50 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @clerk/engineering-backend 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Clerk Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /actor_token.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type ActorToken struct { 6 | APIResource 7 | Object string `json:"object"` 8 | ID string `json:"id"` 9 | UserID string `json:"user_id"` 10 | Actor json.RawMessage `json:"actor"` 11 | Token string `json:"token,omitempty"` 12 | URL *string `json:"url,omitempty"` 13 | Status string `json:"status"` 14 | CreatedAt int64 `json:"created_at"` 15 | UpdatedAt int64 `json:"updated_at"` 16 | } 17 | -------------------------------------------------------------------------------- /actortoken/actor_token_test.go: -------------------------------------------------------------------------------- 1 | package actortoken 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestActorTokenCreate(t *testing.T) { 16 | userID := "usr_123" 17 | id := "act_123" 18 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 19 | HTTPClient: &http.Client{ 20 | Transport: &clerktest.RoundTripper{ 21 | T: t, 22 | In: json.RawMessage(fmt.Sprintf(`{"user_id":"%s"}`, userID)), 23 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","user_id":"%s"}`, id, userID)), 24 | Path: "/v1/actor_tokens", 25 | Method: http.MethodPost, 26 | }, 27 | }, 28 | })) 29 | 30 | actorToken, err := Create(context.Background(), &CreateParams{ 31 | UserID: clerk.String(userID), 32 | }) 33 | require.NoError(t, err) 34 | require.Equal(t, id, actorToken.ID) 35 | require.Equal(t, userID, actorToken.UserID) 36 | } 37 | 38 | func TestActorTokenCreate_Error(t *testing.T) { 39 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 40 | HTTPClient: &http.Client{ 41 | Transport: &clerktest.RoundTripper{ 42 | T: t, 43 | Status: http.StatusBadRequest, 44 | Out: json.RawMessage(`{ 45 | "errors":[{ 46 | "code":"create-error-code" 47 | }], 48 | "clerk_trace_id":"create-trace-id" 49 | }`), 50 | }, 51 | }, 52 | })) 53 | 54 | _, err := Create(context.Background(), &CreateParams{}) 55 | require.Error(t, err) 56 | apiErr, ok := err.(*clerk.APIErrorResponse) 57 | require.True(t, ok) 58 | require.Equal(t, "create-trace-id", apiErr.TraceID) 59 | require.Equal(t, 1, len(apiErr.Errors)) 60 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 61 | } 62 | 63 | func TestActorTokenRevoke(t *testing.T) { 64 | id := "act_456" 65 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 66 | HTTPClient: &http.Client{ 67 | Transport: &clerktest.RoundTripper{ 68 | T: t, 69 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","status":"revoked"}`, id)), 70 | Path: fmt.Sprintf("/v1/actor_tokens/%s/revoke", id), 71 | Method: http.MethodPost, 72 | }, 73 | }, 74 | })) 75 | 76 | actorToken, err := Revoke(context.Background(), id) 77 | require.NoError(t, err) 78 | require.Equal(t, id, actorToken.ID) 79 | require.Equal(t, "revoked", actorToken.Status) 80 | } 81 | -------------------------------------------------------------------------------- /actortoken/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package actortoken 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new actor token. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.ActorToken, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Revoke revokes a pending actor token. 17 | func Revoke(ctx context.Context, id string) (*clerk.ActorToken, error) { 18 | return getClient().Revoke(ctx, id) 19 | } 20 | 21 | func getClient() *Client { 22 | return &Client{ 23 | Backend: clerk.GetBackend(), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /actortoken/client.go: -------------------------------------------------------------------------------- 1 | // Package actortoken provides the Actor Tokens API. 2 | package actortoken 3 | 4 | import ( 5 | "context" 6 | "encoding/json" 7 | "net/http" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/actor_tokens" 15 | 16 | // Client is used to invoke the Actor Tokens API. 17 | type Client struct { 18 | Backend clerk.Backend 19 | } 20 | 21 | func NewClient(config *clerk.ClientConfig) *Client { 22 | return &Client{ 23 | Backend: clerk.NewBackend(&config.BackendConfig), 24 | } 25 | } 26 | 27 | type CreateParams struct { 28 | clerk.APIParams 29 | UserID *string `json:"user_id,omitempty"` 30 | Actor json.RawMessage `json:"actor,omitempty"` 31 | ExpiresInSeconds *int64 `json:"expires_in_seconds,omitempty"` 32 | SessionMaxDurationInSeconds *int64 `json:"session_max_duration_in_seconds,omitempty"` 33 | } 34 | 35 | // Create creates a new actor token. 36 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.ActorToken, error) { 37 | req := clerk.NewAPIRequest(http.MethodPost, path) 38 | req.SetParams(params) 39 | token := &clerk.ActorToken{} 40 | err := c.Backend.Call(ctx, req, token) 41 | return token, err 42 | } 43 | 44 | // Revoke revokes a pending actor token. 45 | func (c *Client) Revoke(ctx context.Context, id string) (*clerk.ActorToken, error) { 46 | token := &clerk.ActorToken{} 47 | path, err := clerk.JoinPath(path, id, "revoke") 48 | if err != nil { 49 | return token, err 50 | } 51 | req := clerk.NewAPIRequest(http.MethodPost, path) 52 | err = c.Backend.Call(ctx, req, token) 53 | return token, err 54 | } 55 | -------------------------------------------------------------------------------- /allowlist_identifier.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type AllowlistIdentifier struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | Identifier string `json:"identifier"` 8 | IdentifierType string `json:"identifier_type"` 9 | InvitationID *string `json:"invitation_id,omitempty"` 10 | CreatedAt int64 `json:"created_at"` 11 | UpdatedAt int64 `json:"updated_at"` 12 | } 13 | 14 | type AllowlistIdentifierList struct { 15 | APIResource 16 | AllowlistIdentifiers []*AllowlistIdentifier `json:"data"` 17 | TotalCount int64 `json:"total_count"` 18 | } 19 | -------------------------------------------------------------------------------- /allowlistidentifier/allowlist_identifier_test.go: -------------------------------------------------------------------------------- 1 | package allowlistidentifier 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestAllowlistIdentifierCreate(t *testing.T) { 16 | identifier := "foo@bar.com" 17 | id := "alid_123" 18 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 19 | HTTPClient: &http.Client{ 20 | Transport: &clerktest.RoundTripper{ 21 | T: t, 22 | In: json.RawMessage(fmt.Sprintf(`{"identifier":"%s"}`, identifier)), 23 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","identifier":"%s"}`, id, identifier)), 24 | Method: http.MethodPost, 25 | Path: "/v1/allowlist_identifiers", 26 | }, 27 | }, 28 | })) 29 | 30 | allowlistIdentifier, err := Create(context.Background(), &CreateParams{ 31 | Identifier: clerk.String(identifier), 32 | }) 33 | require.NoError(t, err) 34 | require.Equal(t, id, allowlistIdentifier.ID) 35 | require.Equal(t, identifier, allowlistIdentifier.Identifier) 36 | } 37 | 38 | func TestAllowlistIdentifierCreate_Error(t *testing.T) { 39 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 40 | HTTPClient: &http.Client{ 41 | Transport: &clerktest.RoundTripper{ 42 | T: t, 43 | Status: http.StatusBadRequest, 44 | Out: json.RawMessage(`{ 45 | "errors":[{ 46 | "code":"create-error-code" 47 | }], 48 | "clerk_trace_id":"create-trace-id" 49 | }`), 50 | }, 51 | }, 52 | })) 53 | 54 | _, err := Create(context.Background(), &CreateParams{}) 55 | require.Error(t, err) 56 | apiErr, ok := err.(*clerk.APIErrorResponse) 57 | require.True(t, ok) 58 | require.Equal(t, "create-trace-id", apiErr.TraceID) 59 | require.Equal(t, 1, len(apiErr.Errors)) 60 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 61 | } 62 | 63 | func TestAllowlistIdentifierDelete(t *testing.T) { 64 | id := "alid_456" 65 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 66 | HTTPClient: &http.Client{ 67 | Transport: &clerktest.RoundTripper{ 68 | T: t, 69 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), 70 | Method: http.MethodDelete, 71 | Path: "/v1/allowlist_identifiers/" + id, 72 | }, 73 | }, 74 | })) 75 | 76 | allowlistIdentifier, err := Delete(context.Background(), id) 77 | require.NoError(t, err) 78 | require.Equal(t, id, allowlistIdentifier.ID) 79 | require.True(t, allowlistIdentifier.Deleted) 80 | } 81 | 82 | func TestAllowlistIdentifierList(t *testing.T) { 83 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 84 | HTTPClient: &http.Client{ 85 | Transport: &clerktest.RoundTripper{ 86 | T: t, 87 | Out: json.RawMessage(`{ 88 | "data": [{"id":"alid_123","identifier":"foo@bar.com"}], 89 | "total_count": 1 90 | }`), 91 | Method: http.MethodGet, 92 | Path: "/v1/allowlist_identifiers", 93 | }, 94 | }, 95 | })) 96 | 97 | list, err := List(context.Background(), &ListParams{}) 98 | require.NoError(t, err) 99 | require.Equal(t, int64(1), list.TotalCount) 100 | require.Equal(t, 1, len(list.AllowlistIdentifiers)) 101 | require.Equal(t, "alid_123", list.AllowlistIdentifiers[0].ID) 102 | require.Equal(t, "foo@bar.com", list.AllowlistIdentifiers[0].Identifier) 103 | } 104 | -------------------------------------------------------------------------------- /allowlistidentifier/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package allowlistidentifier 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create adds a new identifier to the allowlist. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.AllowlistIdentifier, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Delete removes an identifier from the allowlist. 17 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 18 | return getClient().Delete(ctx, id) 19 | } 20 | 21 | // List returns all the identifiers in the allowlist. 22 | func List(ctx context.Context, params *ListParams) (*clerk.AllowlistIdentifierList, error) { 23 | return getClient().List(ctx, params) 24 | } 25 | 26 | func getClient() *Client { 27 | return &Client{ 28 | Backend: clerk.GetBackend(), 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /allowlistidentifier/client.go: -------------------------------------------------------------------------------- 1 | // Package allowlistidentifier provides the Allowlist Identifiers API. 2 | package allowlistidentifier 3 | 4 | import ( 5 | "context" 6 | "fmt" 7 | "net/http" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/allowlist_identifiers" 15 | 16 | // Client is used to invoke the Allowlist Identifiers API. 17 | type Client struct { 18 | Backend clerk.Backend 19 | } 20 | 21 | func NewClient(config *clerk.ClientConfig) *Client { 22 | return &Client{ 23 | Backend: clerk.NewBackend(&config.BackendConfig), 24 | } 25 | } 26 | 27 | type CreateParams struct { 28 | clerk.APIParams 29 | Identifier *string `json:"identifier,omitempty"` 30 | Notify *bool `json:"notify,omitempty"` 31 | } 32 | 33 | // Create adds a new identifier to the allowlist. 34 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.AllowlistIdentifier, error) { 35 | req := clerk.NewAPIRequest(http.MethodPost, path) 36 | req.SetParams(params) 37 | identifier := &clerk.AllowlistIdentifier{} 38 | err := c.Backend.Call(ctx, req, identifier) 39 | return identifier, err 40 | } 41 | 42 | // Delete removes an identifier from the allowlist. 43 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 44 | path, err := clerk.JoinPath(path, id) 45 | if err != nil { 46 | return nil, err 47 | } 48 | req := clerk.NewAPIRequest(http.MethodDelete, path) 49 | identifier := &clerk.DeletedResource{} 50 | err = c.Backend.Call(ctx, req, identifier) 51 | return identifier, err 52 | } 53 | 54 | type ListParams struct { 55 | clerk.APIParams 56 | } 57 | 58 | // List returns all the identifiers in the allowlist. 59 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.AllowlistIdentifierList, error) { 60 | req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) 61 | list := &clerk.AllowlistIdentifierList{} 62 | err := c.Backend.Call(ctx, req, list) 63 | return list, err 64 | } 65 | -------------------------------------------------------------------------------- /blocklist_identifier.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type BlocklistIdentifier struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | Identifier string `json:"identifier"` 8 | IdentifierType string `json:"identifier_type"` 9 | CreatedAt int64 `json:"created_at"` 10 | UpdatedAt int64 `json:"updated_at"` 11 | } 12 | 13 | type BlocklistIdentifierList struct { 14 | APIResource 15 | BlocklistIdentifiers []*BlocklistIdentifier `json:"data"` 16 | TotalCount int64 `json:"total_count"` 17 | } 18 | -------------------------------------------------------------------------------- /blocklistidentifier/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package blocklistidentifier 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create adds a new identifier to the blocklist. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.BlocklistIdentifier, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Delete removes an identifier from the blocklist. 17 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 18 | return getClient().Delete(ctx, id) 19 | } 20 | 21 | // List returns all the identifiers in the blocklist. 22 | func List(ctx context.Context, params *ListParams) (*clerk.BlocklistIdentifierList, error) { 23 | return getClient().List(ctx, params) 24 | } 25 | 26 | func getClient() *Client { 27 | return &Client{ 28 | Backend: clerk.GetBackend(), 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /blocklistidentifier/client.go: -------------------------------------------------------------------------------- 1 | // Package blocklistidentifier provides the Blocklist Identifiers API. 2 | package blocklistidentifier 3 | 4 | import ( 5 | "context" 6 | "fmt" 7 | "net/http" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/blocklist_identifiers" 15 | 16 | // Client is used to invoke the Blocklist Identifiers API. 17 | type Client struct { 18 | Backend clerk.Backend 19 | } 20 | 21 | func NewClient(config *clerk.ClientConfig) *Client { 22 | return &Client{ 23 | Backend: clerk.NewBackend(&config.BackendConfig), 24 | } 25 | } 26 | 27 | type CreateParams struct { 28 | clerk.APIParams 29 | Identifier *string `json:"identifier,omitempty"` 30 | } 31 | 32 | // Create adds a new identifier to the blocklist. 33 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.BlocklistIdentifier, error) { 34 | req := clerk.NewAPIRequest(http.MethodPost, path) 35 | req.SetParams(params) 36 | identifier := &clerk.BlocklistIdentifier{} 37 | err := c.Backend.Call(ctx, req, identifier) 38 | return identifier, err 39 | } 40 | 41 | // Delete removes an identifier from the blocklist. 42 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 43 | path, err := clerk.JoinPath(path, id) 44 | if err != nil { 45 | return nil, err 46 | } 47 | req := clerk.NewAPIRequest(http.MethodDelete, path) 48 | identifier := &clerk.DeletedResource{} 49 | err = c.Backend.Call(ctx, req, identifier) 50 | return identifier, err 51 | } 52 | 53 | type ListParams struct { 54 | clerk.APIParams 55 | } 56 | 57 | // List returns all the identifiers in the blocklist. 58 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.BlocklistIdentifierList, error) { 59 | req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) 60 | list := &clerk.BlocklistIdentifierList{} 61 | err := c.Backend.Call(ctx, req, list) 62 | return list, err 63 | } 64 | -------------------------------------------------------------------------------- /blocklistidentifier/client_test.go: -------------------------------------------------------------------------------- 1 | package blocklistidentifier 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestBlocklistIdentifierClientCreate(t *testing.T) { 16 | t.Parallel() 17 | identifier := "foo@bar.com" 18 | id := "blid_123" 19 | config := &clerk.ClientConfig{} 20 | config.HTTPClient = &http.Client{ 21 | Transport: &clerktest.RoundTripper{ 22 | T: t, 23 | In: json.RawMessage(fmt.Sprintf(`{"identifier":"%s"}`, identifier)), 24 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","identifier":"%s"}`, id, identifier)), 25 | Method: http.MethodPost, 26 | Path: "/v1/blocklist_identifiers", 27 | }, 28 | } 29 | client := NewClient(config) 30 | blocklistIdentifier, err := client.Create(context.Background(), &CreateParams{ 31 | Identifier: clerk.String(identifier), 32 | }) 33 | require.NoError(t, err) 34 | require.Equal(t, id, blocklistIdentifier.ID) 35 | require.Equal(t, identifier, blocklistIdentifier.Identifier) 36 | } 37 | 38 | func TestBlocklistIdentifierClientCreate_Error(t *testing.T) { 39 | t.Parallel() 40 | config := &clerk.ClientConfig{} 41 | config.HTTPClient = &http.Client{ 42 | Transport: &clerktest.RoundTripper{ 43 | T: t, 44 | Status: http.StatusBadRequest, 45 | Out: json.RawMessage(`{ 46 | "errors":[{ 47 | "code":"create-error-code" 48 | }], 49 | "clerk_trace_id":"create-trace-id" 50 | }`), 51 | }, 52 | } 53 | client := NewClient(config) 54 | _, err := client.Create(context.Background(), &CreateParams{}) 55 | require.Error(t, err) 56 | apiErr, ok := err.(*clerk.APIErrorResponse) 57 | require.True(t, ok) 58 | require.Equal(t, "create-trace-id", apiErr.TraceID) 59 | require.Equal(t, 1, len(apiErr.Errors)) 60 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 61 | } 62 | 63 | func TestBlocklistIdentifierClientDelete(t *testing.T) { 64 | t.Parallel() 65 | id := "blid_456" 66 | config := &clerk.ClientConfig{} 67 | config.HTTPClient = &http.Client{ 68 | Transport: &clerktest.RoundTripper{ 69 | T: t, 70 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), 71 | Method: http.MethodDelete, 72 | Path: "/v1/blocklist_identifiers/" + id, 73 | }, 74 | } 75 | client := NewClient(config) 76 | blocklistIdentifier, err := client.Delete(context.Background(), id) 77 | require.NoError(t, err) 78 | require.Equal(t, id, blocklistIdentifier.ID) 79 | require.True(t, blocklistIdentifier.Deleted) 80 | } 81 | 82 | func TestBlocklistIdentifierClientList(t *testing.T) { 83 | t.Parallel() 84 | config := &clerk.ClientConfig{} 85 | config.HTTPClient = &http.Client{ 86 | Transport: &clerktest.RoundTripper{ 87 | T: t, 88 | Out: json.RawMessage(`{ 89 | "data": [{"id":"blid_123","identifier":"foo@bar.com"}], 90 | "total_count": 1 91 | }`), 92 | Method: http.MethodGet, 93 | Path: "/v1/blocklist_identifiers", 94 | }, 95 | } 96 | client := NewClient(config) 97 | list, err := client.List(context.Background(), &ListParams{}) 98 | require.NoError(t, err) 99 | require.Equal(t, int64(1), list.TotalCount) 100 | require.Equal(t, 1, len(list.BlocklistIdentifiers)) 101 | require.Equal(t, "blid_123", list.BlocklistIdentifiers[0].ID) 102 | require.Equal(t, "foo@bar.com", list.BlocklistIdentifiers[0].Identifier) 103 | } 104 | -------------------------------------------------------------------------------- /clerktest/clerktest.go: -------------------------------------------------------------------------------- 1 | // Package clerktest provides utilities for testing. 2 | package clerktest 3 | 4 | import ( 5 | "bytes" 6 | "crypto" 7 | "crypto/rand" 8 | "crypto/rsa" 9 | "encoding/json" 10 | "io" 11 | "net/http" 12 | "net/url" 13 | "sync" 14 | "testing" 15 | "time" 16 | 17 | "github.com/go-jose/go-jose/v3" 18 | "github.com/go-jose/go-jose/v3/jwt" 19 | "github.com/stretchr/testify/require" 20 | ) 21 | 22 | // RoundTripper can be used as a mock Transport for http.Clients. 23 | // Set the RoundTripper's fields accordingly to determine the 24 | // response or perform assertions on the http.Request properties. 25 | type RoundTripper struct { 26 | T *testing.T 27 | // Status is the response Status code. 28 | Status int 29 | // Out is the response body. 30 | Out json.RawMessage 31 | // Set this field to assert on the request method. 32 | Method string 33 | // Set this field to assert that the request path matches. 34 | Path string 35 | // Set this field to assert that the request URL querystring matches. 36 | Query *url.Values 37 | // Set this field to assert that the request body matches. 38 | In json.RawMessage 39 | } 40 | 41 | // RoundTrip returns an http.Response based on the RoundTripper's fields. 42 | // It will also perform assertions on the http.Request. 43 | func (rt *RoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { 44 | if rt.Status == 0 { 45 | rt.Status = http.StatusOK 46 | } 47 | if rt.Method != "" { 48 | require.Equal(rt.T, rt.Method, r.Method) 49 | } 50 | if rt.Path != "" { 51 | require.Equal(rt.T, rt.Path, r.URL.Path) 52 | } 53 | if rt.Query != nil { 54 | require.Equal(rt.T, rt.Query.Encode(), r.URL.Query().Encode()) 55 | } 56 | if rt.In != nil { 57 | body, err := io.ReadAll(r.Body) 58 | if err != nil { 59 | return nil, err 60 | } 61 | defer r.Body.Close() 62 | require.JSONEq(rt.T, string(rt.In), string(body)) 63 | } 64 | return &http.Response{ 65 | StatusCode: rt.Status, 66 | Body: io.NopCloser(bytes.NewReader(rt.Out)), 67 | }, nil 68 | } 69 | 70 | // GenerateJWT creates a JSON web token with the provided claims 71 | // and key ID. 72 | func GenerateJWT(t *testing.T, claims any, kid string) (string, crypto.PublicKey) { 73 | t.Helper() 74 | 75 | privKey, err := rsa.GenerateKey(rand.Reader, 2048) 76 | require.NoError(t, err) 77 | 78 | signerOpts := &jose.SignerOptions{} 79 | signerOpts.WithType("JWT") 80 | if kid != "" { 81 | signerOpts.WithHeader("kid", kid) 82 | } 83 | signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.RS256, Key: privKey}, signerOpts) 84 | require.NoError(t, err) 85 | 86 | builder := jwt.Signed(signer) 87 | builder = builder.Claims(claims) 88 | token, err := builder.CompactSerialize() 89 | require.NoError(t, err) 90 | 91 | return token, privKey.Public() 92 | } 93 | 94 | // Clock provides a test clock which can be manually advanced through time. 95 | type Clock struct { 96 | mu sync.RWMutex 97 | // The current time of this test clock. 98 | time time.Time 99 | } 100 | 101 | // NewClockAt returns a Clock initialized at the given time. 102 | func NewClockAt(t time.Time) *Clock { 103 | return &Clock{time: t} 104 | } 105 | 106 | // Now returns the clock's current time. 107 | func (c *Clock) Now() time.Time { 108 | return c.time 109 | } 110 | 111 | // Advance moves the test clock to a new point in time. 112 | func (c *Clock) Advance(d time.Duration) { 113 | c.mu.Lock() 114 | defer c.mu.Unlock() 115 | c.time = c.time.Add(d) 116 | } 117 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type Client struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | LastActiveSessionID *string `json:"last_active_session_id"` 8 | SignInID *string `json:"sign_in_id"` 9 | SignUpID *string `json:"sign_up_id"` 10 | SessionIDs []string `json:"session_ids"` 11 | Sessions []*Session `json:"sessions"` 12 | CreatedAt int64 `json:"created_at"` 13 | UpdatedAt int64 `json:"updated_at"` 14 | } 15 | 16 | type ClientList struct { 17 | APIResource 18 | Clients []*Client `json:"data"` 19 | TotalCount int64 `json:"total_count"` 20 | } 21 | -------------------------------------------------------------------------------- /client/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package client 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Get retrieves the client specified by ID. 12 | func Get(ctx context.Context, id string) (*clerk.Client, error) { 13 | return getClient().Get(ctx, id) 14 | } 15 | 16 | // Verify verifies the Client in the provided JWT. 17 | func Verify(ctx context.Context, params *VerifyParams) (*clerk.Client, error) { 18 | return getClient().Verify(ctx, params) 19 | } 20 | 21 | // List returns a list of all the clients. 22 | // 23 | // Deprecated: The operation is deprecated and will be removed in 24 | // future versions. 25 | func List(ctx context.Context, params *ListParams) (*clerk.ClientList, error) { 26 | return getClient().List(ctx, params) 27 | } 28 | 29 | func getClient() *Client { 30 | return &Client{ 31 | Backend: clerk.GetBackend(), 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /client/client.go: -------------------------------------------------------------------------------- 1 | // Package client provides the Client API. 2 | package client 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | "net/url" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/clients" 15 | 16 | // Client is used to invoke the Client API. 17 | // This is an API client for interacting with Clerk Client resources. 18 | type Client struct { 19 | Backend clerk.Backend 20 | } 21 | 22 | func NewClient(config *clerk.ClientConfig) *Client { 23 | return &Client{ 24 | Backend: clerk.NewBackend(&config.BackendConfig), 25 | } 26 | } 27 | 28 | // Get retrieves the client specified by ID. 29 | func (c *Client) Get(ctx context.Context, id string) (*clerk.Client, error) { 30 | path, err := clerk.JoinPath(path, id) 31 | if err != nil { 32 | return nil, err 33 | } 34 | req := clerk.NewAPIRequest(http.MethodGet, path) 35 | client := &clerk.Client{} 36 | err = c.Backend.Call(ctx, req, client) 37 | return client, err 38 | } 39 | 40 | type VerifyParams struct { 41 | clerk.APIParams 42 | Token *string `json:"token,omitempty"` 43 | } 44 | 45 | // Verify verifies the Client in the provided JWT. 46 | func (c *Client) Verify(ctx context.Context, params *VerifyParams) (*clerk.Client, error) { 47 | path, err := clerk.JoinPath(path, "/verify") 48 | if err != nil { 49 | return nil, err 50 | } 51 | req := clerk.NewAPIRequest(http.MethodPost, path) 52 | req.SetParams(params) 53 | client := &clerk.Client{} 54 | err = c.Backend.Call(ctx, req, client) 55 | return client, err 56 | } 57 | 58 | type ListParams struct { 59 | clerk.APIParams 60 | clerk.ListParams 61 | } 62 | 63 | func (params *ListParams) ToQuery() url.Values { 64 | return params.ListParams.ToQuery() 65 | } 66 | 67 | // List returns a list of all the clients. 68 | // 69 | // Deprecated: The operation is deprecated and will be removed in 70 | // future versions. 71 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.ClientList, error) { 72 | req := clerk.NewAPIRequest(http.MethodGet, path) 73 | req.SetParams(params) 74 | list := &clerk.ClientList{} 75 | err := c.Backend.Call(ctx, req, list) 76 | return list, err 77 | } 78 | -------------------------------------------------------------------------------- /client/client_test.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "net/url" 9 | "testing" 10 | 11 | "github.com/clerk/clerk-sdk-go/v2" 12 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func TestClientClientGet(t *testing.T) { 17 | t.Parallel() 18 | id := "client_123" 19 | config := &clerk.ClientConfig{} 20 | config.HTTPClient = &http.Client{ 21 | Transport: &clerktest.RoundTripper{ 22 | T: t, 23 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s"}`, id)), 24 | Method: http.MethodGet, 25 | Path: "/v1/clients/" + id, 26 | }, 27 | } 28 | c := NewClient(config) 29 | client, err := c.Get(context.Background(), id) 30 | require.NoError(t, err) 31 | require.Equal(t, id, client.ID) 32 | } 33 | 34 | func TestClientClientVerify(t *testing.T) { 35 | t.Parallel() 36 | id := "client_123" 37 | token := "the-token" 38 | config := &clerk.ClientConfig{} 39 | config.HTTPClient = &http.Client{ 40 | Transport: &clerktest.RoundTripper{ 41 | T: t, 42 | In: json.RawMessage(fmt.Sprintf(`{"token":"%s"}`, token)), 43 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s"}`, id)), 44 | Method: http.MethodPost, 45 | Path: "/v1/clients/verify", 46 | }, 47 | } 48 | c := NewClient(config) 49 | client, err := c.Verify(context.Background(), &VerifyParams{ 50 | Token: clerk.String("the-token"), 51 | }) 52 | require.NoError(t, err) 53 | require.Equal(t, id, client.ID) 54 | } 55 | 56 | func TestClientClientList(t *testing.T) { 57 | t.Parallel() 58 | config := &clerk.ClientConfig{} 59 | config.HTTPClient = &http.Client{ 60 | Transport: &clerktest.RoundTripper{ 61 | T: t, 62 | Out: json.RawMessage(`{ 63 | "data": [{"id":"client_123","last_active_session_id":"sess_123"}], 64 | "total_count": 1 65 | }`), 66 | Method: http.MethodGet, 67 | Path: "/v1/clients", 68 | Query: &url.Values{ 69 | "limit": []string{"1"}, 70 | "offset": []string{"2"}, 71 | }, 72 | }, 73 | } 74 | c := NewClient(config) 75 | params := &ListParams{} 76 | params.Limit = clerk.Int64(1) 77 | params.Offset = clerk.Int64(2) 78 | list, err := c.List(context.Background(), params) 79 | require.NoError(t, err) 80 | require.Equal(t, int64(1), list.TotalCount) 81 | require.Equal(t, 1, len(list.Clients)) 82 | require.Equal(t, "client_123", list.Clients[0].ID) 83 | require.Equal(t, "sess_123", *list.Clients[0].LastActiveSessionID) 84 | } 85 | -------------------------------------------------------------------------------- /cmd/gen/main.go: -------------------------------------------------------------------------------- 1 | //go:build ignore 2 | 3 | // This program runs on a given package and generates one function 4 | // for each client API method. 5 | // Can be invoked by running go generate. 6 | package main 7 | 8 | import ( 9 | "bufio" 10 | "bytes" 11 | "fmt" 12 | "go/format" 13 | "log" 14 | "os" 15 | "path" 16 | "path/filepath" 17 | "regexp" 18 | "strings" 19 | "text/template" 20 | "unicode" 21 | ) 22 | 23 | func main() { 24 | cwd, err := os.Getwd() 25 | if err != nil { 26 | log.Fatalf("cannot get working dir: %s", err) 27 | } 28 | 29 | // We're looking for source code in /client.go files. 30 | filePath, err := filepath.Abs(path.Join(cwd, "client.go")) 31 | if err != nil { 32 | log.Fatal(fmt.Errorf("get absolute file path: %w", err)) 33 | } 34 | 35 | file, err := os.Open(filePath) 36 | if err != nil { 37 | log.Fatal(fmt.Errorf("open %s: %w", filePath, err)) 38 | } 39 | defer file.Close() 40 | 41 | var b bytes.Buffer 42 | // Start writing with the header. 43 | err = headTempl.Execute(&b, headVars{ 44 | Command: "gen", 45 | PackageName: path.Base(cwd), 46 | }) 47 | if err != nil { 48 | log.Fatal(fmt.Errorf("%s: write header: %w", filePath, err)) 49 | } 50 | 51 | // Now write all Client methods as functions. 52 | sc := bufio.NewScanner(file) 53 | var comments strings.Builder 54 | for sc.Scan() { 55 | line := strings.Trim(sc.Text(), " ") 56 | 57 | // Gather all comments, they might be a method's 58 | // godoc. 59 | if strings.HasPrefix(line, "//") { 60 | comments.WriteString("\n" + line) 61 | } 62 | if line == "" { 63 | comments.Reset() 64 | } 65 | 66 | // Not a *Client method, skip 67 | if !strings.HasPrefix(line, lineStartsWith) { 68 | continue 69 | } 70 | 71 | // We've reached a line containing a method definition. Let's 72 | // write the method godoc comments. 73 | _, err := b.WriteString(comments.String()) 74 | if err != nil { 75 | log.Fatal(fmt.Errorf("cannot write comments: %w", err)) 76 | } 77 | comments.Reset() 78 | 79 | // Gather all exported *Client functions 80 | vars := getFuncVars(line) 81 | isExported := false 82 | for i, r := range vars.FuncName { 83 | if i > 0 { 84 | break 85 | } 86 | isExported = unicode.IsUpper(r) 87 | } 88 | if !isExported { 89 | continue 90 | } 91 | err = funcTempl.Execute(&b, vars) 92 | if err != nil { 93 | log.Fatal(fmt.Errorf("write func from %s: %w", line, err)) 94 | } 95 | } 96 | if err := sc.Err(); err != nil { 97 | log.Fatal(fmt.Errorf("read file %s: %w", filePath, err)) 98 | } 99 | 100 | // Write the last parts of the file. 101 | err = footTempl.Execute(&b, nil) 102 | if err != nil { 103 | log.Fatal(fmt.Errorf("%s: write footer: %w", filePath, err)) 104 | } 105 | 106 | // Format the source code. 107 | formatted, err := format.Source(b.Bytes()) 108 | if err != nil { 109 | log.Fatal(fmt.Errorf("formatting %s: %w", filePath, err)) 110 | } 111 | 112 | // We'll write to /api.go files. Open a file for writing. 113 | writePath := strings.ReplaceAll(filePath, "client.go", "api.go") 114 | f, err := os.Create(writePath) 115 | if err != nil { 116 | log.Fatal(fmt.Errorf("create file %s for writing: %w", writePath, err)) 117 | } 118 | // Write the file 119 | _, err = f.Write(formatted) 120 | if err != nil { 121 | log.Fatal(fmt.Errorf("commit func: %w", err)) 122 | } 123 | } 124 | 125 | // We care only about *Client methods. Method declarations begin 126 | // with lineStartsWith. 127 | const lineStartsWith = "func (c *Client) " 128 | 129 | var nameRE = regexp.MustCompile("^\\w+\\(") 130 | var argsRE = regexp.MustCompile("^.+\\)\\s[\\(e]") 131 | var returnRE = regexp.MustCompile("^.+\\s{") 132 | 133 | // Parse a method definition line and get the name, arguments and 134 | // return types. 135 | // The line has the format 136 | // func (c *Client) MethodName(ctx context.Context, params *Params) (*clerk.Resource, error) { 137 | // Quick and dirty method but it works :). 138 | func getFuncVars(line string) funcVars { 139 | line = strings.TrimPrefix(line, "func (c *Client) ") 140 | 141 | name := nameRE.FindString(line) 142 | line = strings.TrimPrefix(line, name) 143 | 144 | args := argsRE.FindString(line) 145 | args = strings.TrimSuffix(args, ") e") 146 | line = strings.TrimPrefix(line, args) 147 | 148 | returnV := returnRE.FindString(line) 149 | returnV = strings.TrimSuffix(returnV, " {") 150 | 151 | name = strings.Trim(name, "(") 152 | args = strings.Trim(args, ") (") 153 | returnV = strings.Trim(returnV, ")") 154 | allArgs := strings.Split(args, ",") 155 | params := make([]string, len(allArgs)) 156 | for i, arg := range allArgs { 157 | params[i] = strings.Split(strings.TrimPrefix(arg, " "), " ")[0] 158 | } 159 | 160 | return funcVars{ 161 | FuncName: name, 162 | FuncArgs: args, 163 | FuncReturn: returnV, 164 | FuncParams: strings.Join(params, ","), 165 | } 166 | } 167 | 168 | type headVars struct { 169 | Command string 170 | PackageName string 171 | } 172 | 173 | var headTempl = template.Must(template.New("").Parse(` 174 | // Code generated by "{{.Command}}"; DO NOT EDIT. 175 | // This file is meant to be re-generated in place and/or deleted at any time. 176 | package {{.PackageName}} 177 | 178 | import ( 179 | "context" 180 | 181 | "github.com/clerk/clerk-sdk-go/v2" 182 | ) 183 | `)) 184 | 185 | type funcVars struct { 186 | FuncName string 187 | FuncArgs string 188 | FuncReturn string 189 | FuncParams string 190 | } 191 | 192 | var funcTempl = template.Must(template.New("").Parse(` 193 | func {{.FuncName}}({{.FuncArgs}}) ({{.FuncReturn}}) { 194 | return getClient().{{.FuncName}}({{.FuncParams}}) 195 | } 196 | `)) 197 | 198 | var footTempl = template.Must(template.New("").Parse(` 199 | func getClient() *Client { 200 | return &Client{ 201 | Backend: clerk.GetBackend(), 202 | } 203 | } 204 | `)) 205 | -------------------------------------------------------------------------------- /deleted_resource.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | // DeletedResource describes an API resource that is no longer 4 | // available. 5 | // It's usually encountered as a result of delete API operations. 6 | type DeletedResource struct { 7 | APIResource 8 | ID string `json:"id,omitempty"` 9 | Slug string `json:"slug,omitempty"` 10 | Object string `json:"object"` 11 | Deleted bool `json:"deleted"` 12 | } 13 | -------------------------------------------------------------------------------- /domain.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type Domain struct { 4 | APIResource 5 | ID string `json:"id"` 6 | Object string `json:"object"` 7 | Name string `json:"name"` 8 | IsSatellite bool `json:"is_satellite"` 9 | FrontendAPIURL string `json:"frontend_api_url"` 10 | AccountPortalURL *string `json:"accounts_portal_url,omitempty"` 11 | ProxyURL *string `json:"proxy_url,omitempty"` 12 | CNAMETargets []CNAMETarget `json:"cname_targets,omitempty"` 13 | DevelopmentOrigin string `json:"development_origin"` 14 | } 15 | 16 | type CNAMETarget struct { 17 | Host string `json:"host"` 18 | Value string `json:"value"` 19 | } 20 | 21 | type DomainList struct { 22 | APIResource 23 | Domains []*Domain `json:"data"` 24 | TotalCount int64 `json:"total_count"` 25 | } 26 | -------------------------------------------------------------------------------- /domain/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package domain 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new domain. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.Domain, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Update updates a domain's properties. 17 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.Domain, error) { 18 | return getClient().Update(ctx, id, params) 19 | } 20 | 21 | // Delete removes a domain. 22 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 23 | return getClient().Delete(ctx, id) 24 | } 25 | 26 | // List returns a list of domains. 27 | func List(ctx context.Context, params *ListParams) (*clerk.DomainList, error) { 28 | return getClient().List(ctx, params) 29 | } 30 | 31 | func getClient() *Client { 32 | return &Client{ 33 | Backend: clerk.GetBackend(), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /domain/client.go: -------------------------------------------------------------------------------- 1 | // Package domain provides the Domains API. 2 | package domain 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/domains" 14 | 15 | // Client is used to invoke the Domains API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | type CreateParams struct { 27 | clerk.APIParams 28 | Name *string `json:"name,omitempty"` 29 | ProxyURL *string `json:"proxy_url,omitempty"` 30 | IsSatellite *bool `json:"is_satellite,omitempty"` 31 | } 32 | 33 | // Create creates a new domain. 34 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.Domain, error) { 35 | req := clerk.NewAPIRequest(http.MethodPost, path) 36 | req.SetParams(params) 37 | 38 | domain := &clerk.Domain{} 39 | err := c.Backend.Call(ctx, req, domain) 40 | return domain, err 41 | } 42 | 43 | type UpdateParams struct { 44 | clerk.APIParams 45 | Name *string `json:"name,omitempty"` 46 | ProxyURL *string `json:"proxy_url,omitempty"` 47 | IsSecondary *bool `json:"is_secondary,omitempty"` 48 | } 49 | 50 | // Update updates a domain's properties. 51 | func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (*clerk.Domain, error) { 52 | path, err := clerk.JoinPath(path, id) 53 | if err != nil { 54 | return nil, err 55 | } 56 | req := clerk.NewAPIRequest(http.MethodPatch, path) 57 | req.SetParams(params) 58 | 59 | domain := &clerk.Domain{} 60 | err = c.Backend.Call(ctx, req, domain) 61 | return domain, err 62 | } 63 | 64 | // Delete removes a domain. 65 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 66 | path, err := clerk.JoinPath(path, id) 67 | if err != nil { 68 | return nil, err 69 | } 70 | req := clerk.NewAPIRequest(http.MethodDelete, path) 71 | domain := &clerk.DeletedResource{} 72 | err = c.Backend.Call(ctx, req, domain) 73 | return domain, err 74 | } 75 | 76 | type ListParams struct { 77 | clerk.APIParams 78 | } 79 | 80 | // List returns a list of domains. 81 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.DomainList, error) { 82 | req := clerk.NewAPIRequest(http.MethodGet, path) 83 | list := &clerk.DomainList{} 84 | err := c.Backend.Call(ctx, req, list) 85 | return list, err 86 | } 87 | -------------------------------------------------------------------------------- /domain/domain_test.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestDomainCreate(t *testing.T) { 16 | name := "clerk.com" 17 | id := "dmn_123" 18 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 19 | HTTPClient: &http.Client{ 20 | Transport: &clerktest.RoundTripper{ 21 | T: t, 22 | In: json.RawMessage(fmt.Sprintf(`{"name":"%s"}`, name)), 23 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), 24 | Path: "/v1/domains", 25 | Method: http.MethodPost, 26 | }, 27 | }, 28 | })) 29 | 30 | dmn, err := Create(context.Background(), &CreateParams{ 31 | Name: clerk.String(name), 32 | }) 33 | require.NoError(t, err) 34 | require.Equal(t, id, dmn.ID) 35 | require.Equal(t, name, dmn.Name) 36 | } 37 | 38 | func TestDomainCreate_Error(t *testing.T) { 39 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 40 | HTTPClient: &http.Client{ 41 | Transport: &clerktest.RoundTripper{ 42 | T: t, 43 | Status: http.StatusBadRequest, 44 | Out: json.RawMessage(`{ 45 | "errors":[{ 46 | "code":"create-error-code" 47 | }], 48 | "clerk_trace_id":"create-trace-id" 49 | }`), 50 | }, 51 | }, 52 | })) 53 | 54 | _, err := Create(context.Background(), &CreateParams{}) 55 | require.Error(t, err) 56 | apiErr, ok := err.(*clerk.APIErrorResponse) 57 | require.True(t, ok) 58 | require.Equal(t, "create-trace-id", apiErr.TraceID) 59 | require.Equal(t, 1, len(apiErr.Errors)) 60 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 61 | } 62 | 63 | func TestDomainUpdate(t *testing.T) { 64 | id := "dmn_456" 65 | name := "clerk.dev" 66 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 67 | HTTPClient: &http.Client{ 68 | Transport: &clerktest.RoundTripper{ 69 | T: t, 70 | In: json.RawMessage(fmt.Sprintf(`{"name":"%s"}`, name)), 71 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), 72 | Path: fmt.Sprintf("/v1/domains/%s", id), 73 | Method: http.MethodPatch, 74 | }, 75 | }, 76 | })) 77 | 78 | dmn, err := Update(context.Background(), id, &UpdateParams{ 79 | Name: clerk.String(name), 80 | }) 81 | require.NoError(t, err) 82 | require.Equal(t, id, dmn.ID) 83 | require.Equal(t, name, dmn.Name) 84 | } 85 | 86 | func TestDomainUpdate_Error(t *testing.T) { 87 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 88 | HTTPClient: &http.Client{ 89 | Transport: &clerktest.RoundTripper{ 90 | T: t, 91 | Status: http.StatusBadRequest, 92 | Out: json.RawMessage(`{ 93 | "errors":[{ 94 | "code":"update-error-code" 95 | }], 96 | "clerk_trace_id":"update-trace-id" 97 | }`), 98 | }, 99 | }, 100 | })) 101 | 102 | _, err := Update(context.Background(), "dmn_123", &UpdateParams{}) 103 | require.Error(t, err) 104 | apiErr, ok := err.(*clerk.APIErrorResponse) 105 | require.True(t, ok) 106 | require.Equal(t, "update-trace-id", apiErr.TraceID) 107 | require.Equal(t, 1, len(apiErr.Errors)) 108 | require.Equal(t, "update-error-code", apiErr.Errors[0].Code) 109 | } 110 | 111 | func TestDomainDelete(t *testing.T) { 112 | id := "dmn_789" 113 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 114 | HTTPClient: &http.Client{ 115 | Transport: &clerktest.RoundTripper{ 116 | T: t, 117 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), 118 | Path: fmt.Sprintf("/v1/domains/%s", id), 119 | Method: http.MethodDelete, 120 | }, 121 | }, 122 | })) 123 | 124 | dmn, err := Delete(context.Background(), id) 125 | require.NoError(t, err) 126 | require.Equal(t, id, dmn.ID) 127 | require.True(t, dmn.Deleted) 128 | } 129 | 130 | func TestDomainList(t *testing.T) { 131 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 132 | HTTPClient: &http.Client{ 133 | Transport: &clerktest.RoundTripper{ 134 | T: t, 135 | Out: json.RawMessage(`{ 136 | "data": [{"id":"dmn_123","name":"clerk.com"}], 137 | "total_count": 1 138 | }`), 139 | Path: "/v1/domains", 140 | Method: http.MethodGet, 141 | }, 142 | }, 143 | })) 144 | 145 | list, err := List(context.Background(), &ListParams{}) 146 | require.NoError(t, err) 147 | require.Equal(t, int64(1), list.TotalCount) 148 | require.Equal(t, 1, len(list.Domains)) 149 | require.Equal(t, "dmn_123", list.Domains[0].ID) 150 | require.Equal(t, "clerk.com", list.Domains[0].Name) 151 | } 152 | -------------------------------------------------------------------------------- /email_address.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type EmailAddress struct { 6 | APIResource 7 | ID string `json:"id"` 8 | Object string `json:"object"` 9 | EmailAddress string `json:"email_address"` 10 | Reserved bool `json:"reserved"` 11 | Verification *Verification `json:"verification"` 12 | LinkedTo []*LinkedIdentification `json:"linked_to"` 13 | } 14 | 15 | type Verification struct { 16 | Status string `json:"status"` 17 | Strategy string `json:"strategy"` 18 | Attempts *int64 `json:"attempts"` 19 | ExpireAt *int64 `json:"expire_at"` 20 | VerifiedAtClient string `json:"verified_at_client,omitempty"` 21 | Nonce *string `json:"nonce,omitempty"` 22 | ExternalVerificationRedirectURL *string `json:"external_verification_redirect_url,omitempty"` 23 | Error json.RawMessage `json:"error,omitempty"` 24 | } 25 | 26 | type LinkedIdentification struct { 27 | ID string `json:"id"` 28 | Type string `json:"type"` 29 | } 30 | -------------------------------------------------------------------------------- /emailaddress/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package emailaddress 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new email address. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.EmailAddress, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Get retrieves an email address. 17 | func Get(ctx context.Context, id string) (*clerk.EmailAddress, error) { 18 | return getClient().Get(ctx, id) 19 | } 20 | 21 | // Update updates the email address specified by id. 22 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.EmailAddress, error) { 23 | return getClient().Update(ctx, id, params) 24 | } 25 | 26 | // Delete deletes an email address. 27 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 28 | return getClient().Delete(ctx, id) 29 | } 30 | 31 | func getClient() *Client { 32 | return &Client{ 33 | Backend: clerk.GetBackend(), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /emailaddress/client.go: -------------------------------------------------------------------------------- 1 | // Package emailaddress provides the Email Addresses API. 2 | package emailaddress 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/email_addresses" 14 | 15 | // Client is used to invoke the Email Addresses API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | type CreateParams struct { 27 | clerk.APIParams 28 | UserID *string `json:"user_id,omitempty"` 29 | EmailAddress *string `json:"email_address,omitempty"` 30 | Verified *bool `json:"verified,omitempty"` 31 | Primary *bool `json:"primary,omitempty"` 32 | } 33 | 34 | // Create creates a new email address. 35 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.EmailAddress, error) { 36 | req := clerk.NewAPIRequest(http.MethodPost, path) 37 | req.SetParams(params) 38 | emailAddress := &clerk.EmailAddress{} 39 | err := c.Backend.Call(ctx, req, emailAddress) 40 | return emailAddress, err 41 | } 42 | 43 | // Get retrieves an email address. 44 | func (c *Client) Get(ctx context.Context, id string) (*clerk.EmailAddress, error) { 45 | path, err := clerk.JoinPath(path, id) 46 | if err != nil { 47 | return nil, err 48 | } 49 | req := clerk.NewAPIRequest(http.MethodGet, path) 50 | emailAddress := &clerk.EmailAddress{} 51 | err = c.Backend.Call(ctx, req, emailAddress) 52 | return emailAddress, err 53 | } 54 | 55 | type UpdateParams struct { 56 | clerk.APIParams 57 | Verified *bool `json:"verified,omitempty"` 58 | Primary *bool `json:"primary,omitempty"` 59 | } 60 | 61 | // Update updates the email address specified by id. 62 | func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (*clerk.EmailAddress, error) { 63 | path, err := clerk.JoinPath(path, id) 64 | if err != nil { 65 | return nil, err 66 | } 67 | req := clerk.NewAPIRequest(http.MethodPatch, path) 68 | req.SetParams(params) 69 | emailAddress := &clerk.EmailAddress{} 70 | err = c.Backend.Call(ctx, req, emailAddress) 71 | return emailAddress, err 72 | } 73 | 74 | // Delete deletes an email address. 75 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 76 | path, err := clerk.JoinPath(path, id) 77 | if err != nil { 78 | return nil, err 79 | } 80 | req := clerk.NewAPIRequest(http.MethodDelete, path) 81 | emailAddress := &clerk.DeletedResource{} 82 | err = c.Backend.Call(ctx, req, emailAddress) 83 | return emailAddress, err 84 | } 85 | -------------------------------------------------------------------------------- /emailaddress/client_test.go: -------------------------------------------------------------------------------- 1 | package emailaddress 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestEmailAddressClientCreate(t *testing.T) { 16 | t.Parallel() 17 | email := "foo@bar.com" 18 | userID := "user_123" 19 | id := "idn_123" 20 | config := &clerk.ClientConfig{} 21 | config.HTTPClient = &http.Client{ 22 | Transport: &clerktest.RoundTripper{ 23 | T: t, 24 | In: json.RawMessage(fmt.Sprintf(`{"email_address":"%s","user_id":"%s","verified":false}`, email, userID)), 25 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","email_address":"%s"}`, id, email)), 26 | Method: http.MethodPost, 27 | Path: "/v1/email_addresses", 28 | }, 29 | } 30 | client := NewClient(config) 31 | emailAddress, err := client.Create(context.Background(), &CreateParams{ 32 | UserID: clerk.String(userID), 33 | EmailAddress: clerk.String(email), 34 | Verified: clerk.Bool(false), 35 | }) 36 | require.NoError(t, err) 37 | require.Equal(t, id, emailAddress.ID) 38 | require.Equal(t, email, emailAddress.EmailAddress) 39 | } 40 | 41 | func TestEmailAddressClientCreate_Error(t *testing.T) { 42 | t.Parallel() 43 | config := &clerk.ClientConfig{} 44 | config.HTTPClient = &http.Client{ 45 | Transport: &clerktest.RoundTripper{ 46 | T: t, 47 | Status: http.StatusBadRequest, 48 | Out: json.RawMessage(`{ 49 | "errors":[{ 50 | "code":"create-error-code" 51 | }], 52 | "clerk_trace_id":"create-trace-id" 53 | }`), 54 | }, 55 | } 56 | client := NewClient(config) 57 | _, err := client.Create(context.Background(), &CreateParams{}) 58 | require.Error(t, err) 59 | apiErr, ok := err.(*clerk.APIErrorResponse) 60 | require.True(t, ok) 61 | require.Equal(t, "create-trace-id", apiErr.TraceID) 62 | require.Equal(t, 1, len(apiErr.Errors)) 63 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 64 | } 65 | 66 | func TestEmailAddressClientUpdate(t *testing.T) { 67 | t.Parallel() 68 | id := "idn_123" 69 | config := &clerk.ClientConfig{} 70 | config.HTTPClient = &http.Client{ 71 | Transport: &clerktest.RoundTripper{ 72 | T: t, 73 | In: json.RawMessage(`{"verified":true}`), 74 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","verification":{"status":"verified"}}`, id)), 75 | Method: http.MethodPatch, 76 | Path: "/v1/email_addresses/" + id, 77 | }, 78 | } 79 | client := NewClient(config) 80 | emailAddress, err := client.Update(context.Background(), "idn_123", &UpdateParams{ 81 | Verified: clerk.Bool(true), 82 | }) 83 | require.NoError(t, err) 84 | require.Equal(t, id, emailAddress.ID) 85 | require.Equal(t, "verified", emailAddress.Verification.Status) 86 | } 87 | 88 | func TestEmailAddressClientUpdate_Error(t *testing.T) { 89 | t.Parallel() 90 | config := &clerk.ClientConfig{} 91 | config.HTTPClient = &http.Client{ 92 | Transport: &clerktest.RoundTripper{ 93 | T: t, 94 | Status: http.StatusBadRequest, 95 | Out: json.RawMessage(`{ 96 | "errors":[{ 97 | "code":"update-error-code" 98 | }], 99 | "clerk_trace_id":"update-trace-id" 100 | }`), 101 | }, 102 | } 103 | client := NewClient(config) 104 | _, err := client.Update(context.Background(), "idn_123", &UpdateParams{}) 105 | require.Error(t, err) 106 | apiErr, ok := err.(*clerk.APIErrorResponse) 107 | require.True(t, ok) 108 | require.Equal(t, "update-trace-id", apiErr.TraceID) 109 | require.Equal(t, 1, len(apiErr.Errors)) 110 | require.Equal(t, "update-error-code", apiErr.Errors[0].Code) 111 | } 112 | 113 | func TestEmailAddressClientGet(t *testing.T) { 114 | t.Parallel() 115 | id := "idn_123" 116 | config := &clerk.ClientConfig{} 117 | config.HTTPClient = &http.Client{ 118 | Transport: &clerktest.RoundTripper{ 119 | T: t, 120 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","verification":{"status":"verified"}}`, id)), 121 | Method: http.MethodGet, 122 | Path: "/v1/email_addresses/" + id, 123 | }, 124 | } 125 | client := NewClient(config) 126 | emailAddress, err := client.Get(context.Background(), id) 127 | require.NoError(t, err) 128 | require.Equal(t, id, emailAddress.ID) 129 | require.Equal(t, "verified", emailAddress.Verification.Status) 130 | } 131 | 132 | func TestEmailAddressClientDelete(t *testing.T) { 133 | t.Parallel() 134 | id := "idn_456" 135 | config := &clerk.ClientConfig{} 136 | config.HTTPClient = &http.Client{ 137 | Transport: &clerktest.RoundTripper{ 138 | T: t, 139 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), 140 | Method: http.MethodDelete, 141 | Path: "/v1/email_addresses/" + id, 142 | }, 143 | } 144 | client := NewClient(config) 145 | emailAddress, err := client.Delete(context.Background(), id) 146 | require.NoError(t, err) 147 | require.Equal(t, id, emailAddress.ID) 148 | require.True(t, emailAddress.Deleted) 149 | } 150 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/clerk/clerk-sdk-go/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/go-jose/go-jose/v3 v3.0.3 7 | github.com/stretchr/testify v1.8.2 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/pmezard/go-difflib v1.0.0 // indirect 13 | golang.org/x/crypto v0.19.0 // indirect 14 | gopkg.in/yaml.v3 v3.0.1 // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= 5 | github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= 6 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 7 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 8 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 9 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 11 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 12 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 13 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 14 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 15 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 16 | github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= 17 | github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 18 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 19 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 20 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 21 | golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= 22 | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= 23 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 24 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 25 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 26 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 27 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 28 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 29 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 30 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 31 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 32 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 33 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 34 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 35 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 36 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 37 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 39 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 40 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 41 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 42 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 43 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 44 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 45 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 46 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 47 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 48 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 49 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 50 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 51 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 52 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 53 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 54 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 55 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 56 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 57 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 58 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 59 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 60 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 61 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 62 | -------------------------------------------------------------------------------- /http/response.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/clerk/clerk-sdk-go/v2" 8 | ) 9 | 10 | type ErrorPayload struct { 11 | Type string `json:"type"` 12 | Reason string `json:"reason"` 13 | Metadata map[string]any `json:"metadata,omitempty"` 14 | } 15 | 16 | type ClerkErrorResponse struct { 17 | ClerkError ErrorPayload `json:"clerk_error"` 18 | } 19 | 20 | func NewSessionReverificationErrorPayload(missingConfig clerk.SessionReverificationPolicy) ClerkErrorResponse { 21 | return ClerkErrorResponse{ 22 | ClerkError: ErrorPayload{ 23 | Type: "forbidden", 24 | Reason: "reverification-error", 25 | Metadata: map[string]any{ 26 | "reverification": missingConfig, 27 | }, 28 | }, 29 | } 30 | } 31 | 32 | func WriteNeedsReverificationResponse(w http.ResponseWriter, missingConfig clerk.SessionReverificationPolicy) { 33 | payload := NewSessionReverificationErrorPayload(missingConfig) 34 | w.Header().Set("Content-Type", "application/json") 35 | w.WriteHeader(http.StatusForbidden) 36 | _ = json.NewEncoder(w).Encode(payload) 37 | } 38 | -------------------------------------------------------------------------------- /instance_settings.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type InstanceRestrictions struct { 4 | APIResource 5 | Object string `json:"object"` 6 | Allowlist bool `json:"allowlist"` 7 | Blocklist bool `json:"blocklist"` 8 | BlockEmailSubaddresses bool `json:"block_email_subaddresses"` 9 | BlockDisposableEmailDomains bool `json:"block_disposable_email_domains"` 10 | IgnoreDotsForGmailAddresses bool `json:"ignore_dots_for_gmail_addresses"` 11 | } 12 | 13 | type OrganizationSettings struct { 14 | APIResource 15 | Object string `json:"object"` 16 | Enabled bool `json:"enabled"` 17 | MaxAllowedMemberships int64 `json:"max_allowed_memberships"` 18 | MaxAllowedRoles int64 `json:"max_allowed_roles"` 19 | MaxAllowedPermissions int64 `json:"max_allowed_permissions"` 20 | CreatorRole string `json:"creator_role"` 21 | AdminDeleteEnabled bool `json:"admin_delete_enabled"` 22 | DomainsEnabled bool `json:"domains_enabled"` 23 | DomainsEnrollmentModes []string `json:"domains_enrollment_modes"` 24 | DomainsDefaultRole string `json:"domains_default_role"` 25 | } 26 | -------------------------------------------------------------------------------- /instancesettings/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package instancesettings 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Update updates the instance's settings. 12 | func Update(ctx context.Context, params *UpdateParams) error { 13 | return getClient().Update(ctx, params) 14 | } 15 | 16 | // UpdateRestrictions updates the restriction settings of the instance. 17 | func UpdateRestrictions(ctx context.Context, params *UpdateRestrictionsParams) (*clerk.InstanceRestrictions, error) { 18 | return getClient().UpdateRestrictions(ctx, params) 19 | } 20 | 21 | // UpdateOrganizationSettings updates the organization settings of the instance. 22 | func UpdateOrganizationSettings(ctx context.Context, params *UpdateOrganizationSettingsParams) (*clerk.OrganizationSettings, error) { 23 | return getClient().UpdateOrganizationSettings(ctx, params) 24 | } 25 | 26 | func getClient() *Client { 27 | return &Client{ 28 | Backend: clerk.GetBackend(), 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /instancesettings/client.go: -------------------------------------------------------------------------------- 1 | // Package instancesettings provides the Instance Settings API. 2 | package instancesettings 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/instance" 14 | 15 | // Client is used to invoke the Instance Settings API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | type UpdateParams struct { 27 | clerk.APIParams 28 | // TestMode can be used to toggle test mode for this instance. 29 | // Defaults to true for development instances. 30 | TestMode *bool `json:"test_mode,omitempty"` 31 | 32 | // HIBP is used to configure whether Clerk should use the 33 | // "Have I Been Pawned" service to check passwords against 34 | // known security breaches. 35 | // By default, this is enabled in all instances. 36 | HIBP *bool `json:"hibp,omitempty"` 37 | 38 | // EnhancedEmailDeliverability controls how Clerk delivers emails. 39 | // Specifically, when set to true, if the instance is a production 40 | // instance, OTP verification emails are sent by the Clerk's shared 41 | // domain via Postmark. 42 | EnhancedEmailDeliverability *bool `json:"enhanced_email_deliverability,omitempty"` 43 | 44 | // SupportEmail is the contact email address that will be displayed 45 | // on the frontend, in case your instance users need support. 46 | // If the empty string is provided, the support email that is currently 47 | // configured in the instance will be removed. 48 | SupportEmail *string `json:"support_email,omitempty"` 49 | 50 | // ClerkJSVersion allows you to request a specific Clerk JS version on the Clerk Hosted Account pages. 51 | // If an empty string is provided, the stored version will be removed. 52 | // If an explicit version is not set, the Clerk JS version will be automatically be resolved. 53 | ClerkJSVersion *string `json:"clerk_js_version,omitempty"` 54 | 55 | // CookielessDev can be used to enable the new mode in which no third-party 56 | // cookies are used in development instances. Make sure to also enable the 57 | // setting in Clerk.js 58 | // 59 | // Deprecated: Use URLBasedSessionSyncing instead 60 | CookielessDev *bool `json:"cookieless_dev,omitempty"` 61 | 62 | // URLBasedSessionSyncing can be used to enable the new mode in which no third-party 63 | // cookies are used in development instances. Make sure to also enable the 64 | // setting in Clerk.js 65 | URLBasedSessionSyncing *bool `json:"url_based_session_syncing,omitempty"` 66 | 67 | // URL that is going to be used in development instances in order to create custom redirects 68 | // and fix the third-party cookies issues. 69 | DevelopmentOrigin *string `json:"development_origin,omitempty"` 70 | } 71 | 72 | // Update updates the instance's settings. 73 | func (c *Client) Update(ctx context.Context, params *UpdateParams) error { 74 | req := clerk.NewAPIRequest(http.MethodPatch, path) 75 | req.SetParams(params) 76 | err := c.Backend.Call(ctx, req, &clerk.APIResource{}) 77 | return err 78 | } 79 | 80 | type UpdateRestrictionsParams struct { 81 | clerk.APIParams 82 | Allowlist *bool `json:"allowlist,omitempty"` 83 | Blocklist *bool `json:"blocklist,omitempty"` 84 | BlockEmailSubaddresses *bool `json:"block_email_subaddresses,omitempty"` 85 | BlockDisposableEmailDomains *bool `json:"block_disposable_email_domains,omitempty"` 86 | IgnoreDotsForGmailAddresses *bool `json:"ignore_dots_for_gmail_addresses,omitempty"` 87 | } 88 | 89 | // UpdateRestrictions updates the restriction settings of the instance. 90 | func (c *Client) UpdateRestrictions(ctx context.Context, params *UpdateRestrictionsParams) (*clerk.InstanceRestrictions, error) { 91 | path, err := clerk.JoinPath(path, "/restrictions") 92 | if err != nil { 93 | return nil, err 94 | } 95 | req := clerk.NewAPIRequest(http.MethodPatch, path) 96 | req.SetParams(params) 97 | instanceRestrictions := &clerk.InstanceRestrictions{} 98 | err = c.Backend.Call(ctx, req, instanceRestrictions) 99 | return instanceRestrictions, err 100 | } 101 | 102 | type UpdateOrganizationSettingsParams struct { 103 | clerk.APIParams 104 | Enabled *bool `json:"enabled,omitempty"` 105 | MaxAllowedMemberships *int64 `json:"max_allowed_memberships,omitempty"` 106 | CreatorRoleID *string `json:"creator_role_id,omitempty"` 107 | AdminDeleteEnabled *bool `json:"admin_delete_enabled,omitempty"` 108 | DomainsEnabled *bool `json:"domains_enabled,omitempty"` 109 | DomainsEnrollmentModes *[]string `json:"domains_enrollment_modes,omitempty"` 110 | DomainsDefaultRoleID *string `json:"domains_default_role_id,omitempty"` 111 | // This feature is currently in beta and is not yet available for all instances. 112 | // do not use this feature in production. 113 | ForceOrganizationSelection *bool `json:"force_organization_selection,omitempty"` 114 | } 115 | 116 | // UpdateOrganizationSettings updates the organization settings of the instance. 117 | func (c *Client) UpdateOrganizationSettings(ctx context.Context, params *UpdateOrganizationSettingsParams) (*clerk.OrganizationSettings, error) { 118 | path, err := clerk.JoinPath(path, "/organization_settings") 119 | if err != nil { 120 | return nil, err 121 | } 122 | req := clerk.NewAPIRequest(http.MethodPatch, path) 123 | req.SetParams(params) 124 | orgSettings := &clerk.OrganizationSettings{} 125 | err = c.Backend.Call(ctx, req, orgSettings) 126 | return orgSettings, err 127 | } 128 | -------------------------------------------------------------------------------- /instancesettings/client_test.go: -------------------------------------------------------------------------------- 1 | package instancesettings 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | "testing" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestInstanceClientUpdate(t *testing.T) { 15 | t.Parallel() 16 | config := &clerk.ClientConfig{} 17 | config.HTTPClient = &http.Client{ 18 | Transport: &clerktest.RoundTripper{ 19 | T: t, 20 | In: json.RawMessage(`{"test_mode":true}`), 21 | Out: nil, 22 | Method: http.MethodPatch, 23 | Path: "/v1/instance", 24 | }, 25 | } 26 | client := NewClient(config) 27 | err := client.Update(context.Background(), &UpdateParams{ 28 | TestMode: clerk.Bool(true), 29 | }) 30 | require.NoError(t, err) 31 | } 32 | 33 | func TestInstanceClientUpdate_Error(t *testing.T) { 34 | t.Parallel() 35 | config := &clerk.ClientConfig{} 36 | config.HTTPClient = &http.Client{ 37 | Transport: &clerktest.RoundTripper{ 38 | T: t, 39 | Status: http.StatusBadRequest, 40 | Out: json.RawMessage(`{ 41 | "errors":[{ 42 | "code":"update-error-code" 43 | }], 44 | "clerk_trace_id":"update-trace-id" 45 | }`), 46 | }, 47 | } 48 | client := NewClient(config) 49 | err := client.Update(context.Background(), &UpdateParams{}) 50 | require.Error(t, err) 51 | apiErr, ok := err.(*clerk.APIErrorResponse) 52 | require.True(t, ok) 53 | require.Equal(t, "update-trace-id", apiErr.TraceID) 54 | require.Equal(t, 1, len(apiErr.Errors)) 55 | require.Equal(t, "update-error-code", apiErr.Errors[0].Code) 56 | } 57 | 58 | func TestInstanceClientUpdateRestrictions(t *testing.T) { 59 | t.Parallel() 60 | config := &clerk.ClientConfig{} 61 | config.HTTPClient = &http.Client{ 62 | Transport: &clerktest.RoundTripper{ 63 | T: t, 64 | In: json.RawMessage(`{"allowlist":true}`), 65 | Out: json.RawMessage(`{"allowlist":true,"blocklist":false}`), 66 | Method: http.MethodPatch, 67 | Path: "/v1/instance/restrictions", 68 | }, 69 | } 70 | client := NewClient(config) 71 | restrictions, err := client.UpdateRestrictions(context.Background(), &UpdateRestrictionsParams{ 72 | Allowlist: clerk.Bool(true), 73 | }) 74 | require.NoError(t, err) 75 | require.True(t, restrictions.Allowlist) 76 | require.False(t, restrictions.Blocklist) 77 | } 78 | 79 | func TestInstanceClientUpdateRestrictions_Error(t *testing.T) { 80 | t.Parallel() 81 | config := &clerk.ClientConfig{} 82 | config.HTTPClient = &http.Client{ 83 | Transport: &clerktest.RoundTripper{ 84 | T: t, 85 | Status: http.StatusBadRequest, 86 | Out: json.RawMessage(`{ 87 | "errors":[{ 88 | "code":"update-error-code" 89 | }], 90 | "clerk_trace_id":"update-trace-id" 91 | }`), 92 | }, 93 | } 94 | client := NewClient(config) 95 | _, err := client.UpdateRestrictions(context.Background(), &UpdateRestrictionsParams{}) 96 | require.Error(t, err) 97 | apiErr, ok := err.(*clerk.APIErrorResponse) 98 | require.True(t, ok) 99 | require.Equal(t, "update-trace-id", apiErr.TraceID) 100 | require.Equal(t, 1, len(apiErr.Errors)) 101 | require.Equal(t, "update-error-code", apiErr.Errors[0].Code) 102 | } 103 | 104 | func TestInstanceClientUpdateOrganizationSettings(t *testing.T) { 105 | t.Parallel() 106 | config := &clerk.ClientConfig{} 107 | config.HTTPClient = &http.Client{ 108 | Transport: &clerktest.RoundTripper{ 109 | T: t, 110 | In: json.RawMessage(`{"enabled":true,"force_organization_selection": true}`), 111 | Out: json.RawMessage(`{"enabled":true,"max_allowed_memberships":3}`), 112 | Method: http.MethodPatch, 113 | Path: "/v1/instance/organization_settings", 114 | }, 115 | } 116 | client := NewClient(config) 117 | orgSettings, err := client.UpdateOrganizationSettings(context.Background(), &UpdateOrganizationSettingsParams{ 118 | Enabled: clerk.Bool(true), 119 | ForceOrganizationSelection: clerk.Bool(true), 120 | }) 121 | require.NoError(t, err) 122 | require.True(t, orgSettings.Enabled) 123 | require.Equal(t, int64(3), orgSettings.MaxAllowedMemberships) 124 | } 125 | 126 | func TestInstanceClientUpdateOrganizationSettings_Error(t *testing.T) { 127 | t.Parallel() 128 | config := &clerk.ClientConfig{} 129 | config.HTTPClient = &http.Client{ 130 | Transport: &clerktest.RoundTripper{ 131 | T: t, 132 | Status: http.StatusBadRequest, 133 | Out: json.RawMessage(`{ 134 | "errors":[{ 135 | "code":"update-error-code" 136 | }], 137 | "clerk_trace_id":"update-trace-id" 138 | }`), 139 | }, 140 | } 141 | client := NewClient(config) 142 | _, err := client.UpdateOrganizationSettings(context.Background(), &UpdateOrganizationSettingsParams{}) 143 | require.Error(t, err) 144 | apiErr, ok := err.(*clerk.APIErrorResponse) 145 | require.True(t, ok) 146 | require.Equal(t, "update-trace-id", apiErr.TraceID) 147 | require.Equal(t, 1, len(apiErr.Errors)) 148 | require.Equal(t, "update-error-code", apiErr.Errors[0].Code) 149 | } 150 | -------------------------------------------------------------------------------- /invitation.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type Invitation struct { 6 | APIResource 7 | Object string `json:"object"` 8 | ID string `json:"id"` 9 | EmailAddress string `json:"email_address"` 10 | PublicMetadata json.RawMessage `json:"public_metadata"` 11 | Revoked bool `json:"revoked,omitempty"` 12 | Status string `json:"status"` 13 | URL string `json:"url,omitempty"` 14 | ExpiresAt *int64 `json:"expires_at"` 15 | CreatedAt int64 `json:"created_at"` 16 | UpdatedAt int64 `json:"updated_at"` 17 | } 18 | 19 | type Invitations struct { 20 | APIResource 21 | Invitations []*Invitation `json:"data"` 22 | } 23 | 24 | type InvitationList struct { 25 | APIResource 26 | Invitations []*Invitation `json:"data"` 27 | TotalCount int64 `json:"total_count"` 28 | } 29 | -------------------------------------------------------------------------------- /invitation/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package invitation 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // List returns all invitations. 12 | func List(ctx context.Context, params *ListParams) (*clerk.InvitationList, error) { 13 | return getClient().List(ctx, params) 14 | } 15 | 16 | // Create adds a new identifier to the allowlist. 17 | func Create(ctx context.Context, params *CreateParams) (*clerk.Invitation, error) { 18 | return getClient().Create(ctx, params) 19 | } 20 | 21 | // BulkCreate creates multiple invitations. 22 | func BulkCreate(ctx context.Context, params *BulkCreateParams) (*clerk.Invitations, error) { 23 | return getClient().BulkCreate(ctx, params) 24 | } 25 | 26 | // Revoke revokes a pending invitation. 27 | func Revoke(ctx context.Context, id string) (*clerk.Invitation, error) { 28 | return getClient().Revoke(ctx, id) 29 | } 30 | 31 | func getClient() *Client { 32 | return &Client{ 33 | Backend: clerk.GetBackend(), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /invitation/client.go: -------------------------------------------------------------------------------- 1 | package invitation 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "net/url" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | ) 12 | 13 | //go:generate go run ../cmd/gen/main.go 14 | 15 | const path = "/invitations" 16 | 17 | // Client is used to invoke the Invitations API. 18 | type Client struct { 19 | Backend clerk.Backend 20 | } 21 | 22 | func NewClient(config *clerk.ClientConfig) *Client { 23 | return &Client{ 24 | Backend: clerk.NewBackend(&config.BackendConfig), 25 | } 26 | } 27 | 28 | type ListParams struct { 29 | clerk.APIParams 30 | clerk.ListParams 31 | OrderBy *string `json:"order_by,omitempty"` 32 | Query *string `json:"query,omitempty"` 33 | Statuses []string `json:"status,omitempty"` 34 | } 35 | 36 | // ToQuery returns query string values from the params. 37 | func (params *ListParams) ToQuery() url.Values { 38 | q := params.ListParams.ToQuery() 39 | if params.OrderBy != nil { 40 | q.Set("order_by", *params.OrderBy) 41 | } 42 | if params.Query != nil { 43 | q.Set("query", *params.Query) 44 | } 45 | for _, status := range params.Statuses { 46 | q.Add("status", status) 47 | } 48 | return q 49 | } 50 | 51 | // List returns all invitations. 52 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.InvitationList, error) { 53 | req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) 54 | req.SetParams(params) 55 | list := &clerk.InvitationList{} 56 | err := c.Backend.Call(ctx, req, list) 57 | return list, err 58 | } 59 | 60 | type CreateParams struct { 61 | clerk.APIParams 62 | EmailAddress string `json:"email_address"` 63 | PublicMetadata *json.RawMessage `json:"public_metadata,omitempty"` 64 | RedirectURL *string `json:"redirect_url,omitempty"` 65 | Notify *bool `json:"notify,omitempty"` 66 | IgnoreExisting *bool `json:"ignore_existing,omitempty"` 67 | ExpiresInDays *int64 `json:"expires_in_days,omitempty"` 68 | TemplateSlug *string `json:"template_slug,omitempty"` 69 | } 70 | 71 | // Create adds a new identifier to the allowlist. 72 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.Invitation, error) { 73 | req := clerk.NewAPIRequest(http.MethodPost, path) 74 | req.SetParams(params) 75 | invitation := &clerk.Invitation{} 76 | err := c.Backend.Call(ctx, req, invitation) 77 | return invitation, err 78 | } 79 | 80 | type BulkCreateParams struct { 81 | clerk.APIParams 82 | Invitations []*CreateParams 83 | } 84 | 85 | func (b BulkCreateParams) MarshalJSON() ([]byte, error) { 86 | return json.Marshal(b.Invitations) 87 | } 88 | 89 | type bulkCreateResponse struct { 90 | clerk.APIResource 91 | Invitations []*clerk.Invitation 92 | } 93 | 94 | func (b *bulkCreateResponse) UnmarshalJSON(data []byte) error { 95 | return json.Unmarshal(data, &b.Invitations) 96 | } 97 | 98 | // BulkCreate creates multiple invitations. 99 | func (c *Client) BulkCreate(ctx context.Context, params *BulkCreateParams) (*clerk.Invitations, error) { 100 | path, err := clerk.JoinPath(path, "bulk") 101 | if err != nil { 102 | return nil, err 103 | } 104 | 105 | req := clerk.NewAPIRequest(http.MethodPost, path) 106 | req.SetParams(params) 107 | 108 | res := &bulkCreateResponse{} 109 | if err := c.Backend.Call(ctx, req, res); err != nil { 110 | return nil, err 111 | } 112 | 113 | return &clerk.Invitations{ 114 | APIResource: res.APIResource, 115 | Invitations: res.Invitations, 116 | }, nil 117 | } 118 | 119 | // Revoke revokes a pending invitation. 120 | func (c *Client) Revoke(ctx context.Context, id string) (*clerk.Invitation, error) { 121 | path, err := clerk.JoinPath(path, id, "revoke") 122 | if err != nil { 123 | return nil, err 124 | } 125 | req := clerk.NewAPIRequest(http.MethodPost, path) 126 | invitation := &clerk.Invitation{} 127 | err = c.Backend.Call(ctx, req, invitation) 128 | return invitation, err 129 | } 130 | -------------------------------------------------------------------------------- /jwk.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import ( 4 | "crypto/x509" 5 | "encoding/pem" 6 | "fmt" 7 | 8 | "github.com/go-jose/go-jose/v3" 9 | ) 10 | 11 | type JSONWebKeySet struct { 12 | APIResource 13 | Keys []*JSONWebKey `json:"keys"` 14 | } 15 | 16 | type JSONWebKey struct { 17 | APIResource 18 | Key any `json:"key"` 19 | KeyID string `json:"kid"` 20 | Algorithm string `json:"alg"` 21 | Use string `json:"use"` 22 | raw jose.JSONWebKey 23 | } 24 | 25 | func (k *JSONWebKey) UnmarshalJSON(data []byte) error { 26 | err := k.raw.UnmarshalJSON(data) 27 | if err != nil { 28 | return err 29 | } 30 | k.Key = k.raw.Key 31 | k.KeyID = k.raw.KeyID 32 | k.Algorithm = k.raw.Algorithm 33 | k.Use = k.raw.Use 34 | return nil 35 | } 36 | 37 | // JSONWebKeyFromPEM returns a JWK from an RSA key. 38 | func JSONWebKeyFromPEM(key string) (*JSONWebKey, error) { 39 | block, _ := pem.Decode([]byte(key)) 40 | if block == nil { 41 | return nil, fmt.Errorf("invalid PEM-encoded block") 42 | } 43 | 44 | if block.Type != "PUBLIC KEY" { 45 | return nil, fmt.Errorf("invalid key type, expected a public key") 46 | } 47 | 48 | rsaPublicKey, err := x509.ParsePKIXPublicKey(block.Bytes) 49 | if err != nil { 50 | return nil, fmt.Errorf("failed to parse public key: %w", err) 51 | } 52 | 53 | return &JSONWebKey{ 54 | Key: rsaPublicKey, 55 | Algorithm: "RS256", 56 | }, nil 57 | } 58 | -------------------------------------------------------------------------------- /jwks/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package jwks 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Get retrieves a JSON Web Key set. 12 | func Get(ctx context.Context, params *GetParams) (*clerk.JSONWebKeySet, error) { 13 | return getClient().Get(ctx, params) 14 | } 15 | 16 | func getClient() *Client { 17 | return &Client{ 18 | Backend: clerk.GetBackend(), 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /jwks/client.go: -------------------------------------------------------------------------------- 1 | // Package jwks provides access to the JWKS endpoint. 2 | package jwks 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/jwks" 14 | 15 | // Client is used to invoke the JWKS API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | type GetParams struct { 27 | clerk.APIParams 28 | } 29 | 30 | // Get retrieves a JSON Web Key set. 31 | func (c *Client) Get(ctx context.Context, params *GetParams) (*clerk.JSONWebKeySet, error) { 32 | req := clerk.NewAPIRequest(http.MethodGet, path) 33 | req.SetParams(params) 34 | resource := &clerk.JSONWebKeySet{} 35 | err := c.Backend.Call(ctx, req, resource) 36 | return resource, err 37 | } 38 | -------------------------------------------------------------------------------- /jwks/jwk_test.go: -------------------------------------------------------------------------------- 1 | package jwks 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | "testing" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestJWKGet(t *testing.T) { 15 | key := map[string]any{ 16 | "use": "sig", 17 | "kty": "RSA", 18 | "kid": "the-kid", 19 | "alg": "RS256", 20 | "n": "the-key", 21 | "e": "AQAB", 22 | } 23 | out := map[string]any{ 24 | "keys": []map[string]any{key}, 25 | } 26 | raw, err := json.Marshal(out) 27 | require.NoError(t, err) 28 | 29 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 30 | HTTPClient: &http.Client{ 31 | Transport: &clerktest.RoundTripper{ 32 | T: t, 33 | Out: raw, 34 | Path: "/v1/jwks", 35 | Method: http.MethodGet, 36 | }, 37 | }, 38 | })) 39 | jwk, err := Get(context.Background(), &GetParams{}) 40 | require.NoError(t, err) 41 | require.Equal(t, 1, len(jwk.Keys)) 42 | require.NotNil(t, jwk.Keys[0].Key) 43 | require.Equal(t, key["use"], jwk.Keys[0].Use) 44 | require.Equal(t, key["alg"], jwk.Keys[0].Algorithm) 45 | require.Equal(t, key["kid"], jwk.Keys[0].KeyID) 46 | } 47 | -------------------------------------------------------------------------------- /jwt_template.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type JWTTemplate struct { 6 | APIResource 7 | Object string `json:"object"` 8 | ID string `json:"id"` 9 | Name string `json:"name"` 10 | Claims json.RawMessage `json:"claims"` 11 | Lifetime int64 `json:"lifetime"` 12 | AllowedClockSkew int64 `json:"allowed_clock_skew"` 13 | CustomSigningKey bool `json:"custom_signing_key"` 14 | SigningAlgorithm string `json:"signing_algorithm"` 15 | CreatedAt int64 `json:"created_at"` 16 | UpdatedAt int64 `json:"updated_at"` 17 | } 18 | 19 | type JWTTemplateList struct { 20 | APIResource 21 | JWTTemplates []*JWTTemplate `json:"data"` 22 | TotalCount int64 `json:"total_count"` 23 | } 24 | -------------------------------------------------------------------------------- /jwttemplate/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package jwttemplate 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new JWT template. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.JWTTemplate, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Get returns details about a JWT template. 17 | func Get(ctx context.Context, id string) (*clerk.JWTTemplate, error) { 18 | return getClient().Get(ctx, id) 19 | } 20 | 21 | // Update updates the JWT template specified by id. 22 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.JWTTemplate, error) { 23 | return getClient().Update(ctx, id, params) 24 | } 25 | 26 | // Delete deletes a JWT template. 27 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 28 | return getClient().Delete(ctx, id) 29 | } 30 | 31 | // List returns a list of JWT templates. 32 | func List(ctx context.Context, params *ListParams) (*clerk.JWTTemplateList, error) { 33 | return getClient().List(ctx, params) 34 | } 35 | 36 | func getClient() *Client { 37 | return &Client{ 38 | Backend: clerk.GetBackend(), 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /jwttemplate/client.go: -------------------------------------------------------------------------------- 1 | // Package jwttemplate provides the JWT Templates API. 2 | package jwttemplate 3 | 4 | import ( 5 | "context" 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | ) 12 | 13 | //go:generate go run ../cmd/gen/main.go 14 | 15 | const path = "/jwt_templates" 16 | 17 | // Client is used to invoke the JWT Templates API. 18 | type Client struct { 19 | Backend clerk.Backend 20 | } 21 | 22 | func NewClient(config *clerk.ClientConfig) *Client { 23 | return &Client{ 24 | Backend: clerk.NewBackend(&config.BackendConfig), 25 | } 26 | } 27 | 28 | type CreateParams struct { 29 | clerk.APIParams 30 | Name *string `json:"name,omitempty"` 31 | Claims json.RawMessage `json:"claims,omitempty"` 32 | Lifetime *int64 `json:"lifetime,omitempty"` 33 | AllowedClockSkew *int64 `json:"allowed_clock_skew,omitempty"` 34 | CustomSigningKey *bool `json:"custom_signing_key,omitempty"` 35 | SigningKey *string `json:"signing_key,omitempty"` 36 | SigningAlgorithm *string `json:"signing_algorithm,omitempty"` 37 | } 38 | 39 | // Create creates a new JWT template. 40 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.JWTTemplate, error) { 41 | req := clerk.NewAPIRequest(http.MethodPost, path) 42 | req.SetParams(params) 43 | template := &clerk.JWTTemplate{} 44 | err := c.Backend.Call(ctx, req, template) 45 | return template, err 46 | } 47 | 48 | // Get returns details about a JWT template. 49 | func (c *Client) Get(ctx context.Context, id string) (*clerk.JWTTemplate, error) { 50 | path, err := clerk.JoinPath(path, id) 51 | if err != nil { 52 | return nil, err 53 | } 54 | req := clerk.NewAPIRequest(http.MethodGet, path) 55 | template := &clerk.JWTTemplate{} 56 | err = c.Backend.Call(ctx, req, template) 57 | return template, err 58 | } 59 | 60 | type UpdateParams struct { 61 | clerk.APIParams 62 | Name *string `json:"name,omitempty"` 63 | Claims json.RawMessage `json:"claims,omitempty"` 64 | Lifetime *int64 `json:"lifetime,omitempty"` 65 | AllowedClockSkew *int64 `json:"allowed_clock_skew,omitempty"` 66 | CustomSigningKey *bool `json:"custom_signing_key,omitempty"` 67 | SigningKey *string `json:"signing_key,omitempty"` 68 | SigningAlgorithm *string `json:"signing_algorithm,omitempty"` 69 | } 70 | 71 | // Update updates the JWT template specified by id. 72 | func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (*clerk.JWTTemplate, error) { 73 | path, err := clerk.JoinPath(path, id) 74 | if err != nil { 75 | return nil, err 76 | } 77 | req := clerk.NewAPIRequest(http.MethodPatch, path) 78 | req.SetParams(params) 79 | template := &clerk.JWTTemplate{} 80 | err = c.Backend.Call(ctx, req, template) 81 | return template, err 82 | } 83 | 84 | // Delete deletes a JWT template. 85 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 86 | path, err := clerk.JoinPath(path, id) 87 | if err != nil { 88 | return nil, err 89 | } 90 | req := clerk.NewAPIRequest(http.MethodDelete, path) 91 | template := &clerk.DeletedResource{} 92 | err = c.Backend.Call(ctx, req, template) 93 | return template, err 94 | } 95 | 96 | type ListParams struct { 97 | clerk.APIParams 98 | } 99 | 100 | // List returns a list of JWT templates. 101 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.JWTTemplateList, error) { 102 | req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) 103 | req.SetParams(params) 104 | list := &clerk.JWTTemplateList{} 105 | err := c.Backend.Call(ctx, req, list) 106 | return list, err 107 | } 108 | -------------------------------------------------------------------------------- /jwttemplate/client_test.go: -------------------------------------------------------------------------------- 1 | package jwttemplate 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "net/url" 9 | "testing" 10 | 11 | "github.com/clerk/clerk-sdk-go/v2" 12 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func TestJWTTemplateClientCreate(t *testing.T) { 17 | t.Parallel() 18 | name := "the-name" 19 | id := "jtmpl_123" 20 | config := &clerk.ClientConfig{} 21 | config.HTTPClient = &http.Client{ 22 | Transport: &clerktest.RoundTripper{ 23 | T: t, 24 | In: json.RawMessage(fmt.Sprintf(`{"name":"%s"}`, name)), 25 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), 26 | Method: http.MethodPost, 27 | Path: "/v1/jwt_templates", 28 | }, 29 | } 30 | client := NewClient(config) 31 | jwtTemplate, err := client.Create(context.Background(), &CreateParams{ 32 | Name: clerk.String(name), 33 | }) 34 | require.NoError(t, err) 35 | require.Equal(t, id, jwtTemplate.ID) 36 | require.Equal(t, name, jwtTemplate.Name) 37 | } 38 | 39 | func TestJWTTemplateClientCreate_Error(t *testing.T) { 40 | t.Parallel() 41 | config := &clerk.ClientConfig{} 42 | config.HTTPClient = &http.Client{ 43 | Transport: &clerktest.RoundTripper{ 44 | T: t, 45 | Status: http.StatusBadRequest, 46 | Out: json.RawMessage(`{ 47 | "errors":[{ 48 | "code":"create-error-code" 49 | }], 50 | "clerk_trace_id":"create-trace-id" 51 | }`), 52 | }, 53 | } 54 | client := NewClient(config) 55 | _, err := client.Create(context.Background(), &CreateParams{}) 56 | require.Error(t, err) 57 | apiErr, ok := err.(*clerk.APIErrorResponse) 58 | require.True(t, ok) 59 | require.Equal(t, "create-trace-id", apiErr.TraceID) 60 | require.Equal(t, 1, len(apiErr.Errors)) 61 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 62 | } 63 | 64 | func TestJWTTemplateClientGet(t *testing.T) { 65 | t.Parallel() 66 | id := "jtmpl_123" 67 | name := "the-name" 68 | config := &clerk.ClientConfig{} 69 | config.HTTPClient = &http.Client{ 70 | Transport: &clerktest.RoundTripper{ 71 | T: t, 72 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), 73 | Method: http.MethodGet, 74 | Path: "/v1/jwt_templates/" + id, 75 | }, 76 | } 77 | client := NewClient(config) 78 | jwtTemplate, err := client.Get(context.Background(), id) 79 | require.NoError(t, err) 80 | require.Equal(t, id, jwtTemplate.ID) 81 | require.Equal(t, name, jwtTemplate.Name) 82 | } 83 | 84 | func TestJWTTemplateClientUpdate(t *testing.T) { 85 | t.Parallel() 86 | id := "jtmpl_123" 87 | name := "the-name" 88 | config := &clerk.ClientConfig{} 89 | config.HTTPClient = &http.Client{ 90 | Transport: &clerktest.RoundTripper{ 91 | T: t, 92 | In: json.RawMessage(fmt.Sprintf(`{"name":"%s"}`, name)), 93 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","name":"%s"}`, id, name)), 94 | Method: http.MethodPatch, 95 | Path: "/v1/jwt_templates/" + id, 96 | }, 97 | } 98 | client := NewClient(config) 99 | jwtTemplate, err := client.Update(context.Background(), id, &UpdateParams{ 100 | Name: clerk.String(name), 101 | }) 102 | require.NoError(t, err) 103 | require.Equal(t, id, jwtTemplate.ID) 104 | require.Equal(t, name, jwtTemplate.Name) 105 | } 106 | 107 | func TestJWTTemplateClientUpdate_Error(t *testing.T) { 108 | t.Parallel() 109 | config := &clerk.ClientConfig{} 110 | config.HTTPClient = &http.Client{ 111 | Transport: &clerktest.RoundTripper{ 112 | T: t, 113 | Status: http.StatusBadRequest, 114 | Out: json.RawMessage(`{ 115 | "errors":[{ 116 | "code":"update-error-code" 117 | }], 118 | "clerk_trace_id":"update-trace-id" 119 | }`), 120 | }, 121 | } 122 | client := NewClient(config) 123 | _, err := client.Update(context.Background(), "jtmpl_123", &UpdateParams{}) 124 | require.Error(t, err) 125 | apiErr, ok := err.(*clerk.APIErrorResponse) 126 | require.True(t, ok) 127 | require.Equal(t, "update-trace-id", apiErr.TraceID) 128 | require.Equal(t, 1, len(apiErr.Errors)) 129 | require.Equal(t, "update-error-code", apiErr.Errors[0].Code) 130 | } 131 | 132 | func TestJWTTemplateClientDelete(t *testing.T) { 133 | t.Parallel() 134 | id := "jtmpl_456" 135 | config := &clerk.ClientConfig{} 136 | config.HTTPClient = &http.Client{ 137 | Transport: &clerktest.RoundTripper{ 138 | T: t, 139 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), 140 | Method: http.MethodDelete, 141 | Path: "/v1/jwt_templates/" + id, 142 | }, 143 | } 144 | client := NewClient(config) 145 | jwtTemplate, err := client.Delete(context.Background(), id) 146 | require.NoError(t, err) 147 | require.Equal(t, id, jwtTemplate.ID) 148 | require.True(t, jwtTemplate.Deleted) 149 | } 150 | 151 | func TestJWTTemplateClientList(t *testing.T) { 152 | t.Parallel() 153 | config := &clerk.ClientConfig{} 154 | config.HTTPClient = &http.Client{ 155 | Transport: &clerktest.RoundTripper{ 156 | T: t, 157 | Out: json.RawMessage(`{ 158 | "data": [{"id":"jtmpl_123","name":"the-name"}], 159 | "total_count": 1 160 | }`), 161 | Method: http.MethodGet, 162 | Path: "/v1/jwt_templates", 163 | Query: &url.Values{ 164 | "paginated": []string{"true"}, 165 | }, 166 | }, 167 | } 168 | client := NewClient(config) 169 | list, err := client.List(context.Background(), &ListParams{}) 170 | require.NoError(t, err) 171 | require.Equal(t, int64(1), list.TotalCount) 172 | require.Equal(t, 1, len(list.JWTTemplates)) 173 | require.Equal(t, "jtmpl_123", list.JWTTemplates[0].ID) 174 | require.Equal(t, "the-name", list.JWTTemplates[0].Name) 175 | } 176 | -------------------------------------------------------------------------------- /oauth_access_token.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type OAuthAccessToken struct { 6 | ExternalAccountID string `json:"external_account_id"` 7 | Object string `json:"object"` 8 | Token string `json:"token"` 9 | Provider string `json:"provider"` 10 | PublicMetadata json.RawMessage `json:"public_metadata"` 11 | Label *string `json:"label"` 12 | // Only set in OAuth 2.0 tokens 13 | Scopes []string `json:"scopes,omitempty"` 14 | // Only set in OAuth 1.0 tokens 15 | TokenSecret *string `json:"token_secret,omitempty"` 16 | } 17 | 18 | type OAuthAccessTokenList struct { 19 | APIResource 20 | OAuthAccessTokens []*OAuthAccessToken `json:"data"` 21 | TotalCount int64 `json:"total_count"` 22 | } 23 | -------------------------------------------------------------------------------- /oauth_application.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type OAuthApplication struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | InstanceID string `json:"instance_id"` 8 | Name string `json:"name"` 9 | ClientID string `json:"client_id"` 10 | Public bool `json:"public"` 11 | DynamicallyRegistered bool `json:"dynamically_registered"` 12 | ConsentScreenEnabled bool `json:"consent_screen_enabled"` 13 | Scopes string `json:"scopes"` 14 | CallbackURL string `json:"callback_url"` 15 | DiscoveryURL string `json:"discovery_url"` 16 | AuthorizeURL string `json:"authorize_url"` 17 | TokenFetchURL string `json:"token_fetch_url"` 18 | UserInfoURL string `json:"user_info_url"` 19 | CreatedAt int64 `json:"created_at"` 20 | UpdatedAt int64 `json:"updated_at"` 21 | ClientSecret *string `json:"client_secret,omitempty"` 22 | } 23 | 24 | type OAuthApplicationList struct { 25 | APIResource 26 | OAuthApplications []*OAuthApplication `json:"data"` 27 | TotalCount int64 `json:"total_count"` 28 | } 29 | -------------------------------------------------------------------------------- /oauthapplication/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package oauthapplication 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Get fetches a single OAuth application by its ID. 12 | func Get(ctx context.Context, id string) (*clerk.OAuthApplication, error) { 13 | return getClient().Get(ctx, id) 14 | } 15 | 16 | // List retrieves all OAuth applications. 17 | func List(ctx context.Context, params *ListParams) (*clerk.OAuthApplicationList, error) { 18 | return getClient().List(ctx, params) 19 | } 20 | 21 | // Create creates a new OAuth application with the given parameters. 22 | func Create(ctx context.Context, params *CreateParams) (*clerk.OAuthApplication, error) { 23 | return getClient().Create(ctx, params) 24 | } 25 | 26 | // Update updates an existing OAuth application. 27 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.OAuthApplication, error) { 28 | return getClient().Update(ctx, id, params) 29 | } 30 | 31 | // Delete deletes the given OAuth application 32 | func DeleteOAuthApplication(ctx context.Context, id string) (*clerk.DeletedResource, error) { 33 | return getClient().DeleteOAuthApplication(ctx, id) 34 | } 35 | 36 | // RotateClientSecret rotates the OAuth application's client secret 37 | func RotateClientSecret(ctx context.Context, id string) (*clerk.OAuthApplication, error) { 38 | return getClient().RotateClientSecret(ctx, id) 39 | } 40 | 41 | func getClient() *Client { 42 | return &Client{ 43 | Backend: clerk.GetBackend(), 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /oauthapplication/client.go: -------------------------------------------------------------------------------- 1 | // Package oauthapplication provides the OAuth applications API. 2 | package oauthapplication 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | "net/url" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/oauth_applications" 15 | 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | // Get fetches a single OAuth application by its ID. 27 | func (c *Client) Get(ctx context.Context, id string) (*clerk.OAuthApplication, error) { 28 | path, err := clerk.JoinPath(path, id) 29 | if err != nil { 30 | return nil, err 31 | } 32 | req := clerk.NewAPIRequest(http.MethodGet, path) 33 | resource := &clerk.OAuthApplication{} 34 | err = c.Backend.Call(ctx, req, resource) 35 | return resource, err 36 | } 37 | 38 | type ListParams struct { 39 | clerk.APIParams 40 | clerk.ListParams 41 | } 42 | 43 | func (params *ListParams) ToQuery() url.Values { 44 | return params.ListParams.ToQuery() 45 | } 46 | 47 | // List retrieves all OAuth applications. 48 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.OAuthApplicationList, error) { 49 | req := clerk.NewAPIRequest(http.MethodGet, path) 50 | req.SetParams(params) 51 | list := &clerk.OAuthApplicationList{} 52 | err := c.Backend.Call(ctx, req, list) 53 | return list, err 54 | } 55 | 56 | type CreateParams struct { 57 | clerk.APIParams 58 | Name string `json:"name"` 59 | CallbackURL string `json:"callback_url"` 60 | Scopes string `json:"scopes"` 61 | Public bool `json:"public"` 62 | ConsentScreenEnabled *bool `json:"consent_screen_enabled"` 63 | } 64 | 65 | // Create creates a new OAuth application with the given parameters. 66 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.OAuthApplication, error) { 67 | req := clerk.NewAPIRequest(http.MethodPost, path) 68 | req.SetParams(params) 69 | authApplication := &clerk.OAuthApplication{} 70 | err := c.Backend.Call(ctx, req, authApplication) 71 | return authApplication, err 72 | } 73 | 74 | type UpdateParams struct { 75 | clerk.APIParams 76 | Name *string `json:"name,omitempty"` 77 | CallbackURL *string `json:"callback_url,omitempty"` 78 | Scopes *string `json:"scopes,omitempty"` 79 | ConsentScreenEnabled *bool `json:"consent_screen_enabled,omitempty"` 80 | } 81 | 82 | // Update updates an existing OAuth application. 83 | func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (*clerk.OAuthApplication, error) { 84 | path, err := clerk.JoinPath(path, id) 85 | if err != nil { 86 | return nil, err 87 | } 88 | req := clerk.NewAPIRequest(http.MethodPatch, path) 89 | req.SetParams(params) 90 | authApplication := &clerk.OAuthApplication{} 91 | err = c.Backend.Call(ctx, req, authApplication) 92 | return authApplication, err 93 | } 94 | 95 | // Delete deletes the given OAuth application 96 | func (c *Client) DeleteOAuthApplication(ctx context.Context, id string) (*clerk.DeletedResource, error) { 97 | path, err := clerk.JoinPath(path, id) 98 | if err != nil { 99 | return nil, err 100 | } 101 | req := clerk.NewAPIRequest(http.MethodDelete, path) 102 | authApplication := &clerk.DeletedResource{} 103 | err = c.Backend.Call(ctx, req, authApplication) 104 | return authApplication, err 105 | } 106 | 107 | // RotateClientSecret rotates the OAuth application's client secret 108 | func (c *Client) RotateClientSecret(ctx context.Context, id string) (*clerk.OAuthApplication, error) { 109 | path, err := clerk.JoinPath(path, id, "rotate_secret") 110 | if err != nil { 111 | return nil, err 112 | } 113 | req := clerk.NewAPIRequest(http.MethodPost, path) 114 | authApplication := &clerk.OAuthApplication{} 115 | err = c.Backend.Call(ctx, req, authApplication) 116 | return authApplication, err 117 | } 118 | -------------------------------------------------------------------------------- /organization.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type Organization struct { 6 | APIResource 7 | Object string `json:"object"` 8 | ID string `json:"id"` 9 | Name string `json:"name"` 10 | Slug string `json:"slug"` 11 | ImageURL *string `json:"image_url"` 12 | HasImage bool `json:"has_image"` 13 | MembersCount *int64 `json:"members_count,omitempty"` 14 | MissingMemberWithElevatedPermissions *bool `json:"missing_member_with_elevated_permissions,omitempty"` 15 | PendingInvitationsCount *int64 `json:"pending_invitations_count,omitempty"` 16 | MaxAllowedMemberships int64 `json:"max_allowed_memberships"` 17 | AdminDeleteEnabled bool `json:"admin_delete_enabled"` 18 | PublicMetadata json.RawMessage `json:"public_metadata"` 19 | PrivateMetadata json.RawMessage `json:"private_metadata"` 20 | CreatedBy string `json:"created_by"` 21 | CreatedAt int64 `json:"created_at"` 22 | UpdatedAt int64 `json:"updated_at"` 23 | } 24 | 25 | type OrganizationList struct { 26 | APIResource 27 | Organizations []*Organization `json:"data"` 28 | TotalCount int64 `json:"total_count"` 29 | } 30 | -------------------------------------------------------------------------------- /organization/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package organization 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new organization. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.Organization, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Get retrieves details for an organization. 17 | // The organization can be fetched by either the ID or its slug. 18 | func Get(ctx context.Context, idOrSlug string) (*clerk.Organization, error) { 19 | return getClient().Get(ctx, idOrSlug) 20 | } 21 | 22 | // GetWithParams retrieves details for an organization. 23 | // The organization can be fetched by either the ID or its slug. 24 | func GetWithParams(ctx context.Context, idOrSlug string, params *GetParams) (*clerk.Organization, error) { 25 | return getClient().GetWithParams(ctx, idOrSlug, params) 26 | } 27 | 28 | // Update updates an organization. 29 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.Organization, error) { 30 | return getClient().Update(ctx, id, params) 31 | } 32 | 33 | // UpdateMetadata updates the organization's metadata by merging the 34 | // provided values with the existing ones. 35 | func UpdateMetadata(ctx context.Context, id string, params *UpdateMetadataParams) (*clerk.Organization, error) { 36 | return getClient().UpdateMetadata(ctx, id, params) 37 | } 38 | 39 | // Delete deletes an organization. 40 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 41 | return getClient().Delete(ctx, id) 42 | } 43 | 44 | // UpdateLogo sets or replaces the organization's logo. 45 | func UpdateLogo(ctx context.Context, id string, params *UpdateLogoParams) (*clerk.Organization, error) { 46 | return getClient().UpdateLogo(ctx, id, params) 47 | } 48 | 49 | // DeleteLogo removes the organization's logo. 50 | func DeleteLogo(ctx context.Context, id string) (*clerk.Organization, error) { 51 | return getClient().DeleteLogo(ctx, id) 52 | } 53 | 54 | // List returns a list of organizations. 55 | func List(ctx context.Context, params *ListParams) (*clerk.OrganizationList, error) { 56 | return getClient().List(ctx, params) 57 | } 58 | 59 | func getClient() *Client { 60 | return &Client{ 61 | Backend: clerk.GetBackend(), 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /organization_domain.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type OrganizationDomainVerification struct { 4 | Status string `json:"status"` 5 | Strategy string `json:"strategy"` 6 | Attempts int64 `json:"attempts"` 7 | ExpireAt *int64 `json:"expire_at"` 8 | } 9 | 10 | type OrganizationDomain struct { 11 | APIResource 12 | Object string `json:"object"` 13 | ID string `json:"id"` 14 | OrganizationID string `json:"organization_id"` 15 | Name string `json:"name"` 16 | EnrollmentMode string `json:"enrollment_mode"` 17 | AffiliationEmailAddress *string `json:"affiliation_email_address"` 18 | Verification *OrganizationDomainVerification `json:"verification"` 19 | TotalPendingInvitations int64 `json:"total_pending_invitations"` 20 | TotalPendingSuggestions int64 `json:"total_pending_suggestions"` 21 | CreatedAt int64 `json:"created_at"` 22 | UpdatedAt int64 `json:"updated_at"` 23 | } 24 | 25 | type OrganizationDomainList struct { 26 | APIResource 27 | OrganizationDomains []*OrganizationDomain `json:"data"` 28 | TotalCount int64 `json:"total_count"` 29 | } 30 | -------------------------------------------------------------------------------- /organization_invitation.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type PublicOrganizationData struct { 6 | ID string `json:"id"` 7 | Name string `json:"name"` 8 | Slug string `json:"slug"` 9 | ImageURL *string `json:"image_url,omitempty"` 10 | HasImage bool `json:"has_image"` 11 | } 12 | 13 | type OrganizationInvitation struct { 14 | APIResource 15 | Object string `json:"object"` 16 | ID string `json:"id"` 17 | EmailAddress string `json:"email_address"` 18 | Role string `json:"role"` 19 | RoleName string `json:"role_name"` 20 | OrganizationID string `json:"organization_id"` 21 | PublicOrganizationData *PublicOrganizationData `json:"public_organization_data,omitempty"` 22 | Status string `json:"status"` 23 | PublicMetadata json.RawMessage `json:"public_metadata"` 24 | PrivateMetadata json.RawMessage `json:"private_metadata"` 25 | ExpiresAt *int64 `json:"expires_at,omitempty"` 26 | CreatedAt int64 `json:"created_at"` 27 | UpdatedAt int64 `json:"updated_at"` 28 | } 29 | 30 | type OrganizationInvitationList struct { 31 | APIResource 32 | OrganizationInvitations []*OrganizationInvitation `json:"data"` 33 | TotalCount int64 `json:"total_count"` 34 | } 35 | -------------------------------------------------------------------------------- /organization_membership.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type OrganizationMembership struct { 6 | APIResource 7 | Object string `json:"object"` 8 | ID string `json:"id"` 9 | Organization *Organization `json:"organization"` 10 | Permissions []string `json:"permissions"` 11 | PublicMetadata json.RawMessage `json:"public_metadata"` 12 | PrivateMetadata json.RawMessage `json:"private_metadata"` 13 | Role string `json:"role"` 14 | RoleName string `json:"role_name"` 15 | CreatedAt int64 `json:"created_at"` 16 | UpdatedAt int64 `json:"updated_at"` 17 | PublicUserData *OrganizationMembershipPublicUserData `json:"public_user_data,omitempty"` 18 | } 19 | 20 | type OrganizationMembershipList struct { 21 | APIResource 22 | OrganizationMemberships []*OrganizationMembership `json:"data"` 23 | TotalCount int64 `json:"total_count"` 24 | } 25 | 26 | type OrganizationMembershipPublicUserData struct { 27 | UserID string `json:"user_id"` 28 | FirstName *string `json:"first_name"` 29 | LastName *string `json:"last_name"` 30 | ImageURL *string `json:"image_url"` 31 | HasImage bool `json:"has_image"` 32 | Identifier string `json:"identifier"` 33 | } 34 | -------------------------------------------------------------------------------- /organizationdomain/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package organizationdomain 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create adds a new domain to the organization. 12 | func Create(ctx context.Context, organizationID string, params *CreateParams) (*clerk.OrganizationDomain, error) { 13 | return getClient().Create(ctx, organizationID, params) 14 | } 15 | 16 | // Update updates an organization domain. 17 | func Update(ctx context.Context, params *UpdateParams) (*clerk.OrganizationDomain, error) { 18 | return getClient().Update(ctx, params) 19 | } 20 | 21 | // Delete removes a domain from an organization. 22 | func Delete(ctx context.Context, params *DeleteParams) (*clerk.DeletedResource, error) { 23 | return getClient().Delete(ctx, params) 24 | } 25 | 26 | // List returns a list of organization domains. 27 | func List(ctx context.Context, organizationID string, params *ListParams) (*clerk.OrganizationDomainList, error) { 28 | return getClient().List(ctx, organizationID, params) 29 | } 30 | 31 | func getClient() *Client { 32 | return &Client{ 33 | Backend: clerk.GetBackend(), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /organizationdomain/client.go: -------------------------------------------------------------------------------- 1 | // Package organizationdomain provides the Organization Domains API. 2 | package organizationdomain 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | "net/url" 8 | "strconv" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | ) 12 | 13 | //go:generate go run ../cmd/gen/main.go 14 | 15 | const path = "/organizations" 16 | 17 | // Client is used to invoke the Organization Domains API. 18 | type Client struct { 19 | Backend clerk.Backend 20 | } 21 | 22 | func NewClient(config *clerk.ClientConfig) *Client { 23 | return &Client{ 24 | Backend: clerk.NewBackend(&config.BackendConfig), 25 | } 26 | } 27 | 28 | type CreateParams struct { 29 | clerk.APIParams 30 | Name *string `json:"name,omitempty"` 31 | EnrollmentMode *string `json:"enrollment_mode,omitempty"` 32 | Verified *bool `json:"verified,omitempty"` 33 | } 34 | 35 | // Create adds a new domain to the organization. 36 | func (c *Client) Create(ctx context.Context, organizationID string, params *CreateParams) (*clerk.OrganizationDomain, error) { 37 | path, err := clerk.JoinPath(path, organizationID, "/domains") 38 | if err != nil { 39 | return nil, err 40 | } 41 | req := clerk.NewAPIRequest(http.MethodPost, path) 42 | req.SetParams(params) 43 | domain := &clerk.OrganizationDomain{} 44 | err = c.Backend.Call(ctx, req, domain) 45 | return domain, err 46 | } 47 | 48 | type UpdateParams struct { 49 | clerk.APIParams 50 | OrganizationID string `json:"-"` 51 | DomainID string `json:"-"` 52 | EnrollmentMode *string `json:"enrollment_mode,omitempty"` 53 | Verified *bool `json:"verified,omitempty"` 54 | } 55 | 56 | // Update updates an organization domain. 57 | func (c *Client) Update(ctx context.Context, params *UpdateParams) (*clerk.OrganizationDomain, error) { 58 | path, err := clerk.JoinPath(path, params.OrganizationID, "/domains", params.DomainID) 59 | if err != nil { 60 | return nil, err 61 | } 62 | req := clerk.NewAPIRequest(http.MethodPatch, path) 63 | req.SetParams(params) 64 | domain := &clerk.OrganizationDomain{} 65 | err = c.Backend.Call(ctx, req, domain) 66 | return domain, err 67 | } 68 | 69 | type DeleteParams struct { 70 | clerk.APIParams 71 | OrganizationID string `json:"-"` 72 | DomainID string `json:"-"` 73 | } 74 | 75 | // Delete removes a domain from an organization. 76 | func (c *Client) Delete(ctx context.Context, params *DeleteParams) (*clerk.DeletedResource, error) { 77 | path, err := clerk.JoinPath(path, params.OrganizationID, "/domains", params.DomainID) 78 | if err != nil { 79 | return nil, err 80 | } 81 | req := clerk.NewAPIRequest(http.MethodDelete, path) 82 | res := &clerk.DeletedResource{} 83 | err = c.Backend.Call(ctx, req, res) 84 | return res, err 85 | } 86 | 87 | type ListParams struct { 88 | clerk.APIParams 89 | clerk.ListParams 90 | Verified *bool `json:"verified,omitempty"` 91 | EnrollmentModes *[]string `json:"enrollment_mode,omitempty"` 92 | } 93 | 94 | // ToQuery returns the parameters as url.Values so they can be used 95 | // in a URL query string. 96 | func (params *ListParams) ToQuery() url.Values { 97 | q := params.ListParams.ToQuery() 98 | 99 | if params.Verified != nil { 100 | q.Set("verified", strconv.FormatBool(*params.Verified)) 101 | } 102 | 103 | if params.EnrollmentModes != nil && len(*params.EnrollmentModes) > 0 { 104 | q["enrollment_mode"] = *params.EnrollmentModes 105 | } 106 | return q 107 | } 108 | 109 | // List returns a list of organization domains. 110 | func (c *Client) List(ctx context.Context, organizationID string, params *ListParams) (*clerk.OrganizationDomainList, error) { 111 | path, err := clerk.JoinPath(path, organizationID, "/domains") 112 | if err != nil { 113 | return nil, err 114 | } 115 | req := clerk.NewAPIRequest(http.MethodGet, path) 116 | req.SetParams(params) 117 | domains := &clerk.OrganizationDomainList{} 118 | err = c.Backend.Call(ctx, req, domains) 119 | return domains, err 120 | } 121 | -------------------------------------------------------------------------------- /organizationinvitation/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package organizationinvitation 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates and sends an invitation to join an organization. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.OrganizationInvitation, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // List returns a list of organization invitations 17 | func List(ctx context.Context, params *ListParams) (*clerk.OrganizationInvitationList, error) { 18 | return getClient().List(ctx, params) 19 | } 20 | 21 | // Get retrieves the detail for an organization invitation. 22 | func Get(ctx context.Context, params *GetParams) (*clerk.OrganizationInvitation, error) { 23 | return getClient().Get(ctx, params) 24 | } 25 | 26 | // Revoke marks the organization invitation as revoked. 27 | func Revoke(ctx context.Context, params *RevokeParams) (*clerk.OrganizationInvitation, error) { 28 | return getClient().Revoke(ctx, params) 29 | } 30 | 31 | // ListAllFromInstance lists all the organization invitations from the current instance 32 | func ListFromInstance(ctx context.Context, params *ListFromInstanceParams) (*clerk.OrganizationInvitationList, error) { 33 | return getClient().ListFromInstance(ctx, params) 34 | } 35 | 36 | func getClient() *Client { 37 | return &Client{ 38 | Backend: clerk.GetBackend(), 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /organizationinvitation/client.go: -------------------------------------------------------------------------------- 1 | // Package organizationinvitation provides the Organization Invitations API. 2 | package organizationinvitation 3 | 4 | import ( 5 | "context" 6 | "encoding/json" 7 | "net/http" 8 | "net/url" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | ) 12 | 13 | //go:generate go run ../cmd/gen/main.go 14 | 15 | const path = "/organizations" 16 | 17 | // Client is used to invoke the Organization Invitations API. 18 | type Client struct { 19 | Backend clerk.Backend 20 | } 21 | 22 | func NewClient(config *clerk.ClientConfig) *Client { 23 | return &Client{ 24 | Backend: clerk.NewBackend(&config.BackendConfig), 25 | } 26 | } 27 | 28 | type CreateParams struct { 29 | clerk.APIParams 30 | EmailAddress *string `json:"email_address,omitempty"` 31 | Role *string `json:"role,omitempty"` 32 | RedirectURL *string `json:"redirect_url,omitempty"` 33 | InviterUserID *string `json:"inviter_user_id,omitempty"` 34 | PublicMetadata *json.RawMessage `json:"public_metadata,omitempty"` 35 | PrivateMetadata *json.RawMessage `json:"private_metadata,omitempty"` 36 | OrganizationID string `json:"-"` 37 | ExpiresInDays *int64 `json:"expires_in_days,omitempty"` 38 | } 39 | 40 | // Create creates and sends an invitation to join an organization. 41 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.OrganizationInvitation, error) { 42 | path, err := clerk.JoinPath(path, params.OrganizationID, "/invitations") 43 | if err != nil { 44 | return nil, err 45 | } 46 | req := clerk.NewAPIRequest(http.MethodPost, path) 47 | req.SetParams(params) 48 | invitation := &clerk.OrganizationInvitation{} 49 | err = c.Backend.Call(ctx, req, invitation) 50 | return invitation, err 51 | } 52 | 53 | type ListParams struct { 54 | clerk.APIParams 55 | clerk.ListParams 56 | OrganizationID string 57 | Statuses *[]string 58 | } 59 | 60 | func (p *ListParams) ToQuery() url.Values { 61 | q := p.ListParams.ToQuery() 62 | 63 | if p.Statuses != nil && len(*p.Statuses) > 0 { 64 | q["status"] = *p.Statuses 65 | } 66 | 67 | return q 68 | } 69 | 70 | // List returns a list of organization invitations 71 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.OrganizationInvitationList, error) { 72 | path, err := clerk.JoinPath(path, params.OrganizationID, "/invitations") 73 | if err != nil { 74 | return nil, err 75 | } 76 | req := clerk.NewAPIRequest(http.MethodGet, path) 77 | req.SetParams(params) 78 | invitation := &clerk.OrganizationInvitationList{} 79 | err = c.Backend.Call(ctx, req, invitation) 80 | return invitation, err 81 | } 82 | 83 | type GetParams struct { 84 | OrganizationID string 85 | ID string 86 | } 87 | 88 | // Get retrieves the detail for an organization invitation. 89 | func (c *Client) Get(ctx context.Context, params *GetParams) (*clerk.OrganizationInvitation, error) { 90 | path, err := clerk.JoinPath(path, params.OrganizationID, "/invitations", params.ID) 91 | if err != nil { 92 | return nil, err 93 | } 94 | req := clerk.NewAPIRequest(http.MethodGet, path) 95 | invitation := &clerk.OrganizationInvitation{} 96 | err = c.Backend.Call(ctx, req, invitation) 97 | return invitation, err 98 | } 99 | 100 | type RevokeParams struct { 101 | clerk.APIParams 102 | RequestingUserID *string `json:"requesting_user_id,omitempty"` 103 | OrganizationID string `json:"-"` 104 | ID string `json:"-"` 105 | } 106 | 107 | // Revoke marks the organization invitation as revoked. 108 | func (c *Client) Revoke(ctx context.Context, params *RevokeParams) (*clerk.OrganizationInvitation, error) { 109 | path, err := clerk.JoinPath(path, params.OrganizationID, "/invitations", params.ID, "/revoke") 110 | if err != nil { 111 | return nil, err 112 | } 113 | req := clerk.NewAPIRequest(http.MethodPost, path) 114 | req.SetParams(params) 115 | invitation := &clerk.OrganizationInvitation{} 116 | err = c.Backend.Call(ctx, req, invitation) 117 | return invitation, err 118 | } 119 | 120 | type ListFromInstanceParams struct { 121 | clerk.APIParams 122 | clerk.ListParams 123 | Statuses *[]string `json:"statuses,omitempty"` 124 | Query *string `json:"query,omitempty"` 125 | OrderBy *string `json:"order_by,omitempty"` 126 | } 127 | 128 | func (p *ListFromInstanceParams) ToQuery() url.Values { 129 | q := p.ListParams.ToQuery() 130 | 131 | if p.Statuses != nil && len(*p.Statuses) > 0 { 132 | q["status"] = *p.Statuses 133 | } 134 | 135 | if p.Query != nil { 136 | q.Add("query", *p.Query) 137 | } 138 | 139 | if p.OrderBy != nil { 140 | q.Add("order_by", *p.OrderBy) 141 | } 142 | 143 | return q 144 | } 145 | 146 | // ListAllFromInstance lists all the organization invitations from the current instance 147 | func (c *Client) ListFromInstance(ctx context.Context, params *ListFromInstanceParams) (*clerk.OrganizationInvitationList, error) { 148 | path, err := clerk.JoinPath("/organization_invitations") 149 | if err != nil { 150 | return nil, err 151 | } 152 | req := clerk.NewAPIRequest(http.MethodGet, path) 153 | req.SetParams(params) 154 | invitation := &clerk.OrganizationInvitationList{} 155 | err = c.Backend.Call(ctx, req, invitation) 156 | return invitation, err 157 | } 158 | -------------------------------------------------------------------------------- /organizationmembership/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package organizationmembership 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create adds a new member to the organization. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.OrganizationMembership, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Update updates an organization membership. 17 | func Update(ctx context.Context, params *UpdateParams) (*clerk.OrganizationMembership, error) { 18 | return getClient().Update(ctx, params) 19 | } 20 | 21 | // Delete removes a member from an organization. 22 | func Delete(ctx context.Context, params *DeleteParams) (*clerk.OrganizationMembership, error) { 23 | return getClient().Delete(ctx, params) 24 | } 25 | 26 | // List returns a list of organization memberships. 27 | func List(ctx context.Context, params *ListParams) (*clerk.OrganizationMembershipList, error) { 28 | return getClient().List(ctx, params) 29 | } 30 | 31 | func getClient() *Client { 32 | return &Client{ 33 | Backend: clerk.GetBackend(), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /phone_number.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type PhoneNumber struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | PhoneNumber string `json:"phone_number"` 8 | ReservedForSecondFactor bool `json:"reserved_for_second_factor"` 9 | DefaultSecondFactor bool `json:"default_second_factor"` 10 | Reserved bool `json:"reserved"` 11 | Verification *Verification `json:"verification"` 12 | LinkedTo []*LinkedIdentification `json:"linked_to"` 13 | BackupCodes []string `json:"backup_codes"` 14 | } 15 | -------------------------------------------------------------------------------- /phonenumber/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package phonenumber 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new phone number. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.PhoneNumber, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Get retrieves a phone number. 17 | func Get(ctx context.Context, id string) (*clerk.PhoneNumber, error) { 18 | return getClient().Get(ctx, id) 19 | } 20 | 21 | // Update updates the phone number specified by id. 22 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.PhoneNumber, error) { 23 | return getClient().Update(ctx, id, params) 24 | } 25 | 26 | // Delete deletes a phone number. 27 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 28 | return getClient().Delete(ctx, id) 29 | } 30 | 31 | func getClient() *Client { 32 | return &Client{ 33 | Backend: clerk.GetBackend(), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /phonenumber/client.go: -------------------------------------------------------------------------------- 1 | // Package phonenumber provides the Phone Numbers API. 2 | package phonenumber 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/phone_numbers" 14 | 15 | // Client is used to invoke the Phone Numbers API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | type CreateParams struct { 27 | clerk.APIParams 28 | UserID *string `json:"user_id,omitempty"` 29 | PhoneNumber *string `json:"phone_number,omitempty"` 30 | Verified *bool `json:"verified,omitempty"` 31 | Primary *bool `json:"primary,omitempty"` 32 | } 33 | 34 | // Create creates a new phone number. 35 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.PhoneNumber, error) { 36 | req := clerk.NewAPIRequest(http.MethodPost, path) 37 | req.SetParams(params) 38 | resource := &clerk.PhoneNumber{} 39 | err := c.Backend.Call(ctx, req, resource) 40 | return resource, err 41 | } 42 | 43 | // Get retrieves a phone number. 44 | func (c *Client) Get(ctx context.Context, id string) (*clerk.PhoneNumber, error) { 45 | path, err := clerk.JoinPath(path, id) 46 | if err != nil { 47 | return nil, err 48 | } 49 | req := clerk.NewAPIRequest(http.MethodGet, path) 50 | resource := &clerk.PhoneNumber{} 51 | err = c.Backend.Call(ctx, req, resource) 52 | return resource, err 53 | } 54 | 55 | type UpdateParams struct { 56 | clerk.APIParams 57 | Verified *bool `json:"verified,omitempty"` 58 | Primary *bool `json:"primary,omitempty"` 59 | ReservedForSecondFactor *bool `json:"reserved_for_second_factor,omitempty"` 60 | } 61 | 62 | // Update updates the phone number specified by id. 63 | func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (*clerk.PhoneNumber, error) { 64 | path, err := clerk.JoinPath(path, id) 65 | if err != nil { 66 | return nil, err 67 | } 68 | req := clerk.NewAPIRequest(http.MethodPatch, path) 69 | req.SetParams(params) 70 | resource := &clerk.PhoneNumber{} 71 | err = c.Backend.Call(ctx, req, resource) 72 | return resource, err 73 | } 74 | 75 | // Delete deletes a phone number. 76 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 77 | path, err := clerk.JoinPath(path, id) 78 | if err != nil { 79 | return nil, err 80 | } 81 | req := clerk.NewAPIRequest(http.MethodDelete, path) 82 | resource := &clerk.DeletedResource{} 83 | err = c.Backend.Call(ctx, req, resource) 84 | return resource, err 85 | } 86 | -------------------------------------------------------------------------------- /phonenumber/client_test.go: -------------------------------------------------------------------------------- 1 | package phonenumber 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestPhoneNumberClientCreate(t *testing.T) { 16 | t.Parallel() 17 | phone := "+10123456789" 18 | userID := "user_123" 19 | id := "idn_123" 20 | config := &clerk.ClientConfig{} 21 | config.HTTPClient = &http.Client{ 22 | Transport: &clerktest.RoundTripper{ 23 | T: t, 24 | In: json.RawMessage(fmt.Sprintf(`{"phone_number":"%s","user_id":"%s","verified":false}`, phone, userID)), 25 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","phone_number":"%s"}`, id, phone)), 26 | Method: http.MethodPost, 27 | Path: "/v1/phone_numbers", 28 | }, 29 | } 30 | client := NewClient(config) 31 | phoneNumber, err := client.Create(context.Background(), &CreateParams{ 32 | UserID: clerk.String(userID), 33 | PhoneNumber: clerk.String(phone), 34 | Verified: clerk.Bool(false), 35 | }) 36 | require.NoError(t, err) 37 | require.Equal(t, id, phoneNumber.ID) 38 | require.Equal(t, phone, phoneNumber.PhoneNumber) 39 | } 40 | 41 | func TestPhoneNumberClientUpdate(t *testing.T) { 42 | t.Parallel() 43 | id := "idn_123" 44 | config := &clerk.ClientConfig{} 45 | config.HTTPClient = &http.Client{ 46 | Transport: &clerktest.RoundTripper{ 47 | T: t, 48 | In: json.RawMessage(`{"verified":true, "reserved_for_second_factor":true}`), 49 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","reserved_for_second_factor":true,"verification":{"status":"verified"}}`, id)), 50 | Method: http.MethodPatch, 51 | Path: "/v1/phone_numbers/" + id, 52 | }, 53 | } 54 | client := NewClient(config) 55 | phoneNumber, err := client.Update(context.Background(), "idn_123", &UpdateParams{ 56 | Verified: clerk.Bool(true), 57 | ReservedForSecondFactor: clerk.Bool(true), 58 | }) 59 | require.NoError(t, err) 60 | require.Equal(t, id, phoneNumber.ID) 61 | require.Equal(t, "verified", phoneNumber.Verification.Status) 62 | require.Equal(t, true, phoneNumber.ReservedForSecondFactor) 63 | } 64 | 65 | func TestPhoneNumberClientGet(t *testing.T) { 66 | t.Parallel() 67 | id := "idn_123" 68 | config := &clerk.ClientConfig{} 69 | config.HTTPClient = &http.Client{ 70 | Transport: &clerktest.RoundTripper{ 71 | T: t, 72 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","verification":{"status":"verified"}}`, id)), 73 | Method: http.MethodGet, 74 | Path: "/v1/phone_numbers/" + id, 75 | }, 76 | } 77 | client := NewClient(config) 78 | phoneNumber, err := client.Get(context.Background(), id) 79 | require.NoError(t, err) 80 | require.Equal(t, id, phoneNumber.ID) 81 | require.Equal(t, "verified", phoneNumber.Verification.Status) 82 | } 83 | 84 | func TestPhoneNumberClientDelete(t *testing.T) { 85 | t.Parallel() 86 | id := "idn_456" 87 | config := &clerk.ClientConfig{} 88 | config.HTTPClient = &http.Client{ 89 | Transport: &clerktest.RoundTripper{ 90 | T: t, 91 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), 92 | Method: http.MethodDelete, 93 | Path: "/v1/phone_numbers/" + id, 94 | }, 95 | } 96 | client := NewClient(config) 97 | phoneNumber, err := client.Delete(context.Background(), id) 98 | require.NoError(t, err) 99 | require.Equal(t, id, phoneNumber.ID) 100 | require.True(t, phoneNumber.Deleted) 101 | } 102 | -------------------------------------------------------------------------------- /proxy_check.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type ProxyCheck struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | DomainID string `json:"domain_id"` 8 | ProxyURL string `json:"proxy_url"` 9 | Successful bool `json:"successful"` 10 | LastRunAt *int64 `json:"last_run_at"` 11 | CreatedAt int64 `json:"created_at"` 12 | UpdatedAt int64 `json:"updated_at"` 13 | } 14 | -------------------------------------------------------------------------------- /proxycheck/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package proxycheck 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a proxy check. 12 | // 13 | // Deprecated: The operation is deprecated and will be removed in 14 | // future versions. 15 | func Create(ctx context.Context, params *CreateParams) (*clerk.ProxyCheck, error) { 16 | return getClient().Create(ctx, params) 17 | } 18 | 19 | func getClient() *Client { 20 | return &Client{ 21 | Backend: clerk.GetBackend(), 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /proxycheck/client.go: -------------------------------------------------------------------------------- 1 | // Package proxycheck provides the Proxy Checks API. 2 | // 3 | // Deprecated: The Proxy Checks API is deprecated and will be 4 | // removed in future versions. 5 | package proxycheck 6 | 7 | import ( 8 | "context" 9 | "net/http" 10 | 11 | "github.com/clerk/clerk-sdk-go/v2" 12 | ) 13 | 14 | //go:generate go run ../cmd/gen/main.go 15 | 16 | const path = "/proxy_checks" 17 | 18 | // Client is used to invoke the Proxy Checks API. 19 | type Client struct { 20 | Backend clerk.Backend 21 | } 22 | 23 | func NewClient(config *clerk.ClientConfig) *Client { 24 | return &Client{ 25 | Backend: clerk.NewBackend(&config.BackendConfig), 26 | } 27 | } 28 | 29 | type CreateParams struct { 30 | clerk.APIParams 31 | DomainID *string `json:"domain_id,omitempty"` 32 | ProxyURL *string `json:"proxy_url,omitempty"` 33 | } 34 | 35 | // Create creates a proxy check. 36 | // 37 | // Deprecated: The operation is deprecated and will be removed in 38 | // future versions. 39 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.ProxyCheck, error) { 40 | req := clerk.NewAPIRequest(http.MethodPost, path) 41 | req.SetParams(params) 42 | resource := &clerk.ProxyCheck{} 43 | err := c.Backend.Call(ctx, req, resource) 44 | return resource, err 45 | } 46 | -------------------------------------------------------------------------------- /proxycheck/client_test.go: -------------------------------------------------------------------------------- 1 | package proxycheck 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestProxyCheckClientCreate(t *testing.T) { 16 | t.Parallel() 17 | id := "proxchk_123" 18 | proxyURL := "https://clerk.com/__proxy" 19 | domainID := "dmn_123" 20 | config := &clerk.ClientConfig{} 21 | config.HTTPClient = &http.Client{ 22 | Transport: &clerktest.RoundTripper{ 23 | T: t, 24 | In: json.RawMessage(fmt.Sprintf(`{"domain_id":"%s","proxy_url":"%s"}`, domainID, proxyURL)), 25 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","domain_id":"%s","proxy_url":"%s","successful":true}`, id, domainID, proxyURL)), 26 | Method: http.MethodPost, 27 | Path: "/v1/proxy_checks", 28 | }, 29 | } 30 | client := NewClient(config) 31 | proxyCheck, err := client.Create(context.Background(), &CreateParams{ 32 | ProxyURL: clerk.String(proxyURL), 33 | DomainID: clerk.String(domainID), 34 | }) 35 | require.NoError(t, err) 36 | require.Equal(t, id, proxyCheck.ID) 37 | require.Equal(t, proxyURL, proxyCheck.ProxyURL) 38 | require.Equal(t, domainID, proxyCheck.DomainID) 39 | require.True(t, proxyCheck.Successful) 40 | } 41 | -------------------------------------------------------------------------------- /redirect_url.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type RedirectURL struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | URL string `json:"url"` 8 | CreatedAt int64 `json:"created_at"` 9 | UpdatedAt int64 `json:"updated_at"` 10 | } 11 | 12 | type RedirectURLList struct { 13 | APIResource 14 | RedirectURLs []*RedirectURL `json:"data"` 15 | TotalCount int64 `json:"total_count"` 16 | } 17 | -------------------------------------------------------------------------------- /redirecturl/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package redirecturl 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new redirect url. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.RedirectURL, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Get retrieves details for a redirect url by ID. 17 | func Get(ctx context.Context, id string) (*clerk.RedirectURL, error) { 18 | return getClient().Get(ctx, id) 19 | } 20 | 21 | // Delete deletes a redirect url. 22 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 23 | return getClient().Delete(ctx, id) 24 | } 25 | 26 | // List returns a list of redirect urls. 27 | func List(ctx context.Context, params *ListParams) (*clerk.RedirectURLList, error) { 28 | return getClient().List(ctx, params) 29 | } 30 | 31 | func getClient() *Client { 32 | return &Client{ 33 | Backend: clerk.GetBackend(), 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /redirecturl/client.go: -------------------------------------------------------------------------------- 1 | // Package redirecturl provides the Redirect URLs API. 2 | package redirecturl 3 | 4 | import ( 5 | "context" 6 | "fmt" 7 | "net/http" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/redirect_urls" 15 | 16 | // Client is used to invoke the Redirect URLs API. 17 | type Client struct { 18 | Backend clerk.Backend 19 | } 20 | 21 | func NewClient(config *clerk.ClientConfig) *Client { 22 | return &Client{ 23 | Backend: clerk.NewBackend(&config.BackendConfig), 24 | } 25 | } 26 | 27 | type CreateParams struct { 28 | clerk.APIParams 29 | URL *string `json:"url,omitempty"` 30 | } 31 | 32 | // Create creates a new redirect url. 33 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.RedirectURL, error) { 34 | req := clerk.NewAPIRequest(http.MethodPost, path) 35 | req.SetParams(params) 36 | redirectURL := &clerk.RedirectURL{} 37 | err := c.Backend.Call(ctx, req, redirectURL) 38 | return redirectURL, err 39 | } 40 | 41 | // Get retrieves details for a redirect url by ID. 42 | func (c *Client) Get(ctx context.Context, id string) (*clerk.RedirectURL, error) { 43 | path, err := clerk.JoinPath(path, id) 44 | if err != nil { 45 | return nil, err 46 | } 47 | req := clerk.NewAPIRequest(http.MethodGet, path) 48 | redirectURL := &clerk.RedirectURL{} 49 | err = c.Backend.Call(ctx, req, redirectURL) 50 | return redirectURL, err 51 | } 52 | 53 | // Delete deletes a redirect url. 54 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 55 | path, err := clerk.JoinPath(path, id) 56 | if err != nil { 57 | return nil, err 58 | } 59 | req := clerk.NewAPIRequest(http.MethodDelete, path) 60 | redirectURL := &clerk.DeletedResource{} 61 | err = c.Backend.Call(ctx, req, redirectURL) 62 | return redirectURL, err 63 | } 64 | 65 | type ListParams struct { 66 | clerk.APIParams 67 | } 68 | 69 | // List returns a list of redirect urls. 70 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.RedirectURLList, error) { 71 | req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) 72 | list := &clerk.RedirectURLList{} 73 | err := c.Backend.Call(ctx, req, list) 74 | return list, err 75 | } 76 | -------------------------------------------------------------------------------- /redirecturl/client_test.go: -------------------------------------------------------------------------------- 1 | package redirecturl 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestRedirectURLClientCreate(t *testing.T) { 16 | t.Parallel() 17 | id := "ru_123" 18 | url := "https://example.com" 19 | config := &clerk.ClientConfig{} 20 | config.HTTPClient = &http.Client{ 21 | Transport: &clerktest.RoundTripper{ 22 | T: t, 23 | In: json.RawMessage(fmt.Sprintf(`{"url":"%s"}`, url)), 24 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","url":"%s"}`, id, url)), 25 | Method: http.MethodPost, 26 | Path: "/v1/redirect_urls", 27 | }, 28 | } 29 | client := NewClient(config) 30 | redirectURL, err := client.Create(context.Background(), &CreateParams{ 31 | URL: clerk.String(url), 32 | }) 33 | require.NoError(t, err) 34 | require.Equal(t, id, redirectURL.ID) 35 | require.Equal(t, url, redirectURL.URL) 36 | } 37 | 38 | func TestRedirectURLClientCreate_Error(t *testing.T) { 39 | t.Parallel() 40 | config := &clerk.ClientConfig{} 41 | config.HTTPClient = &http.Client{ 42 | Transport: &clerktest.RoundTripper{ 43 | T: t, 44 | Status: http.StatusBadRequest, 45 | Out: json.RawMessage(`{ 46 | "errors":[{ 47 | "code":"create-error-code" 48 | }], 49 | "clerk_trace_id":"create-trace-id" 50 | }`), 51 | }, 52 | } 53 | client := NewClient(config) 54 | _, err := client.Create(context.Background(), &CreateParams{}) 55 | require.Error(t, err) 56 | apiErr, ok := err.(*clerk.APIErrorResponse) 57 | require.True(t, ok) 58 | require.Equal(t, "create-trace-id", apiErr.TraceID) 59 | require.Equal(t, 1, len(apiErr.Errors)) 60 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 61 | } 62 | 63 | func TestRedirectURLClientGet(t *testing.T) { 64 | t.Parallel() 65 | id := "ru_123" 66 | url := "https://example.com" 67 | config := &clerk.ClientConfig{} 68 | config.HTTPClient = &http.Client{ 69 | Transport: &clerktest.RoundTripper{ 70 | T: t, 71 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","url":"%s"}`, id, url)), 72 | Method: http.MethodGet, 73 | Path: "/v1/redirect_urls/" + id, 74 | }, 75 | } 76 | client := NewClient(config) 77 | redirectURL, err := client.Get(context.Background(), id) 78 | require.NoError(t, err) 79 | require.Equal(t, id, redirectURL.ID) 80 | require.Equal(t, url, redirectURL.URL) 81 | } 82 | 83 | func TestRedirectURLClientDelete(t *testing.T) { 84 | t.Parallel() 85 | id := "ru_123" 86 | config := &clerk.ClientConfig{} 87 | config.HTTPClient = &http.Client{ 88 | Transport: &clerktest.RoundTripper{ 89 | T: t, 90 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","deleted":true}`, id)), 91 | Method: http.MethodDelete, 92 | Path: "/v1/redirect_urls/" + id, 93 | }, 94 | } 95 | client := NewClient(config) 96 | redirectURL, err := client.Delete(context.Background(), id) 97 | require.NoError(t, err) 98 | require.Equal(t, id, redirectURL.ID) 99 | require.True(t, redirectURL.Deleted) 100 | } 101 | 102 | func TestRedirectURLClientList(t *testing.T) { 103 | t.Parallel() 104 | config := &clerk.ClientConfig{} 105 | config.HTTPClient = &http.Client{ 106 | Transport: &clerktest.RoundTripper{ 107 | T: t, 108 | Out: json.RawMessage(`{ 109 | "data": [{"id":"ru_123","url":"https://example.com"}], 110 | "total_count": 1 111 | }`), 112 | Method: http.MethodGet, 113 | Path: "/v1/redirect_urls", 114 | }, 115 | } 116 | client := NewClient(config) 117 | list, err := client.List(context.Background(), &ListParams{}) 118 | require.NoError(t, err) 119 | require.Equal(t, int64(1), list.TotalCount) 120 | require.Equal(t, 1, len(list.RedirectURLs)) 121 | require.Equal(t, "ru_123", list.RedirectURLs[0].ID) 122 | require.Equal(t, "https://example.com", list.RedirectURLs[0].URL) 123 | } 124 | -------------------------------------------------------------------------------- /saml_connection.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type SAMLConnection struct { 4 | APIResource 5 | ID string `json:"id"` 6 | Object string `json:"object"` 7 | Name string `json:"name"` 8 | Domain string `json:"domain"` 9 | IdpEntityID *string `json:"idp_entity_id"` 10 | OrganizationID *string `json:"organization_id"` 11 | IdpSsoURL *string `json:"idp_sso_url"` 12 | IdpCertificate *string `json:"idp_certificate"` 13 | IdpMetadataURL *string `json:"idp_metadata_url"` 14 | IdpMetadata *string `json:"idp_metadata"` 15 | AcsURL string `json:"acs_url"` 16 | SPEntityID string `json:"sp_entity_id"` 17 | SPMetadataURL string `json:"sp_metadata_url"` 18 | AttributeMapping SAMLConnectionAttributeMapping `json:"attribute_mapping"` 19 | Active bool `json:"active"` 20 | Provider string `json:"provider"` 21 | UserCount int64 `json:"user_count"` 22 | SyncUserAttributes bool `json:"sync_user_attributes"` 23 | AllowSubdomains bool `json:"allow_subdomains"` 24 | AllowIdpInitiated bool `json:"allow_idp_initiated"` 25 | DisableAdditionalIdentifications bool `json:"disable_additional_identifications"` 26 | CreatedAt int64 `json:"created_at"` 27 | UpdatedAt int64 `json:"updated_at"` 28 | } 29 | 30 | type SAMLConnectionAttributeMapping struct { 31 | UserID string `json:"user_id"` 32 | EmailAddress string `json:"email_address"` 33 | FirstName string `json:"first_name"` 34 | LastName string `json:"last_name"` 35 | } 36 | 37 | type SAMLConnectionList struct { 38 | APIResource 39 | SAMLConnections []*SAMLConnection `json:"data"` 40 | TotalCount int64 `json:"total_count"` 41 | } 42 | -------------------------------------------------------------------------------- /samlconnection/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package samlconnection 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new SAML Connection. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.SAMLConnection, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Get returns details about a SAML Connection. 17 | func Get(ctx context.Context, id string) (*clerk.SAMLConnection, error) { 18 | return getClient().Get(ctx, id) 19 | } 20 | 21 | // Update updates the SAML Connection specified by id. 22 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.SAMLConnection, error) { 23 | return getClient().Update(ctx, id, params) 24 | } 25 | 26 | // Delete deletes a SAML Connection. 27 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 28 | return getClient().Delete(ctx, id) 29 | } 30 | 31 | // List returns a list of SAML Connections. 32 | func List(ctx context.Context, params *ListParams) (*clerk.SAMLConnectionList, error) { 33 | return getClient().List(ctx, params) 34 | } 35 | 36 | func getClient() *Client { 37 | return &Client{ 38 | Backend: clerk.GetBackend(), 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /samlconnection/client.go: -------------------------------------------------------------------------------- 1 | // Package samlconnection provides the SAML Connections API. 2 | package samlconnection 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | "net/url" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/saml_connections" 15 | 16 | // Client is used to invoke the SAML Connections API. 17 | type Client struct { 18 | Backend clerk.Backend 19 | } 20 | 21 | func NewClient(config *clerk.ClientConfig) *Client { 22 | return &Client{ 23 | Backend: clerk.NewBackend(&config.BackendConfig), 24 | } 25 | } 26 | 27 | type AttributeMappingParams struct { 28 | UserID string `json:"user_id"` 29 | EmailAddress string `json:"email_address"` 30 | FirstName string `json:"first_name"` 31 | LastName string `json:"last_name"` 32 | } 33 | 34 | type CreateParams struct { 35 | clerk.APIParams 36 | Name *string `json:"name,omitempty"` 37 | OrganizationID *string `json:"organization_id,omitempty"` 38 | Domain *string `json:"domain,omitempty"` 39 | Provider *string `json:"provider,omitempty"` 40 | IdpEntityID *string `json:"idp_entity_id,omitempty"` 41 | IdpSsoURL *string `json:"idp_sso_url,omitempty"` 42 | IdpCertificate *string `json:"idp_certificate,omitempty"` 43 | IdpMetadataURL *string `json:"idp_metadata_url,omitempty"` 44 | IdpMetadata *string `json:"idp_metadata,omitempty"` 45 | AttributeMapping *AttributeMappingParams `json:"attribute_mapping,omitempty"` 46 | } 47 | 48 | // Create creates a new SAML Connection. 49 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.SAMLConnection, error) { 50 | req := clerk.NewAPIRequest(http.MethodPost, path) 51 | req.SetParams(params) 52 | connection := &clerk.SAMLConnection{} 53 | err := c.Backend.Call(ctx, req, connection) 54 | return connection, err 55 | } 56 | 57 | // Get returns details about a SAML Connection. 58 | func (c *Client) Get(ctx context.Context, id string) (*clerk.SAMLConnection, error) { 59 | path, err := clerk.JoinPath(path, id) 60 | if err != nil { 61 | return nil, err 62 | } 63 | req := clerk.NewAPIRequest(http.MethodGet, path) 64 | connection := &clerk.SAMLConnection{} 65 | err = c.Backend.Call(ctx, req, connection) 66 | return connection, err 67 | } 68 | 69 | type UpdateParams struct { 70 | clerk.APIParams 71 | Name *string `json:"name,omitempty"` 72 | Domain *string `json:"domain,omitempty"` 73 | IdpEntityID *string `json:"idp_entity_id,omitempty"` 74 | // OrganizationID is a nullable optional field. 75 | // - If nil or unset, no action will be taken. 76 | // - If an empty value (""), the organization_id will be unset. 77 | // - If a valid ID is provided, the organization_id will be updated. 78 | OrganizationID *string `json:"organization_id,omitempty"` 79 | IdpSsoURL *string `json:"idp_sso_url,omitempty"` 80 | IdpCertificate *string `json:"idp_certificate,omitempty"` 81 | IdpMetadataURL *string `json:"idp_metadata_url,omitempty"` 82 | IdpMetadata *string `json:"idp_metadata,omitempty"` 83 | AttributeMapping *AttributeMappingParams `json:"attribute_mapping,omitempty"` 84 | Active *bool `json:"active,omitempty"` 85 | SyncUserAttributes *bool `json:"sync_user_attributes,omitempty"` 86 | AllowSubdomains *bool `json:"allow_subdomains,omitempty"` 87 | AllowIdpInitiated *bool `json:"allow_idp_initiated,omitempty"` 88 | DisableAdditionalIdentifications *bool `json:"disable_additional_identifications,omitempty"` 89 | } 90 | 91 | // Update updates the SAML Connection specified by id. 92 | func (c *Client) Update(ctx context.Context, id string, params *UpdateParams) (*clerk.SAMLConnection, error) { 93 | path, err := clerk.JoinPath(path, id) 94 | if err != nil { 95 | return nil, err 96 | } 97 | req := clerk.NewAPIRequest(http.MethodPatch, path) 98 | req.SetParams(params) 99 | connection := &clerk.SAMLConnection{} 100 | err = c.Backend.Call(ctx, req, connection) 101 | return connection, err 102 | } 103 | 104 | // Delete deletes a SAML Connection. 105 | func (c *Client) Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 106 | path, err := clerk.JoinPath(path, id) 107 | if err != nil { 108 | return nil, err 109 | } 110 | req := clerk.NewAPIRequest(http.MethodDelete, path) 111 | template := &clerk.DeletedResource{} 112 | err = c.Backend.Call(ctx, req, template) 113 | return template, err 114 | } 115 | 116 | type ListParams struct { 117 | clerk.APIParams 118 | clerk.ListParams 119 | Query *string `json:"query,omitempty"` 120 | OrderBy *string `json:"order_by,omitempty"` 121 | } 122 | 123 | // ToQuery returns query string values from the params. 124 | func (params *ListParams) ToQuery() url.Values { 125 | q := params.ListParams.ToQuery() 126 | if params.Query != nil { 127 | q.Set("query", *params.Query) 128 | } 129 | if params.OrderBy != nil { 130 | q.Set("order_by", *params.OrderBy) 131 | } 132 | return q 133 | } 134 | 135 | // List returns a list of SAML Connections. 136 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.SAMLConnectionList, error) { 137 | req := clerk.NewAPIRequest(http.MethodGet, path) 138 | req.SetParams(params) 139 | list := &clerk.SAMLConnectionList{} 140 | err := c.Backend.Call(ctx, req, list) 141 | return list, err 142 | } 143 | -------------------------------------------------------------------------------- /session.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type SessionActivity struct { 6 | Object string `json:"object"` 7 | ID string `json:"id"` 8 | DeviceType *string `json:"device_type,omitempty"` 9 | IsMobile bool `json:"is_mobile"` 10 | BrowserName *string `json:"browser_name,omitempty"` 11 | BrowserVersion *string `json:"browser_version,omitempty"` 12 | IPAddress *string `json:"ip_address,omitempty"` 13 | City *string `json:"city,omitempty"` 14 | Country *string `json:"country,omitempty"` 15 | } 16 | 17 | type Session struct { 18 | APIResource 19 | Object string `json:"object"` 20 | ID string `json:"id"` 21 | ClientID string `json:"client_id"` 22 | UserID string `json:"user_id"` 23 | Status string `json:"status"` 24 | LastActiveOrganizationID string `json:"last_active_organization_id,omitempty"` 25 | LatestActivity *SessionActivity `json:"latest_activity,omitempty"` 26 | Actor json.RawMessage `json:"actor,omitempty"` 27 | LastActiveAt int64 `json:"last_active_at"` 28 | ExpireAt int64 `json:"expire_at"` 29 | AbandonAt int64 `json:"abandon_at"` 30 | CreatedAt int64 `json:"created_at"` 31 | UpdatedAt int64 `json:"updated_at"` 32 | } 33 | 34 | type SessionList struct { 35 | APIResource 36 | Sessions []*Session `json:"data"` 37 | TotalCount int64 `json:"total_count"` 38 | } 39 | -------------------------------------------------------------------------------- /session/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package session 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Get retrieves details for a session. 12 | func Get(ctx context.Context, id string) (*clerk.Session, error) { 13 | return getClient().Get(ctx, id) 14 | } 15 | 16 | // List returns a list of sessions. 17 | func List(ctx context.Context, params *ListParams) (*clerk.SessionList, error) { 18 | return getClient().List(ctx, params) 19 | } 20 | 21 | // Revoke marks the session as revoked. 22 | func Revoke(ctx context.Context, params *RevokeParams) (*clerk.Session, error) { 23 | return getClient().Revoke(ctx, params) 24 | } 25 | 26 | // Creates a session token for the specified session 27 | // If a template is provided, return a token created with the specified template 28 | func CreateToken(ctx context.Context, params *CreateTokenParams) (*clerk.SessionToken, error) { 29 | return getClient().CreateToken(ctx, params) 30 | } 31 | 32 | // Creates a session for the specified user 33 | // 34 | // This operation is intended only for use in testing, and is not available for production instances. 35 | func Create(ctx context.Context, params *CreateParams) (*clerk.Session, error) { 36 | return getClient().Create(ctx, params) 37 | } 38 | 39 | // Verify verifies the session. 40 | // 41 | // Deprecated: The operation is deprecated and will be removed in future versions. 42 | // It is recommended to switch to networkless verification using short-lived 43 | // session tokens instead. 44 | // See https://clerk.com/docs/backend-requests/resources/session-tokens 45 | func Verify(ctx context.Context, params *VerifyParams) (*clerk.Session, error) { 46 | return getClient().Verify(ctx, params) 47 | } 48 | 49 | func getClient() *Client { 50 | return &Client{ 51 | Backend: clerk.GetBackend(), 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /session/client.go: -------------------------------------------------------------------------------- 1 | // Package session provides the Sessions API. 2 | package session 3 | 4 | import ( 5 | "context" 6 | "fmt" 7 | "net/http" 8 | "net/url" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | ) 12 | 13 | //go:generate go run ../cmd/gen/main.go 14 | 15 | const path = "/sessions" 16 | 17 | // Client is used to invoke the Sessions API. 18 | type Client struct { 19 | Backend clerk.Backend 20 | } 21 | 22 | func NewClient(config *clerk.ClientConfig) *Client { 23 | return &Client{ 24 | Backend: clerk.NewBackend(&config.BackendConfig), 25 | } 26 | } 27 | 28 | // Get retrieves details for a session. 29 | func (c *Client) Get(ctx context.Context, id string) (*clerk.Session, error) { 30 | path, err := clerk.JoinPath(path, id) 31 | if err != nil { 32 | return nil, err 33 | } 34 | req := clerk.NewAPIRequest(http.MethodGet, path) 35 | session := &clerk.Session{} 36 | err = c.Backend.Call(ctx, req, session) 37 | return session, err 38 | } 39 | 40 | type ListParams struct { 41 | clerk.APIParams 42 | clerk.ListParams 43 | ClientID *string `json:"client_id,omitempty"` 44 | UserID *string `json:"user_id,omitempty"` 45 | Status *string `json:"status,omitempty"` 46 | } 47 | 48 | // ToQuery returns the params as url.Values. 49 | func (params *ListParams) ToQuery() url.Values { 50 | q := params.ListParams.ToQuery() 51 | if params.ClientID != nil { 52 | q.Add("client_id", *params.ClientID) 53 | } 54 | if params.UserID != nil { 55 | q.Add("user_id", *params.UserID) 56 | } 57 | if params.Status != nil { 58 | q.Add("status", *params.Status) 59 | } 60 | return q 61 | } 62 | 63 | // List returns a list of sessions. 64 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.SessionList, error) { 65 | req := clerk.NewAPIRequest(http.MethodGet, fmt.Sprintf("%s?paginated=true", path)) 66 | req.SetParams(params) 67 | list := &clerk.SessionList{} 68 | err := c.Backend.Call(ctx, req, list) 69 | return list, err 70 | } 71 | 72 | type RevokeParams struct { 73 | ID string `json:"id"` 74 | } 75 | 76 | // Revoke marks the session as revoked. 77 | func (c *Client) Revoke(ctx context.Context, params *RevokeParams) (*clerk.Session, error) { 78 | path, err := clerk.JoinPath(path, params.ID, "/revoke") 79 | if err != nil { 80 | return nil, err 81 | } 82 | req := clerk.NewAPIRequest(http.MethodPost, path) 83 | session := &clerk.Session{} 84 | err = c.Backend.Call(ctx, req, session) 85 | return session, err 86 | } 87 | 88 | type CreateTokenParams struct { 89 | clerk.APIParams 90 | ID string `json:"-"` 91 | TemplateName string `json:"-"` 92 | ExpiresInSeconds *int64 `json:"expires_in_seconds,omitempty"` 93 | } 94 | 95 | // Creates a session token for the specified session 96 | // If a template is provided, return a token created with the specified template 97 | func (c *Client) CreateToken(ctx context.Context, params *CreateTokenParams) (*clerk.SessionToken, error) { 98 | path, err := clerk.JoinPath(path, params.ID, "/tokens", params.TemplateName) 99 | if err != nil { 100 | return nil, err 101 | } 102 | req := clerk.NewAPIRequest(http.MethodPost, path) 103 | req.SetParams(params) 104 | token := &clerk.SessionToken{} 105 | err = c.Backend.Call(ctx, req, token) 106 | return token, err 107 | } 108 | 109 | type CreateParams struct { 110 | clerk.APIParams 111 | UserID string `json:"user_id"` 112 | } 113 | 114 | // Creates a session for the specified user 115 | // 116 | // This operation is intended only for use in testing, and is not available for production instances. 117 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.Session, error) { 118 | req := clerk.NewAPIRequest(http.MethodPost, path) 119 | req.SetParams(params) 120 | session := &clerk.Session{} 121 | err := c.Backend.Call(ctx, req, session) 122 | return session, err 123 | } 124 | 125 | type VerifyParams struct { 126 | ID string `json:"-"` 127 | Token *string `json:"token,omitempty"` 128 | } 129 | 130 | // Verify verifies the session. 131 | // 132 | // Deprecated: The operation is deprecated and will be removed in future versions. 133 | // It is recommended to switch to networkless verification using short-lived 134 | // session tokens instead. 135 | // See https://clerk.com/docs/backend-requests/resources/session-tokens 136 | func (c *Client) Verify(ctx context.Context, params *VerifyParams) (*clerk.Session, error) { 137 | path, err := clerk.JoinPath(path, params.ID, "/verify") 138 | if err != nil { 139 | return nil, err 140 | } 141 | req := clerk.NewAPIRequest(http.MethodPost, path) 142 | session := &clerk.Session{} 143 | err = c.Backend.Call(ctx, req, session) 144 | return session, err 145 | } 146 | -------------------------------------------------------------------------------- /session/client_test.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "net/url" 9 | "testing" 10 | 11 | "github.com/clerk/clerk-sdk-go/v2" 12 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func TestSessionClientGet(t *testing.T) { 17 | t.Parallel() 18 | id := "sess_123" 19 | status := "active" 20 | config := &clerk.ClientConfig{} 21 | config.HTTPClient = &http.Client{ 22 | Transport: &clerktest.RoundTripper{ 23 | T: t, 24 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","status":"%s"}`, id, status)), 25 | Method: http.MethodGet, 26 | Path: "/v1/sessions/" + id, 27 | }, 28 | } 29 | client := NewClient(config) 30 | session, err := client.Get(context.Background(), id) 31 | require.NoError(t, err) 32 | require.Equal(t, id, session.ID) 33 | require.Equal(t, status, session.Status) 34 | } 35 | 36 | func TestSessionClientList(t *testing.T) { 37 | t.Parallel() 38 | config := &clerk.ClientConfig{} 39 | config.HTTPClient = &http.Client{ 40 | Transport: &clerktest.RoundTripper{ 41 | T: t, 42 | Out: json.RawMessage(`{ 43 | "data": [{"id":"sess_123","status":"active"}], 44 | "total_count": 1 45 | }`), 46 | Method: http.MethodGet, 47 | Path: "/v1/sessions", 48 | Query: &url.Values{ 49 | "paginated": []string{"true"}, 50 | "limit": []string{"1"}, 51 | "offset": []string{"2"}, 52 | "status": []string{"active"}, 53 | }, 54 | }, 55 | } 56 | client := NewClient(config) 57 | params := &ListParams{ 58 | Status: clerk.String("active"), 59 | } 60 | params.Limit = clerk.Int64(1) 61 | params.Offset = clerk.Int64(2) 62 | list, err := client.List(context.Background(), params) 63 | require.NoError(t, err) 64 | require.Equal(t, int64(1), list.TotalCount) 65 | require.Equal(t, 1, len(list.Sessions)) 66 | require.Equal(t, "sess_123", list.Sessions[0].ID) 67 | require.Equal(t, "active", list.Sessions[0].Status) 68 | } 69 | 70 | func TestSessionClientRevoke(t *testing.T) { 71 | t.Parallel() 72 | id := "sess_123" 73 | status := "revoked" 74 | config := &clerk.ClientConfig{} 75 | config.HTTPClient = &http.Client{ 76 | Transport: &clerktest.RoundTripper{ 77 | T: t, 78 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","status":"%s"}`, id, status)), 79 | Method: http.MethodPost, 80 | Path: "/v1/sessions/" + id + "/revoke", 81 | }, 82 | } 83 | client := NewClient(config) 84 | session, err := client.Revoke(context.Background(), &RevokeParams{ 85 | ID: id, 86 | }) 87 | require.NoError(t, err) 88 | require.Equal(t, id, session.ID) 89 | require.Equal(t, status, session.Status) 90 | } 91 | 92 | func TestSessionClientVerify(t *testing.T) { 93 | t.Parallel() 94 | id := "sess_123" 95 | config := &clerk.ClientConfig{} 96 | config.HTTPClient = &http.Client{ 97 | Transport: &clerktest.RoundTripper{ 98 | T: t, 99 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s"}`, id)), 100 | Method: http.MethodPost, 101 | Path: "/v1/sessions/" + id + "/verify", 102 | }, 103 | } 104 | client := NewClient(config) 105 | session, err := client.Verify(context.Background(), &VerifyParams{ 106 | ID: id, 107 | Token: clerk.String("the-token"), 108 | }) 109 | require.NoError(t, err) 110 | require.Equal(t, id, session.ID) 111 | } 112 | 113 | func TestSessionClientCreateToken(t *testing.T) { 114 | t.Parallel() 115 | sessionId := "sess_123" 116 | jwt := "jwt-value" 117 | config := &clerk.ClientConfig{} 118 | config.HTTPClient = &http.Client{ 119 | Transport: &clerktest.RoundTripper{ 120 | T: t, 121 | Out: json.RawMessage(fmt.Sprintf(`{"object":"token", "jwt": "%s"}`, jwt)), 122 | Method: http.MethodPost, 123 | Path: fmt.Sprintf("/v1/sessions/%s/tokens", sessionId), 124 | }, 125 | } 126 | client := NewClient(config) 127 | token, err := client.CreateToken(context.Background(), &CreateTokenParams{ 128 | ID: sessionId, 129 | }) 130 | require.NoError(t, err) 131 | require.Equal(t, jwt, token.JWT) 132 | } 133 | 134 | func TestSessionClientCreateTokenWithTemplate(t *testing.T) { 135 | t.Parallel() 136 | sessionId := "sess_123" 137 | jwt := "jwt-value" 138 | templateName := "test-template" 139 | config := &clerk.ClientConfig{} 140 | config.HTTPClient = &http.Client{ 141 | Transport: &clerktest.RoundTripper{ 142 | T: t, 143 | Out: json.RawMessage(fmt.Sprintf(`{"object":"token", "jwt": "%s"}`, jwt)), 144 | Method: http.MethodPost, 145 | Path: fmt.Sprintf("/v1/sessions/%s/tokens/%s", sessionId, templateName), 146 | }, 147 | } 148 | client := NewClient(config) 149 | token, err := client.CreateToken(context.Background(), &CreateTokenParams{ 150 | ID: sessionId, 151 | TemplateName: templateName, 152 | }) 153 | 154 | require.NoError(t, err) 155 | require.Equal(t, jwt, token.JWT) 156 | } 157 | 158 | func TestSessionClientCreate(t *testing.T) { 159 | t.Parallel() 160 | userId := "user_123" 161 | sessionId := "sess_123" 162 | config := &clerk.ClientConfig{} 163 | config.HTTPClient = &http.Client{ 164 | Transport: &clerktest.RoundTripper{ 165 | T: t, 166 | Out: json.RawMessage(fmt.Sprintf(`{"object":"session","id":"%s","status":"active", "user_id": "%s"}`, sessionId, userId)), 167 | Method: http.MethodPost, 168 | Path: "/v1/sessions", 169 | }, 170 | } 171 | client := NewClient(config) 172 | session, err := client.Create(context.Background(), &CreateParams{ 173 | UserID: userId, 174 | }) 175 | require.NoError(t, err) 176 | require.Equal(t, userId, session.UserID) 177 | require.Equal(t, session.Object, "session") 178 | require.Equal(t, session.ID, sessionId) 179 | } 180 | -------------------------------------------------------------------------------- /session_reverification.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type SessionReverificationLevel string 4 | 5 | const ( 6 | // SessionReverificationLevelFirstFactor uses first factor methods 7 | // e.g. email/phone code, password 8 | SessionReverificationLevelFirstFactor SessionReverificationLevel = "first_factor" 9 | 10 | // SessionReverificationLevelSecondFactor uses second factor methods, if available 11 | // e.g. authenticator app, backup code 12 | SessionReverificationLevelSecondFactor SessionReverificationLevel = "second_factor" 13 | 14 | // SessionReverificationLevelMultiFactor requires both first and second factor 15 | // methods, if available 16 | SessionReverificationLevelMultiFactor SessionReverificationLevel = "multi_factor" 17 | ) 18 | 19 | type SessionReverificationPolicy struct { 20 | // AfterMinutes is the session age threshold before reverification 21 | AfterMinutes int64 22 | 23 | // Level specifies which verification factors are required 24 | Level SessionReverificationLevel 25 | } 26 | 27 | var ( 28 | SessionReverificationStrictMFA = SessionReverificationPolicy{ 29 | AfterMinutes: 10, 30 | Level: SessionReverificationLevelMultiFactor, 31 | } 32 | 33 | SessionReverificationStrict = SessionReverificationPolicy{ 34 | AfterMinutes: 10, 35 | Level: SessionReverificationLevelSecondFactor, 36 | } 37 | 38 | SessionReverificationModerate = SessionReverificationPolicy{ 39 | AfterMinutes: 60, 40 | Level: SessionReverificationLevelSecondFactor, 41 | } 42 | 43 | SessionReverificationLax = SessionReverificationPolicy{ 44 | AfterMinutes: 1_440, 45 | Level: SessionReverificationLevelSecondFactor, 46 | } 47 | ) 48 | -------------------------------------------------------------------------------- /session_token.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type SessionToken struct { 4 | APIResource 5 | Object string `json:"object"` 6 | JWT string `json:"jwt"` 7 | } 8 | -------------------------------------------------------------------------------- /sign_in_token.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type SignInToken struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | Status string `json:"status"` 8 | UserID string `json:"user_id"` 9 | Token string `json:"token,omitempty"` 10 | URL *string `json:"url,omitempty"` 11 | CreatedAt int64 `json:"created_at"` 12 | UpdatedAt int64 `json:"updated_at"` 13 | } 14 | -------------------------------------------------------------------------------- /signintoken/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package signintoken 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new sign-in token. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.SignInToken, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Revoke revokes a pending sign-in token. 17 | func Revoke(ctx context.Context, id string) (*clerk.SignInToken, error) { 18 | return getClient().Revoke(ctx, id) 19 | } 20 | 21 | func getClient() *Client { 22 | return &Client{ 23 | Backend: clerk.GetBackend(), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /signintoken/client.go: -------------------------------------------------------------------------------- 1 | // Package signintoken provides the Sign-In Token API. 2 | package signintoken 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/sign_in_tokens" 14 | 15 | // Client is used to invoke the Sign-In Token API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | type CreateParams struct { 27 | clerk.APIParams 28 | UserID *string `json:"user_id,omitempty"` 29 | ExpiresInSeconds *int64 `json:"expires_in_seconds,omitempty"` 30 | } 31 | 32 | // Create creates a new sign-in token. 33 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.SignInToken, error) { 34 | req := clerk.NewAPIRequest(http.MethodPost, path) 35 | req.SetParams(params) 36 | token := &clerk.SignInToken{} 37 | err := c.Backend.Call(ctx, req, token) 38 | return token, err 39 | } 40 | 41 | // Revoke revokes a pending sign-in token. 42 | func (c *Client) Revoke(ctx context.Context, id string) (*clerk.SignInToken, error) { 43 | token := &clerk.SignInToken{} 44 | path, err := clerk.JoinPath(path, id, "revoke") 45 | if err != nil { 46 | return token, err 47 | } 48 | req := clerk.NewAPIRequest(http.MethodPost, path) 49 | err = c.Backend.Call(ctx, req, token) 50 | return token, err 51 | } 52 | -------------------------------------------------------------------------------- /signintoken/sign_in_tokens_test.go: -------------------------------------------------------------------------------- 1 | package signintoken 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestSignInTokenTokenCreate(t *testing.T) { 16 | userID := "usr_123" 17 | id := "sign_123" 18 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 19 | HTTPClient: &http.Client{ 20 | Transport: &clerktest.RoundTripper{ 21 | T: t, 22 | In: json.RawMessage(fmt.Sprintf(`{"user_id":"%s"}`, userID)), 23 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","user_id":"%s"}`, id, userID)), 24 | Path: "/v1/sign_in_tokens", 25 | Method: http.MethodPost, 26 | }, 27 | }, 28 | })) 29 | 30 | signInToken, err := Create(context.Background(), &CreateParams{ 31 | UserID: clerk.String(userID), 32 | }) 33 | require.NoError(t, err) 34 | require.Equal(t, id, signInToken.ID) 35 | require.Equal(t, userID, signInToken.UserID) 36 | } 37 | 38 | func TestSignInTokenRevoke(t *testing.T) { 39 | id := "sign_456" 40 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 41 | HTTPClient: &http.Client{ 42 | Transport: &clerktest.RoundTripper{ 43 | T: t, 44 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","status":"revoked"}`, id)), 45 | Path: fmt.Sprintf("/v1/sign_in_tokens/%s/revoke", id), 46 | Method: http.MethodPost, 47 | }, 48 | }, 49 | })) 50 | 51 | signInToken, err := Revoke(context.Background(), id) 52 | require.NoError(t, err) 53 | require.Equal(t, id, signInToken.ID) 54 | require.Equal(t, "revoked", signInToken.Status) 55 | } 56 | -------------------------------------------------------------------------------- /svix_webhook.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type SvixWebhook struct { 4 | APIResource 5 | SvixURL string `json:"svix_url"` 6 | } 7 | -------------------------------------------------------------------------------- /svixwebhook/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package svixwebhook 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a Svix app. 12 | func Create(ctx context.Context) (*clerk.SvixWebhook, error) { 13 | return getClient().Create(ctx) 14 | } 15 | 16 | // Delete deletes the Svix app. 17 | func Delete(ctx context.Context) (*clerk.SvixWebhook, error) { 18 | return getClient().Delete(ctx) 19 | } 20 | 21 | // RefreshURL generates a new URL for accessing Svix's dashboard. 22 | func RefreshURL(ctx context.Context) (*clerk.SvixWebhook, error) { 23 | return getClient().RefreshURL(ctx) 24 | } 25 | 26 | func getClient() *Client { 27 | return &Client{ 28 | Backend: clerk.GetBackend(), 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /svixwebhook/client.go: -------------------------------------------------------------------------------- 1 | // Package svixwebhook provides the Svix Webhooks API. 2 | package svixwebhook 3 | 4 | import ( 5 | "context" 6 | "net/http" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/webhooks/svix" 14 | 15 | // Client is used to invoke the Organizations API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | // Create creates a Svix app. 27 | func (c *Client) Create(ctx context.Context) (*clerk.SvixWebhook, error) { 28 | req := clerk.NewAPIRequest(http.MethodPost, path) 29 | resource := &clerk.SvixWebhook{} 30 | err := c.Backend.Call(ctx, req, resource) 31 | return resource, err 32 | } 33 | 34 | // Delete deletes the Svix app. 35 | func (c *Client) Delete(ctx context.Context) (*clerk.SvixWebhook, error) { 36 | req := clerk.NewAPIRequest(http.MethodDelete, path) 37 | resource := &clerk.SvixWebhook{} 38 | err := c.Backend.Call(ctx, req, resource) 39 | return resource, err 40 | } 41 | 42 | // RefreshURL generates a new URL for accessing Svix's dashboard. 43 | func (c *Client) RefreshURL(ctx context.Context) (*clerk.SvixWebhook, error) { 44 | req := clerk.NewAPIRequest(http.MethodPost, "/webhooks/svix_url") 45 | resource := &clerk.SvixWebhook{} 46 | err := c.Backend.Call(ctx, req, resource) 47 | return resource, err 48 | } 49 | -------------------------------------------------------------------------------- /svixwebhook/client_test.go: -------------------------------------------------------------------------------- 1 | package svixwebhook 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "testing" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 12 | "github.com/stretchr/testify/require" 13 | ) 14 | 15 | func TestSvixWebhookClientCreate(t *testing.T) { 16 | t.Parallel() 17 | svixURL := "https://foo.com/webhook" 18 | config := &clerk.ClientConfig{} 19 | config.HTTPClient = &http.Client{ 20 | Transport: &clerktest.RoundTripper{ 21 | T: t, 22 | Out: json.RawMessage(fmt.Sprintf(`{"svix_url":"%s"}`, svixURL)), 23 | Method: http.MethodPost, 24 | Path: "/v1/webhooks/svix", 25 | }, 26 | } 27 | client := NewClient(config) 28 | webhook, err := client.Create(context.Background()) 29 | require.NoError(t, err) 30 | require.Equal(t, svixURL, webhook.SvixURL) 31 | } 32 | 33 | func TestSvixWebhookClientDelete(t *testing.T) { 34 | t.Parallel() 35 | config := &clerk.ClientConfig{} 36 | config.HTTPClient = &http.Client{ 37 | Transport: &clerktest.RoundTripper{ 38 | T: t, 39 | Method: http.MethodDelete, 40 | Path: "/v1/webhooks/svix", 41 | }, 42 | } 43 | client := NewClient(config) 44 | _, err := client.Delete(context.Background()) 45 | require.NoError(t, err) 46 | } 47 | 48 | func TestSvixWebhookClientRefreshURL(t *testing.T) { 49 | t.Parallel() 50 | svixURL := "https://foo.com/webhook" 51 | config := &clerk.ClientConfig{} 52 | config.HTTPClient = &http.Client{ 53 | Transport: &clerktest.RoundTripper{ 54 | T: t, 55 | Out: json.RawMessage(fmt.Sprintf(`{"svix_url":"%s"}`, svixURL)), 56 | Method: http.MethodPost, 57 | Path: "/v1/webhooks/svix_url", 58 | }, 59 | } 60 | client := NewClient(config) 61 | webhook, err := client.RefreshURL(context.Background()) 62 | require.NoError(t, err) 63 | require.Equal(t, svixURL, webhook.SvixURL) 64 | } 65 | -------------------------------------------------------------------------------- /template.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | // Clerk supports different types of templates. 4 | type TemplateType string 5 | 6 | // List of supported values for template types. 7 | const ( 8 | TemplateTypeEmail TemplateType = "email" 9 | TemplateTypeSMS TemplateType = "sms" 10 | ) 11 | 12 | type Template struct { 13 | APIResource 14 | Object string `json:"object"` 15 | Slug string `json:"slug"` 16 | ResourceType string `json:"resource_type"` 17 | TemplateType TemplateType `json:"template_type"` 18 | Name string `json:"name"` 19 | Position int `json:"position"` 20 | CanRevert bool `json:"can_revert"` 21 | CanDelete bool `json:"can_delete"` 22 | CanToggle bool `json:"can_toggle"` 23 | FromEmailName *string `json:"from_email_name,omitempty"` 24 | ReplyToEmailName *string `json:"reply_to_email_name,omitempty"` 25 | DeliveredByClerk bool `json:"delivered_by_clerk"` 26 | Enabled bool `json:"enabled"` 27 | Subject string `json:"subject"` 28 | Markup string `json:"markup"` 29 | Body string `json:"body"` 30 | AvailableVariables []string `json:"available_variables"` 31 | RequiredVariables []string `json:"required_variables"` 32 | CreatedAt int64 `json:"created_at"` 33 | UpdatedAt int64 `json:"updated_at"` 34 | } 35 | 36 | type TemplateList struct { 37 | APIResource 38 | Templates []*Template `json:"data"` 39 | TotalCount int64 `json:"total_count"` 40 | } 41 | 42 | type TemplatePreview struct { 43 | APIResource 44 | Subject string `json:"subject,omitempty"` 45 | Body string `json:"body"` 46 | FromEmailAddress *string `json:"from_email_address,omitempty"` 47 | ReplyToEmailAddress *string `json:"reply_to_email_address,omitempty"` 48 | } 49 | -------------------------------------------------------------------------------- /template/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package template 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Get retrieves details for a template. 12 | func Get(ctx context.Context, params *GetParams) (*clerk.Template, error) { 13 | return getClient().Get(ctx, params) 14 | } 15 | 16 | // Update updates an existing template or creates a new one with the 17 | // provided params. 18 | func Update(ctx context.Context, params *UpdateParams) (*clerk.Template, error) { 19 | return getClient().Update(ctx, params) 20 | } 21 | 22 | // Delete deletes a custom user template. 23 | func Delete(ctx context.Context, params *DeleteParams) (*clerk.DeletedResource, error) { 24 | return getClient().Delete(ctx, params) 25 | } 26 | 27 | // Revert reverts a template to its default state. 28 | func Revert(ctx context.Context, params *RevertParams) (*clerk.Template, error) { 29 | return getClient().Revert(ctx, params) 30 | } 31 | 32 | // ToggleDelivery sets the delivery by Clerk for a template. 33 | func ToggleDelivery(ctx context.Context, params *ToggleDeliveryParams) (*clerk.Template, error) { 34 | return getClient().ToggleDelivery(ctx, params) 35 | } 36 | 37 | // Preview returns a preview of a template. 38 | func Preview(ctx context.Context, params *PreviewParams) (*clerk.TemplatePreview, error) { 39 | return getClient().Preview(ctx, params) 40 | } 41 | 42 | // List returns a list of templates of a given type. 43 | func List(ctx context.Context, params *ListParams) (*clerk.TemplateList, error) { 44 | return getClient().List(ctx, params) 45 | } 46 | 47 | func getClient() *Client { 48 | return &Client{ 49 | Backend: clerk.GetBackend(), 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /template/client.go: -------------------------------------------------------------------------------- 1 | // Package template provides the Templates API. 2 | package template 3 | 4 | import ( 5 | "context" 6 | "fmt" 7 | "net/http" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | ) 11 | 12 | //go:generate go run ../cmd/gen/main.go 13 | 14 | const path = "/templates" 15 | 16 | // Client is used to invoke the Templates API. 17 | type Client struct { 18 | Backend clerk.Backend 19 | } 20 | 21 | func NewClient(config *clerk.ClientConfig) *Client { 22 | return &Client{ 23 | Backend: clerk.NewBackend(&config.BackendConfig), 24 | } 25 | } 26 | 27 | type GetParams struct { 28 | TemplateType clerk.TemplateType `json:"-"` 29 | Slug string `json:"-"` 30 | } 31 | 32 | // Get retrieves details for a template. 33 | func (c *Client) Get(ctx context.Context, params *GetParams) (*clerk.Template, error) { 34 | path, err := clerk.JoinPath(path, string(params.TemplateType), params.Slug) 35 | if err != nil { 36 | return nil, err 37 | } 38 | req := clerk.NewAPIRequest(http.MethodGet, path) 39 | resource := &clerk.Template{} 40 | err = c.Backend.Call(ctx, req, resource) 41 | return resource, err 42 | } 43 | 44 | type UpdateParams struct { 45 | clerk.APIParams 46 | Name *string `json:"name,omitempty"` 47 | Subject *string `json:"subject,omitempty"` 48 | Markup *string `json:"markup,omitempty"` 49 | Body *string `json:"body,omitempty"` 50 | FromEmailName *string `json:"from_email_name,omitempty"` 51 | ReplyToEmailName *string `json:"reply_to_email_name,omitempty"` 52 | DeliveredByClerk *bool `json:"delivered_by_clerk,omitempty"` 53 | TemplateType clerk.TemplateType `json:"-"` 54 | Slug string `json:"-"` 55 | } 56 | 57 | // Update updates an existing template or creates a new one with the 58 | // provided params. 59 | func (c *Client) Update(ctx context.Context, params *UpdateParams) (*clerk.Template, error) { 60 | path, err := clerk.JoinPath(path, string(params.TemplateType), params.Slug) 61 | if err != nil { 62 | return nil, err 63 | } 64 | req := clerk.NewAPIRequest(http.MethodPut, path) 65 | req.SetParams(params) 66 | resource := &clerk.Template{} 67 | err = c.Backend.Call(ctx, req, resource) 68 | return resource, err 69 | } 70 | 71 | type DeleteParams struct { 72 | TemplateType clerk.TemplateType `json:"-"` 73 | Slug string `json:"-"` 74 | } 75 | 76 | // Delete deletes a custom user template. 77 | func (c *Client) Delete(ctx context.Context, params *DeleteParams) (*clerk.DeletedResource, error) { 78 | path, err := clerk.JoinPath(path, string(params.TemplateType), params.Slug) 79 | if err != nil { 80 | return nil, err 81 | } 82 | req := clerk.NewAPIRequest(http.MethodDelete, path) 83 | resource := &clerk.DeletedResource{} 84 | err = c.Backend.Call(ctx, req, resource) 85 | return resource, err 86 | } 87 | 88 | type RevertParams struct { 89 | TemplateType clerk.TemplateType `json:"-"` 90 | Slug string `json:"-"` 91 | } 92 | 93 | // Revert reverts a template to its default state. 94 | func (c *Client) Revert(ctx context.Context, params *RevertParams) (*clerk.Template, error) { 95 | path, err := clerk.JoinPath(path, string(params.TemplateType), params.Slug, "/revert") 96 | if err != nil { 97 | return nil, err 98 | } 99 | req := clerk.NewAPIRequest(http.MethodPost, path) 100 | resource := &clerk.Template{} 101 | err = c.Backend.Call(ctx, req, resource) 102 | return resource, err 103 | } 104 | 105 | type ToggleDeliveryParams struct { 106 | clerk.APIParams 107 | DeliveredByClerk *bool `json:"delivered_by_clerk,omitempty"` 108 | TemplateType clerk.TemplateType `json:"-"` 109 | Slug string `json:"-"` 110 | } 111 | 112 | // ToggleDelivery sets the delivery by Clerk for a template. 113 | func (c *Client) ToggleDelivery(ctx context.Context, params *ToggleDeliveryParams) (*clerk.Template, error) { 114 | path, err := clerk.JoinPath(path, string(params.TemplateType), params.Slug, "/toggle_delivery") 115 | if err != nil { 116 | return nil, err 117 | } 118 | req := clerk.NewAPIRequest(http.MethodPost, path) 119 | req.SetParams(params) 120 | resource := &clerk.Template{} 121 | err = c.Backend.Call(ctx, req, resource) 122 | return resource, err 123 | } 124 | 125 | type PreviewParams struct { 126 | clerk.APIParams 127 | Subject *string `json:"subject,omitempty"` 128 | Body *string `json:"body,omitempty"` 129 | FromEmailName *string `json:"from_email_name,omitempty"` 130 | ReplyToEmailName *string `json:"reply_to_email_name,omitempty"` 131 | TemplateType clerk.TemplateType `json:"-"` 132 | Slug string `json:"-"` 133 | } 134 | 135 | // Preview returns a preview of a template. 136 | func (c *Client) Preview(ctx context.Context, params *PreviewParams) (*clerk.TemplatePreview, error) { 137 | path, err := clerk.JoinPath(path, string(params.TemplateType), params.Slug, "/preview") 138 | if err != nil { 139 | return nil, err 140 | } 141 | req := clerk.NewAPIRequest(http.MethodPost, path) 142 | req.SetParams(params) 143 | resource := &clerk.TemplatePreview{} 144 | err = c.Backend.Call(ctx, req, resource) 145 | return resource, err 146 | } 147 | 148 | type ListParams struct { 149 | TemplateType clerk.TemplateType `json:"-"` 150 | } 151 | 152 | // List returns a list of templates of a given type. 153 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.TemplateList, error) { 154 | path, err := clerk.JoinPath(path, fmt.Sprintf("%s?paginated=true", params.TemplateType)) 155 | if err != nil { 156 | return nil, err 157 | } 158 | req := clerk.NewAPIRequest(http.MethodGet, path) 159 | list := &clerk.TemplateList{} 160 | err = c.Backend.Call(ctx, req, list) 161 | return list, err 162 | } 163 | -------------------------------------------------------------------------------- /testing_token.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type TestingToken struct { 4 | APIResource 5 | Object string `json:"object"` 6 | Token string `json:"token"` 7 | ExpiresAt int64 `json:"expires_at"` 8 | } 9 | -------------------------------------------------------------------------------- /testingtoken/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package testingtoken 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new testing token. 12 | func Create(ctx context.Context) (*clerk.TestingToken, error) { 13 | return getClient().Create(ctx) 14 | } 15 | 16 | func getClient() *Client { 17 | return &Client{ 18 | Backend: clerk.GetBackend(), 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /testingtoken/client.go: -------------------------------------------------------------------------------- 1 | // Package testingtoken provides the Testing Tokens API. 2 | // 3 | // https://clerk.com/docs/reference/backend-api/tag/Testing-Tokens 4 | package testingtoken 5 | 6 | import ( 7 | "context" 8 | "net/http" 9 | 10 | "github.com/clerk/clerk-sdk-go/v2" 11 | ) 12 | 13 | //go:generate go run ../cmd/gen/main.go 14 | 15 | const path = "/testing_tokens" 16 | 17 | // Client is used to invoke the Testing Tokens API. 18 | type Client struct { 19 | Backend clerk.Backend 20 | } 21 | 22 | func NewClient(config *clerk.ClientConfig) *Client { 23 | return &Client{ 24 | Backend: clerk.NewBackend(&config.BackendConfig), 25 | } 26 | } 27 | 28 | // Create creates a new testing token. 29 | func (c *Client) Create(ctx context.Context) (*clerk.TestingToken, error) { 30 | req := clerk.NewAPIRequest(http.MethodPost, path) 31 | token := &clerk.TestingToken{} 32 | err := c.Backend.Call(ctx, req, token) 33 | return token, err 34 | } 35 | -------------------------------------------------------------------------------- /testingtoken/client_test.go: -------------------------------------------------------------------------------- 1 | package testingtoken 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "net/http" 7 | "testing" 8 | 9 | "github.com/clerk/clerk-sdk-go/v2" 10 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 11 | "github.com/stretchr/testify/require" 12 | ) 13 | 14 | func TestTestingTokenClientCreate(t *testing.T) { 15 | t.Parallel() 16 | 17 | config := &clerk.ClientConfig{} 18 | config.HTTPClient = &http.Client{ 19 | Transport: &clerktest.RoundTripper{ 20 | T: t, 21 | In: nil, 22 | Out: json.RawMessage( 23 | `{"object":"testing_token","token":"1713877200-c_3G2MvPu9PnXcuhbPZNao0LOXqK9A7YrnBn0HmIWxt","expires_at":1713880800}`, 24 | ), 25 | Method: http.MethodPost, 26 | Path: "/v1/testing_tokens", 27 | }, 28 | } 29 | client := NewClient(config) 30 | token, err := client.Create(context.Background()) 31 | require.NoError(t, err) 32 | require.Equal(t, "testing_token", token.Object) 33 | require.Equal(t, "1713877200-c_3G2MvPu9PnXcuhbPZNao0LOXqK9A7YrnBn0HmIWxt", token.Token) 34 | require.Equal(t, int64(1713880800), token.ExpiresAt) 35 | } 36 | -------------------------------------------------------------------------------- /totp.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | // Describes a Time-based One-time Password (TOTP) for a user. 4 | type TOTP struct { 5 | APIResource 6 | Object string `json:"object"` 7 | ID string `json:"id"` 8 | Secret *string `json:"secret"` 9 | URI *string `json:"uri" ` 10 | Verified bool `json:"verified"` 11 | BackupCodes []string `json:"backup_codes"` 12 | CreatedAt int64 `json:"created_at"` 13 | UpdatedAt int64 `json:"updated_at"` 14 | } 15 | -------------------------------------------------------------------------------- /user.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | import "encoding/json" 4 | 5 | type User struct { 6 | APIResource 7 | Object string `json:"object"` 8 | ID string `json:"id"` 9 | Username *string `json:"username"` 10 | FirstName *string `json:"first_name"` 11 | LastName *string `json:"last_name"` 12 | ImageURL *string `json:"image_url,omitempty"` 13 | HasImage bool `json:"has_image"` 14 | PrimaryEmailAddressID *string `json:"primary_email_address_id"` 15 | PrimaryPhoneNumberID *string `json:"primary_phone_number_id"` 16 | PrimaryWeb3WalletID *string `json:"primary_web3_wallet_id"` 17 | PasswordEnabled bool `json:"password_enabled"` 18 | TwoFactorEnabled bool `json:"two_factor_enabled"` 19 | TOTPEnabled bool `json:"totp_enabled"` 20 | BackupCodeEnabled bool `json:"backup_code_enabled"` 21 | EmailAddresses []*EmailAddress `json:"email_addresses"` 22 | PhoneNumbers []*PhoneNumber `json:"phone_numbers"` 23 | Web3Wallets []*Web3Wallet `json:"web3_wallets"` 24 | ExternalAccounts []*ExternalAccount `json:"external_accounts"` 25 | SAMLAccounts []*SAMLAccount `json:"saml_accounts"` 26 | PasswordLastUpdatedAt *int64 `json:"password_last_updated_at,omitempty"` 27 | PublicMetadata json.RawMessage `json:"public_metadata"` 28 | PrivateMetadata json.RawMessage `json:"private_metadata,omitempty"` 29 | UnsafeMetadata json.RawMessage `json:"unsafe_metadata,omitempty"` 30 | ExternalID *string `json:"external_id"` 31 | LastSignInAt *int64 `json:"last_sign_in_at"` 32 | Banned bool `json:"banned"` 33 | Locked bool `json:"locked"` 34 | LockoutExpiresInSeconds *int64 `json:"lockout_expires_in_seconds"` 35 | VerificationAttemptsRemaining *int64 `json:"verification_attempts_remaining"` 36 | DeleteSelfEnabled bool `json:"delete_self_enabled"` 37 | CreateOrganizationEnabled bool `json:"create_organization_enabled"` 38 | CreateOrganizationsLimit *int `json:"create_organizations_limit,omitempty"` 39 | LastActiveAt *int64 `json:"last_active_at"` 40 | LegalAcceptedAt *int64 `json:"legal_accepted_at"` 41 | CreatedAt int64 `json:"created_at"` 42 | UpdatedAt int64 `json:"updated_at"` 43 | } 44 | 45 | type ExternalAccount struct { 46 | Object string `json:"object"` 47 | ID string `json:"id"` 48 | Provider string `json:"provider"` 49 | IdentificationID string `json:"identification_id"` 50 | ProviderUserID string `json:"provider_user_id"` 51 | ApprovedScopes string `json:"approved_scopes"` 52 | EmailAddress string `json:"email_address"` 53 | FirstName string `json:"first_name"` 54 | LastName string `json:"last_name"` 55 | AvatarURL string `json:"avatar_url"` 56 | ImageURL *string `json:"image_url,omitempty"` 57 | Username *string `json:"username"` 58 | PublicMetadata json.RawMessage `json:"public_metadata"` 59 | Label *string `json:"label"` 60 | Verification *Verification `json:"verification"` 61 | } 62 | 63 | type Web3Wallet struct { 64 | Object string `json:"object"` 65 | ID string `json:"id"` 66 | Web3Wallet string `json:"web3_wallet"` 67 | Verification *Verification `json:"verification"` 68 | } 69 | 70 | type SAMLAccount struct { 71 | Object string `json:"object"` 72 | ID string `json:"id"` 73 | Provider string `json:"provider"` 74 | Active bool `json:"active"` 75 | EmailAddress string `json:"email_address"` 76 | FirstName *string `json:"first_name"` 77 | LastName *string `json:"last_name"` 78 | ProviderUserID *string `json:"provider_user_id"` 79 | PublicMetadata json.RawMessage `json:"public_metadata"` 80 | Verification *Verification `json:"verification"` 81 | } 82 | 83 | type UserList struct { 84 | APIResource 85 | Users []*User `json:"data"` 86 | TotalCount int64 `json:"total_count"` 87 | } 88 | -------------------------------------------------------------------------------- /user/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package user 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // Create creates a new user. 12 | func Create(ctx context.Context, params *CreateParams) (*clerk.User, error) { 13 | return getClient().Create(ctx, params) 14 | } 15 | 16 | // Get retrieves details about the user. 17 | func Get(ctx context.Context, id string) (*clerk.User, error) { 18 | return getClient().Get(ctx, id) 19 | } 20 | 21 | // Update updates a user. 22 | func Update(ctx context.Context, id string, params *UpdateParams) (*clerk.User, error) { 23 | return getClient().Update(ctx, id, params) 24 | } 25 | 26 | // UpdateProfileImage sets or replaces the user's profile image. 27 | func UpdateProfileImage(ctx context.Context, id string, params *UpdateProfileImageParams) (*clerk.User, error) { 28 | return getClient().UpdateProfileImage(ctx, id, params) 29 | } 30 | 31 | // DeleteProfileImage deletes the user's profile image. 32 | func DeleteProfileImage(ctx context.Context, id string) (*clerk.User, error) { 33 | return getClient().DeleteProfileImage(ctx, id) 34 | } 35 | 36 | // UpdateMetadata updates the user's metadata by merging the 37 | // provided values with the existing ones. 38 | func UpdateMetadata(ctx context.Context, id string, params *UpdateMetadataParams) (*clerk.User, error) { 39 | return getClient().UpdateMetadata(ctx, id, params) 40 | } 41 | 42 | // Delete deletes a user. 43 | func Delete(ctx context.Context, id string) (*clerk.DeletedResource, error) { 44 | return getClient().Delete(ctx, id) 45 | } 46 | 47 | // List returns a list of users. 48 | func List(ctx context.Context, params *ListParams) (*clerk.UserList, error) { 49 | return getClient().List(ctx, params) 50 | } 51 | 52 | // Count returns the total count of users satisfying the parameters. 53 | func Count(ctx context.Context, params *ListParams) (*TotalCount, error) { 54 | return getClient().Count(ctx, params) 55 | } 56 | 57 | // ListOAuthAccessTokens retrieves a list of the user's access 58 | // tokens for a specific OAuth provider. 59 | func ListOAuthAccessTokens(ctx context.Context, params *ListOAuthAccessTokensParams) (*clerk.OAuthAccessTokenList, error) { 60 | return getClient().ListOAuthAccessTokens(ctx, params) 61 | } 62 | 63 | // DeleteMFA disables a user's multi-factor authentication methods. 64 | func DeleteMFA(ctx context.Context, params *DeleteMFAParams) (*MultifactorAuthentication, error) { 65 | return getClient().DeleteMFA(ctx, params) 66 | } 67 | 68 | // Ban marks the user as banned. 69 | func Ban(ctx context.Context, id string) (*clerk.User, error) { 70 | return getClient().Ban(ctx, id) 71 | } 72 | 73 | // Unban removes the ban for a user. 74 | func Unban(ctx context.Context, id string) (*clerk.User, error) { 75 | return getClient().Unban(ctx, id) 76 | } 77 | 78 | // Lock marks the user as locked. 79 | func Lock(ctx context.Context, id string) (*clerk.User, error) { 80 | return getClient().Lock(ctx, id) 81 | } 82 | 83 | // Unlock removes the lock for a user. 84 | func Unlock(ctx context.Context, id string) (*clerk.User, error) { 85 | return getClient().Unlock(ctx, id) 86 | } 87 | 88 | // ListOrganizationMemberships lists all the user's organization memberships. 89 | func ListOrganizationMemberships(ctx context.Context, id string, params *ListOrganizationMembershipsParams) (*clerk.OrganizationMembershipList, error) { 90 | return getClient().ListOrganizationMemberships(ctx, id, params) 91 | } 92 | 93 | // ListOrganizationInvitations lists all the user's organization invitations. 94 | func ListOrganizationInvitations(ctx context.Context, params *ListOrganizationInvitationsParams) (*clerk.OrganizationInvitationList, error) { 95 | return getClient().ListOrganizationInvitations(ctx, params) 96 | } 97 | 98 | // DeletePasskey deletes a passkey by its identification ID. 99 | func DeletePasskey(ctx context.Context, userID, identificationID string) (*clerk.DeletedResource, error) { 100 | return getClient().DeletePasskey(ctx, userID, identificationID) 101 | } 102 | 103 | // DeleteWeb3Wallet deletes a web3 wallet by its identification ID. 104 | func DeleteWeb3Wallet(ctx context.Context, userID, identificationID string) (*clerk.DeletedResource, error) { 105 | return getClient().DeleteWeb3Wallet(ctx, userID, identificationID) 106 | } 107 | 108 | // Deprecated: CreateTOTP creates a TOTP (Time-based One-Time Password) for the user. 109 | // The endpoint used for this method has been removed, we kept the method for backwards compatibility, 110 | // and now it's a noop action. 111 | func CreateTOTP(ctx context.Context, userID string) (*clerk.TOTP, error) { 112 | return getClient().CreateTOTP(ctx, userID) 113 | } 114 | 115 | // DeleteTOTP deletes all the TOTPs from a given user. 116 | func DeleteTOTP(ctx context.Context, userID string) (*MultifactorAuthentication, error) { 117 | return getClient().DeleteTOTP(ctx, userID) 118 | } 119 | 120 | // DeleteBackupCode deletes all the backup codes from a given user. 121 | func DeleteBackupCode(ctx context.Context, userID string) (*MultifactorAuthentication, error) { 122 | return getClient().DeleteBackupCode(ctx, userID) 123 | } 124 | 125 | // DeleteExternalAccount deletes an external account by its ID. 126 | func DeleteExternalAccount(ctx context.Context, params *DeleteExternalAccountParams) (*clerk.DeletedResource, error) { 127 | return getClient().DeleteExternalAccount(ctx, params) 128 | } 129 | 130 | // VerifyPassword verifies a user's password, returns an error if the password is incorrect. 131 | func VerifyPassword(ctx context.Context, params *VerifyPasswordParams) (*VerifyPasswordResponse, error) { 132 | return getClient().VerifyPassword(ctx, params) 133 | } 134 | 135 | func getClient() *Client { 136 | return &Client{ 137 | Backend: clerk.GetBackend(), 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /waitlist_entries.go: -------------------------------------------------------------------------------- 1 | package clerk 2 | 3 | type WaitlistEntry struct { 4 | APIResource 5 | Object string `json:"object"` 6 | ID string `json:"id"` 7 | EmailAddress string `json:"email_address"` 8 | Status string `json:"status"` 9 | CreatedAt int64 `json:"created_at"` 10 | UpdatedAt int64 `json:"updated_at"` 11 | Invitation *Invitation `json:"invitation"` 12 | } 13 | 14 | type WaitlistEntriesList struct { 15 | APIResource 16 | WaitlistEntries []*WaitlistEntry `json:"data"` 17 | TotalCount int64 `json:"total_count"` 18 | } 19 | -------------------------------------------------------------------------------- /waitlistentry/api.go: -------------------------------------------------------------------------------- 1 | // Code generated by "gen"; DO NOT EDIT. 2 | // This file is meant to be re-generated in place and/or deleted at any time. 3 | package waitlistentry 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | // List returns all waitlist entries. 12 | func List(ctx context.Context, params *ListParams) (*clerk.WaitlistEntriesList, error) { 13 | return getClient().List(ctx, params) 14 | } 15 | 16 | // Create adds a new waitlist entry. 17 | func Create(ctx context.Context, params *CreateParams) (*clerk.WaitlistEntry, error) { 18 | return getClient().Create(ctx, params) 19 | } 20 | 21 | func getClient() *Client { 22 | return &Client{ 23 | Backend: clerk.GetBackend(), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /waitlistentry/client.go: -------------------------------------------------------------------------------- 1 | package waitlistentry 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | "net/url" 7 | 8 | "github.com/clerk/clerk-sdk-go/v2" 9 | ) 10 | 11 | //go:generate go run ../cmd/gen/main.go 12 | 13 | const path = "/waitlist_entries" 14 | 15 | // Client is used to invoke the Waitlist Entries API. 16 | type Client struct { 17 | Backend clerk.Backend 18 | } 19 | 20 | func NewClient(config *clerk.ClientConfig) *Client { 21 | return &Client{ 22 | Backend: clerk.NewBackend(&config.BackendConfig), 23 | } 24 | } 25 | 26 | type ListParams struct { 27 | clerk.APIParams 28 | clerk.ListParams 29 | OrderBy *string `json:"order_by,omitempty"` 30 | Query *string `json:"query,omitempty"` 31 | Statuses []string `json:"status,omitempty"` 32 | } 33 | 34 | // ToQuery returns query string values from the params. 35 | func (params *ListParams) ToQuery() url.Values { 36 | q := params.ListParams.ToQuery() 37 | if params.OrderBy != nil { 38 | q.Set("order_by", *params.OrderBy) 39 | } 40 | if params.Query != nil { 41 | q.Set("query", *params.Query) 42 | } 43 | for _, status := range params.Statuses { 44 | q.Add("status", status) 45 | } 46 | return q 47 | } 48 | 49 | // List returns all waitlist entries. 50 | func (c *Client) List(ctx context.Context, params *ListParams) (*clerk.WaitlistEntriesList, error) { 51 | req := clerk.NewAPIRequest(http.MethodGet, path) 52 | req.SetParams(params) 53 | list := &clerk.WaitlistEntriesList{} 54 | err := c.Backend.Call(ctx, req, list) 55 | return list, err 56 | } 57 | 58 | type CreateParams struct { 59 | clerk.APIParams 60 | EmailAddress string `json:"email_address"` 61 | Notify *bool `json:"notify,omitempty"` 62 | } 63 | 64 | // Create adds a new waitlist entry. 65 | func (c *Client) Create(ctx context.Context, params *CreateParams) (*clerk.WaitlistEntry, error) { 66 | req := clerk.NewAPIRequest(http.MethodPost, path) 67 | req.SetParams(params) 68 | invitation := &clerk.WaitlistEntry{} 69 | err := c.Backend.Call(ctx, req, invitation) 70 | return invitation, err 71 | } 72 | -------------------------------------------------------------------------------- /waitlistentry/waitlistentry_test.go: -------------------------------------------------------------------------------- 1 | package waitlistentry 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "fmt" 7 | "net/http" 8 | "net/url" 9 | "testing" 10 | 11 | "github.com/clerk/clerk-sdk-go/v2" 12 | "github.com/clerk/clerk-sdk-go/v2/clerktest" 13 | "github.com/stretchr/testify/require" 14 | ) 15 | 16 | func TestWaitlistList(t *testing.T) { 17 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 18 | HTTPClient: &http.Client{ 19 | Transport: &clerktest.RoundTripper{ 20 | T: t, 21 | Out: json.RawMessage(`{ 22 | "data": [{"id":"wle_123","email_address":"foo@bar.com"}], 23 | "total_count": 1 24 | }`), 25 | Path: "/v1/waitlist_entries", 26 | Method: http.MethodGet, 27 | }, 28 | }, 29 | })) 30 | 31 | list, err := List(context.Background(), &ListParams{}) 32 | require.NoError(t, err) 33 | require.Equal(t, int64(1), list.TotalCount) 34 | require.Equal(t, 1, len(list.WaitlistEntries)) 35 | require.Equal(t, "wle_123", list.WaitlistEntries[0].ID) 36 | require.Equal(t, "foo@bar.com", list.WaitlistEntries[0].EmailAddress) 37 | } 38 | 39 | func TestWaitlistEntriesListWithParams(t *testing.T) { 40 | limit := int64(10) 41 | offset := int64(20) 42 | orderBy := "-created_at" 43 | query := "example@email.com" 44 | status1 := "pending" 45 | status2 := "invited" 46 | 47 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 48 | HTTPClient: &http.Client{ 49 | Transport: &clerktest.RoundTripper{ 50 | T: t, 51 | Out: json.RawMessage(`{ 52 | "data": [ 53 | {"id":"wle_123","email_address":"foo@bar.com"}, 54 | {"id":"wle_124","email_address":"baz@qux.com","invitation":{"id":"inv_124","email_address":"baz@qux.com"}} 55 | ], 56 | "total_count": 2 57 | }`), 58 | Path: "/v1/waitlist_entries", 59 | Method: http.MethodGet, 60 | Query: &url.Values{ 61 | "limit": []string{fmt.Sprintf("%d", limit)}, 62 | "offset": []string{fmt.Sprintf("%d", offset)}, 63 | "order_by": []string{orderBy}, 64 | "query": []string{query}, 65 | "status": []string{status1, status2}, 66 | }, 67 | }, 68 | }, 69 | })) 70 | 71 | list, err := List(context.Background(), &ListParams{ 72 | ListParams: clerk.ListParams{ 73 | Limit: &limit, 74 | Offset: &offset, 75 | }, 76 | OrderBy: &orderBy, 77 | Query: &query, 78 | Statuses: []string{status1, status2}, 79 | }) 80 | require.NoError(t, err) 81 | require.Equal(t, int64(2), list.TotalCount) 82 | require.Len(t, list.WaitlistEntries, 2) 83 | require.Equal(t, "wle_123", list.WaitlistEntries[0].ID) 84 | require.Equal(t, "foo@bar.com", list.WaitlistEntries[0].EmailAddress) 85 | require.Nil(t, list.WaitlistEntries[0].Invitation) 86 | require.Equal(t, "wle_124", list.WaitlistEntries[1].ID) 87 | require.Equal(t, "baz@qux.com", list.WaitlistEntries[1].EmailAddress) 88 | require.NotNil(t, list.WaitlistEntries[1].Invitation) 89 | require.Equal(t, "inv_124", list.WaitlistEntries[1].Invitation.ID) 90 | require.Equal(t, "baz@qux.com", list.WaitlistEntries[1].Invitation.EmailAddress) 91 | } 92 | 93 | func TestWaitlistEntryCreate(t *testing.T) { 94 | emailAddress := "foo@bar.com" 95 | id := "inv_123" 96 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 97 | HTTPClient: &http.Client{ 98 | Transport: &clerktest.RoundTripper{ 99 | T: t, 100 | In: json.RawMessage(fmt.Sprintf(`{"email_address":"%s"}`, emailAddress)), 101 | Out: json.RawMessage(fmt.Sprintf(`{"id":"%s","email_address":"%s"}`, id, emailAddress)), 102 | Method: http.MethodPost, 103 | Path: "/v1/waitlist_entries", 104 | }, 105 | }, 106 | })) 107 | 108 | entry, err := Create(context.Background(), &CreateParams{ 109 | EmailAddress: emailAddress, 110 | }) 111 | require.NoError(t, err) 112 | require.Equal(t, id, entry.ID) 113 | require.Equal(t, emailAddress, entry.EmailAddress) 114 | } 115 | 116 | func TestWaitlistEntryCreate_Error(t *testing.T) { 117 | clerk.SetBackend(clerk.NewBackend(&clerk.BackendConfig{ 118 | HTTPClient: &http.Client{ 119 | Transport: &clerktest.RoundTripper{ 120 | T: t, 121 | Status: http.StatusBadRequest, 122 | Out: json.RawMessage(`{ 123 | "errors":[{ 124 | "code":"create-error-code" 125 | }], 126 | "clerk_trace_id":"create-trace-id" 127 | }`), 128 | }, 129 | }, 130 | })) 131 | 132 | _, err := Create(context.Background(), &CreateParams{}) 133 | require.Error(t, err) 134 | apiErr, ok := err.(*clerk.APIErrorResponse) 135 | require.True(t, ok) 136 | require.Equal(t, "create-trace-id", apiErr.TraceID) 137 | require.Equal(t, 1, len(apiErr.Errors)) 138 | require.Equal(t, "create-error-code", apiErr.Errors[0].Code) 139 | } 140 | --------------------------------------------------------------------------------