Repository: amp-labs/connectors
Pull request #138 (2024-03-29 23:30:47)

[ENG-878] Add delete mode in bulk operation
adding "delete" mode and some linting and clean up


Patch:
diff --git a/go.mod b/go.mod
index e9b34104..7ec225df 100644
--- a/go.mod
+++ b/go.mod
@@ -9,7 +9,7 @@ require (
 	github.com/spyzhov/ajson v0.9.1
 	github.com/stretchr/testify v1.9.0
 	github.com/subchen/go-xmldom v1.1.2
-	golang.org/x/oauth2 v0.18.0
+	golang.org/x/oauth2 v0.19.0
 )
 
 require (
@@ -23,11 +23,7 @@ require (
 
 require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	golang.org/x/net v0.22.0 // indirect
-	google.golang.org/appengine v1.6.7 // indirect
-	google.golang.org/protobuf v1.33.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	gotest.tools/v3 v3.5.1
 )
diff --git a/go.sum b/go.sum
index dff46551..b0499960 100644
--- a/go.sum
+++ b/go.sum
@@ -10,11 +10,6 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
 github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA=
 github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig=
-github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
@@ -29,23 +24,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/subchen/go-xmldom v1.1.2 h1:7evI2YqfYYOnuj+PBwyaOZZYjl3iWq35P6KfBUw9jeU=
 github.com/subchen/go-xmldom v1.1.2/go.mod h1:6Pg/HuX5/T4Jlj0IPJF1sRxKVoI/rrKP6LIMge9d5/8=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
-golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
-golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
-golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
+golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
diff --git a/providers/catalog.go b/providers/catalog.go
index f9e19872..819ef715 100644
--- a/providers/catalog.go
+++ b/providers/catalog.go
@@ -23,7 +23,7 @@ const (
 	Gong                                Provider = "gong"
 	Zoom                                Provider = "zoom"
 	Intercom                            Provider = "intercom"
-  	Capsule                             Provider = "capsule"
+	Capsule                             Provider = "capsule"
 	DocuSign                            Provider = "docuSign"
 	DocuSignDeveloper                   Provider = "docuSignDeveloper"
 	Calendly                            Provider = "calendly"
@@ -33,6 +33,12 @@ const (
 	MicrosoftDynamics365Sales           Provider = "microsoftDynamics365Sales"
 	MicrosoftDynamics365BusinessCentral Provider = "microsoftDynamics365BusinessCentral"
 	Gainsight                           Provider = "gainsight"
+	Box                                 Provider = "box"
+	GoogleCalendar                      Provider = "googleCalendar"
+	ZendeskSupport                      Provider = "zendeskSupport"
+	ZendeskChat                         Provider = "zendeskChat"
+	WordPress                           Provider = "wordPress"
+	Airtable                            Provider = "airtable"
 )
 
 // ================================================================================
@@ -45,6 +51,7 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 		AuthType: Oauth2,
 		BaseURL:  "https://{{.workspace}}.my.salesforce.com",
 		OauthOpts: OauthOpts{
+			GrantType:                 AuthorizationCode,
 			AuthURL:                   "https://{{.workspace}}.my.salesforce.com/services/oauth2/authorize",
 			TokenURL:                  "https://{{.workspace}}.my.salesforce.com/services/oauth2/token",
 			ExplicitScopesRequired:    false,
@@ -56,7 +63,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			},
 		},
 		Support: Support{
-			BulkWrite: true,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: true,
+				Delete: false,
+			},
 			Proxy:     true,
 			Read:      true,
 			Subscribe: false,
@@ -73,13 +85,19 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 		AuthType: Oauth2,
 		BaseURL:  "https://api.hubapi.com",
 		OauthOpts: OauthOpts{
+			GrantType:                 AuthorizationCode,
 			AuthURL:                   "https://app.hubspot.com/oauth/authorize",
 			TokenURL:                  "https://api.hubapi.com/oauth/v1/token",
 			ExplicitScopesRequired:    true,
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     true,
 			Read:      true,
 			Subscribe: false,
@@ -92,6 +110,7 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 		AuthType: Oauth2,
 		BaseURL:  "https://api.linkedin.com",
 		OauthOpts: OauthOpts{
+			GrantType:                 AuthorizationCode,
 			AuthURL:                   "https://www.linkedin.com/oauth/v2/authorization",
 			TokenURL:                  "https://www.linkedin.com/oauth/v2/accessToken",
 			ExplicitScopesRequired:    true,
@@ -101,7 +120,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			},
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -120,7 +144,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -139,7 +168,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -158,7 +192,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -177,7 +216,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -196,7 +240,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -215,7 +264,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -234,7 +288,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -253,7 +312,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -272,7 +336,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -291,7 +360,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -310,7 +384,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -329,7 +408,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -352,7 +436,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			},
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     true,
 			Read:      false,
 			Subscribe: false,
@@ -371,7 +460,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -390,7 +484,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -409,7 +508,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -428,7 +532,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: true,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -447,7 +556,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -466,7 +580,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -485,7 +604,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -504,7 +628,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -523,7 +652,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: true,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -542,7 +676,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: false,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -564,7 +703,12 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			},
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
@@ -583,7 +727,161 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			ExplicitWorkspaceRequired: true,
 		},
 		Support: Support{
-			BulkWrite: false,
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
+
+	// Box configuration
+	Box: {
+		AuthType: Oauth2,
+		BaseURL:  "https://api.box.com",
+		OauthOpts: OauthOpts{
+			AuthURL:                   "https://account.box.com/api/oauth2/authorize",
+			TokenURL:                  "https://api.box.com/oauth2/token",
+			ExplicitScopesRequired:    false,
+			ExplicitWorkspaceRequired: false,
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
+
+	GoogleCalendar: {
+		AuthType: Oauth2,
+		BaseURL:  "https://www.googleapis.com/calendar",
+		OauthOpts: OauthOpts{
+			AuthURL:                   "https://accounts.google.com/o/oauth2/v2/auth",
+			TokenURL:                  "https://oauth2.googleapis.com/token",
+			ExplicitScopesRequired:    true,
+			ExplicitWorkspaceRequired: false,
+			TokenMetadataFields: TokenMetadataFields{
+				ScopesField: "scope",
+			},
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
+
+	// Zendesk Support configuration
+	ZendeskSupport: {
+		AuthType: Oauth2,
+		BaseURL:  "https://{{.workspace}}.zendesk.com",
+		OauthOpts: OauthOpts{
+			AuthURL:                   "https://{{.workspace}}.zendesk.com/oauth/authorizations/new",
+			TokenURL:                  "https://{{.workspace}}.zendesk.com/oauth/tokens",
+			ExplicitScopesRequired:    true,
+			ExplicitWorkspaceRequired: true,
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
+
+	ZendeskChat: {
+		AuthType: Oauth2,
+		BaseURL:  "https://www.zopim.com",
+		OauthOpts: OauthOpts{
+			AuthURL:                   "https://www.zopim.com/oauth2/authorizations/new?subdomain={{.workspace}}",
+			TokenURL:                  "https://www.zopim.com/oauth2/token",
+			ExplicitScopesRequired:    true,
+			ExplicitWorkspaceRequired: true,
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
+
+	// WordPress Support configuration
+	WordPress: {
+		AuthType: Oauth2,
+		BaseURL:  "https://public-api.wordpress.com",
+		OauthOpts: OauthOpts{
+			AuthURL:                   "https://public-api.wordpress.com/oauth2/authorize",
+			TokenURL:                  "https://public-api.wordpress.com/oauth2/token",
+			ExplicitScopesRequired:    false,
+			ExplicitWorkspaceRequired: false,
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
+
+	// Airtable Support Configuration
+	Airtable: {
+		AuthType: Oauth2,
+		BaseURL:  "https://api.airtable.com",
+		OauthOpts: OauthOpts{
+			GrantType:                 PKCE,
+			AuthURL:                   "https://airtable.com/oauth2/v1/authorize",
+			TokenURL:                  "https://airtable.com/oauth2/v1/token",
+			ExplicitScopesRequired:    true,
+			ExplicitWorkspaceRequired: false,
+			TokenMetadataFields: TokenMetadataFields{
+				ScopesField: "scope",
+			},
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
 			Proxy:     false,
 			Read:      false,
 			Subscribe: false,
diff --git a/providers/types.gen.go b/providers/types.gen.go
index cdb00f36..2bebb1ce 100644
--- a/providers/types.gen.go
+++ b/providers/types.gen.go
@@ -1,6 +1,6 @@
 // Package providers provides primitives to interact with the openapi HTTP API.
 //
-// Code generated by github.com/deepmap/oapi-codegen version v1.15.0 DO NOT EDIT.
+// Code generated by github.com/deepmap/oapi-codegen version v1.16.2 DO NOT EDIT.
 package providers
 
 // Defines values for AuthType.
@@ -8,9 +8,24 @@ const (
 	Oauth2 AuthType = "oauth2"
 )
 
+// Defines values for OauthOptsGrantType.
+const (
+	AuthorizationCode OauthOptsGrantType = "authorizationCode"
+	ClientCredentials OauthOptsGrantType = "clientCredentials"
+	PKCE              OauthOptsGrantType = "PKCE"
+)
+
 // AuthType defines model for AuthType.
 type AuthType string
 
+// BulkWriteSupport defines model for BulkWriteSupport.
+type BulkWriteSupport struct {
+	Delete bool `json:"delete"`
+	Insert bool `json:"insert"`
+	Update bool `json:"update"`
+	Upsert bool `json:"upsert"`
+}
+
 // CatalogType defines model for CatalogType.
 type CatalogType map[string]ProviderInfo
 
@@ -19,10 +34,14 @@ type OauthOpts struct {
 	AuthURL                   string              `json:"authURL" validate:"required"`
 	ExplicitScopesRequired    bool                `json:"explicitScopesRequired"`
 	ExplicitWorkspaceRequired bool                `json:"explicitWorkspaceRequired"`
+	GrantType                 OauthOptsGrantType  `json:"grantType"`
 	TokenMetadataFields       TokenMetadataFields `json:"tokenMetadataFields"`
 	TokenURL                  string              `json:"tokenURL" validate:"required"`
 }
 
+// OauthOptsGrantType defines model for OauthOpts.GrantType.
+type OauthOptsGrantType string
+
 // Provider defines model for Provider.
 type Provider = string
 
@@ -40,11 +59,11 @@ type ProviderOpts map[string]string
 
 // Support defines model for Support.
 type Support struct {
-	BulkWrite bool `json:"bulkWrite"`
-	Proxy     bool `json:"proxy"`
-	Read      bool `json:"read"`
-	Subscribe bool `json:"subscribe"`
-	Write     bool `json:"write"`
+	BulkWrite BulkWriteSupport `json:"bulkWrite" validate:"required"`
+	Proxy     bool             `json:"proxy"`
+	Read      bool             `json:"read"`
+	Subscribe bool             `json:"subscribe"`
+	Write     bool             `json:"write"`
 }
 
 // TokenMetadataFields defines model for TokenMetadataFields.
diff --git a/providers/types.yaml b/providers/types.yaml
index a344a1f4..cfae4d96 100644
--- a/providers/types.yaml
+++ b/providers/types.yaml
@@ -32,7 +32,7 @@ components:
         - write
       properties:
         bulkWrite:
-          type: boolean
+          $ref: '#/components/schemas/BulkWriteSupport'
         proxy:
           type: boolean
         read:
@@ -41,7 +41,24 @@ components:
           type: boolean
         write:
           type: boolean
-
+    BulkWriteSupport:
+      type: object
+      x-oapi-codegen-extra-tags:
+        validate: required
+      required:
+        - insert
+        - update
+        - upsert
+        - delete
+      properties:
+        insert:
+          type: boolean
+        update:
+          type: boolean
+        upsert:
+          type: boolean
+        delete:
+          type: boolean
     TokenMetadataFields:
       type: object
       properties:
@@ -63,12 +80,16 @@ components:
       x-oapi-codegen-extra-tags:
         validate: required
       required:
+          - grantType
           - authURL
           - tokenURL
           - explicitScopesRequired
           - explicitWorkspaceRequired
           - tokenMetadataFields
       properties:
+        grantType:
+          type: string
+          enum: [authorizationCode, clientCredentials, PKCE]
         authURL:
           type: string
           example: https://login.salesforce.com/services/oauth2/authorize
diff --git a/salesforce/bulk.go b/salesforce/bulk.go
index e2f4bfe2..2ec1eb18 100644
--- a/salesforce/bulk.go
+++ b/salesforce/bulk.go
@@ -14,9 +14,10 @@ import (
 )
 
 const (
-	Insert BulkWriteMode = "insert"
-	Upsert BulkWriteMode = "upsert"
-	Update BulkWriteMode = "update"
+	Insert BulkOperationMode = "insert"
+	Upsert BulkOperationMode = "upsert"
+	Update BulkOperationMode = "update"
+	Delete BulkOperationMode = "delete"
 
 	JobStateAborted        = "Aborted"
 	JobStateFailed         = "Failed"
@@ -50,10 +51,10 @@ type BulkOperationParams struct {
 	CSVData io.Reader // required
 
 	// Salesforce operation mode
-	Mode BulkWriteMode
+	Mode BulkOperationMode
 }
 
-type BulkWriteMode string
+type BulkOperationMode string
 
 // BulkOperation is what's returned from writing data via the BulkOperation call.
 type BulkOperationResult struct {
@@ -109,14 +110,7 @@ func (c *Connector) BulkWrite( //nolint:funlen,cyclop
 	config BulkOperationParams,
 ) (*BulkOperationResult, error) {
 	// Only support upsert for now
-	switch config.Mode {
-	case Upsert:
-		break
-	case Insert:
-		return nil, fmt.Errorf("%w: %s", ErrUnsupportedMode, "insert")
-	case Update:
-		return nil, fmt.Errorf("%w: %s", ErrUnsupportedMode, "Update")
-	default:
+	if config.Mode != Upsert {
 		return nil, fmt.Errorf("%w: %s", ErrUnsupportedMode, config.Mode)
 	}
 
@@ -128,12 +122,12 @@ func (c *Connector) BulkWrite( //nolint:funlen,cyclop
 		"lineEnding":          "LF",
 	}
 
-	result, err := c.bulkOperation(ctx, BulkOperationParams(config), jobBody)
+	result, err := c.bulkOperation(ctx, config, jobBody)
 	if err != nil {
 		return nil, fmt.Errorf("bulk write failed: %w", err)
 	}
 
-	return (*BulkOperationResult)(result), nil
+	return result, nil
 }
 
 func joinURLPath(baseURL string, paths ...string) (string, error) {
diff --git a/scripts/oauth/token.go b/scripts/oauth/token.go
index 0ecd2fb9..5ab69d63 100644
--- a/scripts/oauth/token.go
+++ b/scripts/oauth/token.go
@@ -242,6 +242,7 @@ func setup() *OAuthApp {
 	provider := registry.MustString("Provider")
 	clientId := registry.MustString("ClientId")
 	clientSecret := registry.MustString("ClientSecret")
+
 	state, err := registry.GetString("State")
 	if err != nil {
 		slog.Warn("no state attached, ensure that the provider doesn't require state")


Test patch:
diff --git a/providers/catalog_test.go b/providers/catalog_test.go
index cfc1cbb6..f57b8121 100644
--- a/providers/catalog_test.go
+++ b/providers/catalog_test.go
@@ -22,14 +22,20 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      true,
-				Write:     true,
-				BulkWrite: true,
+				Read:  true,
+				Write: true,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: true,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     true,
 			},
 			AuthType: Oauth2,
 			OauthOpts: OauthOpts{
+				GrantType:                 AuthorizationCode,
 				AuthURL:                   "https://example.my.salesforce.com/services/oauth2/authorize",
 				TokenURL:                  "https://example.my.salesforce.com/services/oauth2/token",
 				ExplicitWorkspaceRequired: true,
@@ -56,14 +62,20 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      true,
-				Write:     true,
-				BulkWrite: false,
+				Read:  true,
+				Write: true,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     true,
 			},
 			AuthType: Oauth2,
 			OauthOpts: OauthOpts{
+				GrantType:                 AuthorizationCode,
 				AuthURL:                   "https://app.hubspot.com/oauth/authorize",
 				TokenURL:                  "https://api.hubapi.com/oauth/v1/token",
 				ExplicitScopesRequired:    true,
@@ -81,14 +93,20 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
 			AuthType: Oauth2,
 			OauthOpts: OauthOpts{
+				GrantType:                 AuthorizationCode,
 				AuthURL:                   "https://www.linkedin.com/oauth/v2/authorization",
 				TokenURL:                  "https://www.linkedin.com/oauth/v2/accessToken",
 				ExplicitScopesRequired:    true,
@@ -118,9 +136,14 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -140,9 +163,14 @@ var testCases = []struct { // nolint
 		description: "Valid Outreach provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -169,7 +197,12 @@ var testCases = []struct { // nolint
 				ExplicitWorkspaceRequired: false,
 			},
 			Support: Support{
-				BulkWrite: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Proxy:     false,
 				Read:      false,
 				Subscribe: false,
@@ -191,7 +224,12 @@ var testCases = []struct { // nolint
 				ExplicitWorkspaceRequired: false,
 			},
 			Support: Support{
-				BulkWrite: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Proxy:     false,
 				Read:      false,
 				Subscribe: false,
@@ -207,9 +245,14 @@ var testCases = []struct { // nolint
 		description: "Valid Copper provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -230,9 +273,14 @@ var testCases = []struct { // nolint
 		description: "Valid ZohoCRM provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -259,7 +307,12 @@ var testCases = []struct { // nolint
 				ExplicitWorkspaceRequired: false,
 			},
 			Support: Support{
-				BulkWrite: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Proxy:     false,
 				Read:      false,
 				Subscribe: false,
@@ -278,9 +331,14 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -304,7 +362,12 @@ var testCases = []struct { // nolint
 				Read:  false,
 				Write: false,
 
-				BulkWrite: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -328,7 +391,12 @@ var testCases = []struct { // nolint
 				Read:  false,
 				Write: false,
 
-				BulkWrite: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -348,9 +416,14 @@ var testCases = []struct { // nolint
 		description: "Valid Asana provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -376,7 +449,12 @@ var testCases = []struct { // nolint
 				ExplicitWorkspaceRequired: false,
 			},
 			Support: Support{
-				BulkWrite: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Proxy:     false,
 				Read:      false,
 				Subscribe: false,
@@ -391,9 +469,14 @@ var testCases = []struct { // nolint
 		description: "Valid Notion provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     true,
 			},
@@ -420,9 +503,14 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -442,9 +530,14 @@ var testCases = []struct { // nolint
 		description: "Zoom provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -464,9 +557,14 @@ var testCases = []struct { // nolint
 		description: "Valid Intercom provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -488,9 +586,14 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -509,9 +612,14 @@ var testCases = []struct { // nolint
 		provider: DocuSignDeveloper,
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -531,9 +639,14 @@ var testCases = []struct { // nolint
 		description: "Calendly provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -553,9 +666,14 @@ var testCases = []struct { // nolint
 		description: "GetResponse provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -575,9 +693,14 @@ var testCases = []struct { // nolint
 		description: "Valid AWeber provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -600,9 +723,14 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -622,9 +750,14 @@ var testCases = []struct { // nolint
 		description: "Valid ConstantContact provider config with no substitutions",
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -647,9 +780,14 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -675,9 +813,14 @@ var testCases = []struct { // nolint
 		},
 		expected: &ProviderInfo{
 			Support: Support{
-				Read:      false,
-				Write:     false,
-				BulkWrite: false,
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
 				Subscribe: false,
 				Proxy:     false,
 			},
@@ -692,6 +835,181 @@ var testCases = []struct { // nolint
 		},
 		expectedErr: nil,
 	},
+	{
+		provider:    Box,
+		description: "Box config with no substitutions",
+		expected: &ProviderInfo{
+			Support: Support{
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
+				Subscribe: false,
+				Proxy:     false,
+			},
+			AuthType: Oauth2,
+			OauthOpts: OauthOpts{
+				AuthURL:                   "https://account.box.com/api/oauth2/authorize",
+				TokenURL:                  "https://api.box.com/oauth2/token",
+				ExplicitScopesRequired:    false,
+				ExplicitWorkspaceRequired: false,
+			},
+			BaseURL: "https://api.box.com",
+		},
+		expectedErr: nil,
+	},
+	{
+		provider:    GoogleCalendar,
+		description: "Google Calendar provider config with no substitutions",
+		expected: &ProviderInfo{
+			Support: Support{
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
+				Subscribe: false,
+				Proxy:     false,
+			},
+			AuthType: Oauth2,
+			OauthOpts: OauthOpts{
+				AuthURL:                   "https://accounts.google.com/o/oauth2/v2/auth",
+				TokenURL:                  "https://oauth2.googleapis.com/token",
+				ExplicitWorkspaceRequired: false,
+				ExplicitScopesRequired:    true,
+				TokenMetadataFields: TokenMetadataFields{
+					ScopesField: "scope",
+				},
+			},
+			BaseURL: "https://www.googleapis.com/calendar",
+		},
+		expectedErr: nil,
+	},
+	{
+		provider:    ZendeskSupport,
+		description: "Zendesk Support provider config with valid substitutions",
+		substitutions: map[string]string{
+			"workspace": "testing",
+		},
+		expected: &ProviderInfo{
+			Support: Support{
+				Read:  false,
+				Write: false,
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
+				Subscribe: false,
+				Proxy:     false,
+			},
+			AuthType: Oauth2,
+			OauthOpts: OauthOpts{
+				AuthURL:                   "https://testing.zendesk.com/oauth/authorizations/new",
+				TokenURL:                  "https://testing.zendesk.com/oauth/tokens",
+				ExplicitScopesRequired:    true,
+				ExplicitWorkspaceRequired: true,
+			},
+			BaseURL: "https://testing.zendesk.com",
+		},
+		expectedErr: nil,
+	},
+	{
+		provider:    ZendeskChat,
+		description: "Valid ZendeskChat provider config with substitutions",
+		substitutions: map[string]string{
+			"workspace": "test",
+		},
+		expected: &ProviderInfo{
+			AuthType: Oauth2,
+			OauthOpts: OauthOpts{
+				AuthURL:                   "https://www.zopim.com/oauth2/authorizations/new?subdomain=test",
+				TokenURL:                  "https://www.zopim.com/oauth2/token",
+				ExplicitScopesRequired:    true,
+				ExplicitWorkspaceRequired: true,
+			},
+			Support: Support{
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
+				Proxy:     false,
+				Read:      false,
+				Subscribe: false,
+				Write:     false,
+			},
+			BaseURL: "https://www.zopim.com",
+		},
+		expectedErr: nil,
+	},
+	{
+		provider:    WordPress,
+		description: "Valid WordPress provider config with no substitutions",
+		expected: &ProviderInfo{
+			AuthType: Oauth2,
+			OauthOpts: OauthOpts{
+				AuthURL:                   "https://public-api.wordpress.com/oauth2/authorize",
+				TokenURL:                  "https://public-api.wordpress.com/oauth2/token",
+				ExplicitScopesRequired:    false,
+				ExplicitWorkspaceRequired: false,
+			},
+			Support: Support{
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
+				Proxy:     false,
+				Read:      false,
+				Subscribe: false,
+				Write:     false,
+			},
+			BaseURL: "https://public-api.wordpress.com",
+		},
+		expectedErr: nil,
+	},
+	{
+		provider:    Airtable,
+		description: "Valid Airtable provider config with no substitutions",
+		expected: &ProviderInfo{
+			AuthType: Oauth2,
+			OauthOpts: OauthOpts{
+				GrantType:                 PKCE,
+				AuthURL:                   "https://airtable.com/oauth2/v1/authorize",
+				TokenURL:                  "https://airtable.com/oauth2/v1/token",
+				ExplicitScopesRequired:    true,
+				ExplicitWorkspaceRequired: false,
+				TokenMetadataFields: TokenMetadataFields{
+					ScopesField: "scope",
+				},
+			},
+			Support: Support{
+				BulkWrite: BulkWriteSupport{
+					Insert: false,
+					Update: false,
+					Upsert: false,
+					Delete: false,
+				},
+				Proxy:     false,
+				Read:      false,
+				Subscribe: false,
+				Write:     false,
+			},
+			BaseURL: "https://api.airtable.com",
+		},
+		expectedErr: nil,
+	},
 }
 
 func TestReadInfo(t *testing.T) { // nolint
diff --git a/test/salesforce/bulkdelete/main.go b/test/salesforce/bulkdelete/main.go
index ea3b219c..e7a7d4bf 100644
--- a/test/salesforce/bulkdelete/main.go
+++ b/test/salesforce/bulkdelete/main.go
@@ -51,7 +51,6 @@ func main() {
 		ObjectName: "Touchpoint__c",
 		CSVData:    bytes.NewReader(objectCSVToDelete),
 	})
-
 	if err != nil {
 		slog.Error("Error bulk deleting", "error", err)
 		return
diff --git a/test/salesforce/metadata/main.go b/test/salesforce/metadata/main.go
index 941123b5..51deeed2 100644
--- a/test/salesforce/metadata/main.go
+++ b/test/salesforce/metadata/main.go
@@ -55,7 +55,6 @@ func main() {
 	}()
 
 	example, err := xmldom.ParseXML(`<createMetadata><metadata xsi:type="CustomObject"><fullName>TestObject15__c</fullName><label>Test Object 15</label><pluralLabel>Test Objects 15</pluralLabel><nameField><type>Text</type><label>Test Object Name</label></nameField><deploymentStatus>Deployed</deploymentStatus><sharingModel>ReadWrite</sharingModel></metadata><metadata xsi:type="CustomField"><fullName>TestObject13__c.Comments__c</fullName><label>Comments</label><type>LongTextArea</type><length>500</length><inlineHelpText>This field contains help text for this object</inlineHelpText><description>Add your comments about this object here</description><visibleLines>30</visibleLines><required>false</required><trackFeedHistory>false</trackFeedHistory><trackHistory>false</trackHistory></metadata></createMetadata>`)
-
 	if err != nil {
 		slog.Error("err parsing", "error", err)
 		os.Exit(1)