Repository: amp-labs/connectors
Pull request #486 (2024-06-06 13:08:47)

[ENG-1232] Create a JSON catalog when the catalog changes
Whenever a catalog change goes in, this will generate a JSON file that we can then refer to for our usage, without having to update dependencies on this repo.

RajatPawar: * **#486** <a href="https://app.graphite.dev/github/pr/amp-labs/connectors/486?utm_source=stack-comment-icon" target="_blank"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="10px" height="10px"/></a> 👈
* `main`

This stack of pull requests is managed by Graphite. <a href="https://stacking.dev/?utm_source=stack-comment">Learn more about stacking.</a>
<h2></h2>

 Join @RajatPawar and the rest of your teammates on <a href="https://graphite.dev?utm-source=stack-comment"><img src="https://static.graphite.dev/graphite-32x32-black.png" alt="Graphite" width="11px" height="11px"/> <b>Graphite</b></a>
  <!-- Current dependencies on/for this PR: -->

Patch:
diff --git a/.github/workflows/generate-json-catalog.yaml b/.github/workflows/generate-json-catalog.yaml
new file mode 100644
index 00000000..6fd29680
--- /dev/null
+++ b/.github/workflows/generate-json-catalog.yaml
@@ -0,0 +1,37 @@
+name: Update catalog.json
+
+on:
+  pull_request:
+    types: [closed]
+    branches:
+      - 'main'
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Check for changes in providers/catalog.go
+        uses: dorny/paths-filter@v3
+        id: filter
+        with:
+          filters: |
+            catalog:
+              - 'providers/catalog.go'
+
+      - name: Run script if catalog has changed
+        if: steps.filter.outputs.catalog == 'true'
+        run: go run scripts/catalog/json.go
+        shell: bash
+
+      - name: Push changes
+        run: |
+          git config --global user.email "no-reply@github.com"
+          git config --global user.name "GitHub Actions"
+          git add providers/catalog.json
+          git commit -m "Update catalog.json"
+          git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
+          git push
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml
index 16113037..beb00199 100644
--- a/.github/workflows/linter.yml
+++ b/.github/workflows/linter.yml
@@ -12,6 +12,6 @@ jobs:
           cache: false
       - name: golangci-lint
         uses: golangci/golangci-lint-action@v3
-        continue-on-error: true
+        continue-on-error: false
         with:
-          version: latest
+          version: v1.54
diff --git a/intercom/metadata/index.json b/intercom/metadata/index.json
index fd2a2f3d..b0e758c6 100755
--- a/intercom/metadata/index.json
+++ b/intercom/metadata/index.json
@@ -1,140 +1,5 @@
 {
   "data": [
-    {
-      "name": "admin",
-      "displayName": "Admin",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Admins/admin"
-    },
-    {
-      "name": "article",
-      "displayName": "Article",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article"
-    },
-    {
-      "name": "article_list_item",
-      "displayName": "Articles",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article_list_item"
-    },
-    {
-      "name": "article_search_highlights",
-      "displayName": "Article Search Highlights",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article_search_highlights"
-    },
-    {
-      "name": "article_search_response",
-      "displayName": "Article Search Response",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article_search_response"
-    },
-    {
-      "name": "company",
-      "displayName": "Company",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Companies/company"
-    },
-    {
-      "name": "contact",
-      "displayName": "Contact",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Contacts/contact"
-    },
-    {
-      "name": "conversation",
-      "displayName": "Conversation",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Conversations/conversation"
-    },
-    {
-      "name": "data_attribute",
-      "displayName": "Data Attribute",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data-Attributes/data_attribute"
-    },
-    {
-      "name": "data_event",
-      "displayName": "Data Event",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data-Events/data_event"
-    },
-    {
-      "name": "data_export",
-      "displayName": "Data Export",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data-Export/data_export"
-    },
-    {
-      "name": "collection",
-      "displayName": "Collection",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Help-Center/collection"
-    },
-    {
-      "name": "help_center",
-      "displayName": "Help Center",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Help-Center/help_center"
-    },
-    {
-      "name": "help_center_list",
-      "displayName": "Help Centers",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Help-Center/help_center_list"
-    },
-    {
-      "name": "message",
-      "displayName": "Message",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Messages/message"
-    },
-    {
-      "name": "news_item",
-      "displayName": "News Item",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/News/news_item"
-    },
-    {
-      "name": "newsfeed",
-      "displayName": "Newsfeed",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/News/newsfeed"
-    },
-    {
-      "name": "newsfeed_assignment",
-      "displayName": "Newsfeed Assignment",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/News/newsfeed_assignment"
-    },
-    {
-      "name": "note",
-      "displayName": "Note",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Notes/note"
-    },
-    {
-      "name": "segment",
-      "displayName": "Segment",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Segments/segment"
-    },
-    {
-      "name": "subscription_type",
-      "displayName": "Subscription Types",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Subscription-Types/subscription_type"
-    },
-    {
-      "name": "tag",
-      "displayName": "Tag",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tags/tag"
-    },
-    {
-      "name": "team",
-      "displayName": "Team",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Teams/team"
-    },
-    {
-      "name": "ticket",
-      "displayName": "Ticket",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket"
-    },
-    {
-      "name": "ticket_contacts",
-      "displayName": "Contacts",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket_contacts"
-    },
-    {
-      "name": "ticket_part",
-      "displayName": "Ticket Part",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket_part"
-    },
-    {
-      "name": "ticket_type",
-      "displayName": "Ticket Type",
-      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket_type"
-    },
     {
       "name": "activity_log",
       "displayName": "Activity Log",
@@ -155,6 +20,11 @@
       "displayName": "Addressable List",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/addressable_list"
     },
+    {
+      "name": "admin",
+      "displayName": "Admin",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Admins/admin"
+    },
     {
       "name": "admin_list",
       "displayName": "Admins",
@@ -185,6 +55,11 @@
       "displayName": "App",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/app"
     },
+    {
+      "name": "article",
+      "displayName": "Article",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article"
+    },
     {
       "name": "article_content",
       "displayName": "Article Content",
@@ -195,6 +70,21 @@
       "displayName": "Articles",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/article_list"
     },
+    {
+      "name": "article_list_item",
+      "displayName": "Articles",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article_list_item"
+    },
+    {
+      "name": "article_search_highlights",
+      "displayName": "Article Search Highlights",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article_search_highlights"
+    },
+    {
+      "name": "article_search_response",
+      "displayName": "Article Search Response",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Articles/article_search_response"
+    },
     {
       "name": "article_statistics",
       "displayName": "Article Statistics",
@@ -220,11 +110,21 @@
       "displayName": "Close Conversation Request",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/close_conversation_request"
     },
+    {
+      "name": "collection",
+      "displayName": "Collection",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Help-Center/collection"
+    },
     {
       "name": "collection_list",
       "displayName": "Collections",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/collection_list"
     },
+    {
+      "name": "company",
+      "displayName": "Company",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Companies/company"
+    },
     {
       "name": "company_attached_contacts",
       "displayName": "Company Attached Contacts",
@@ -245,6 +145,11 @@
       "displayName": "Company Scroll",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/company_scroll"
     },
+    {
+      "name": "contact",
+      "displayName": "Contact",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Contacts/contact"
+    },
     {
       "name": "contact_archived",
       "displayName": "Contact Archived",
@@ -360,6 +265,11 @@
       "displayName": "Content Source List",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/content_sources_list"
     },
+    {
+      "name": "conversation",
+      "displayName": "Conversation",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Conversations/conversation"
+    },
     {
       "name": "conversation_attachment_files",
       "displayName": "Conversation attachment files",
@@ -520,11 +430,21 @@
       "displayName": "customer_request",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/customer_request"
     },
+    {
+      "name": "data_attribute",
+      "displayName": "Data Attribute",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data-Attributes/data_attribute"
+    },
     {
       "name": "data_attribute_list",
       "displayName": "Data Attribute List",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/data_attribute_list"
     },
+    {
+      "name": "data_event",
+      "displayName": "Data Event",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data-Events/data_event"
+    },
     {
       "name": "data_event_list",
       "displayName": "Data Event List",
@@ -540,6 +460,11 @@
       "displayName": "Data Event Summary Item",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/data_event_summary_item"
     },
+    {
+      "name": "data_export",
+      "displayName": "Data Export",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Data-Export/data_export"
+    },
     {
       "name": "data_export_csv",
       "displayName": "Data Export CSV",
@@ -590,6 +515,16 @@
       "displayName": "Group Translated Content",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/group_translated_content"
     },
+    {
+      "name": "help_center",
+      "displayName": "Help Center",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Help-Center/help_center"
+    },
+    {
+      "name": "help_center_list",
+      "displayName": "Help Centers",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Help-Center/help_center_list"
+    },
     {
       "name": "intercom_version",
       "displayName": "intercom_version",
@@ -610,16 +545,41 @@
       "displayName": "Merge contact data",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/merge_contacts_request"
     },
+    {
+      "name": "message",
+      "displayName": "Message",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Messages/message"
+    },
     {
       "name": "multiple_filter_search_request",
       "displayName": "Multiple Filter Search Request",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/multiple_filter_search_request"
     },
+    {
+      "name": "news_item",
+      "displayName": "News Item",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/News/news_item"
+    },
     {
       "name": "news_item_request",
       "displayName": "Create News Item Request",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/news_item_request"
     },
+    {
+      "name": "newsfeed",
+      "displayName": "Newsfeed",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/News/newsfeed"
+    },
+    {
+      "name": "newsfeed_assignment",
+      "displayName": "Newsfeed Assignment",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/News/newsfeed_assignment"
+    },
+    {
+      "name": "note",
+      "displayName": "Note",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Notes/note"
+    },
     {
       "name": "note_list",
       "displayName": "Paginated Response",
@@ -670,6 +630,11 @@
       "displayName": "Search data",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/search_request"
     },
+    {
+      "name": "segment",
+      "displayName": "Segment",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Segments/segment"
+    },
     {
       "name": "segment_list",
       "displayName": "Segment List",
@@ -700,11 +665,21 @@
       "displayName": "Pagination: Starting After",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/starting_after_paging"
     },
+    {
+      "name": "subscription_type",
+      "displayName": "Subscription Types",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Subscription-Types/subscription_type"
+    },
     {
       "name": "subscription_type_list",
       "displayName": "Subscription Types",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/subscription_type_list"
     },
+    {
+      "name": "tag",
+      "displayName": "Tag",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tags/tag"
+    },
     {
       "name": "tag_company_request",
       "displayName": "Tag Company Request Payload",
@@ -725,6 +700,11 @@
       "displayName": "Tags",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/tags"
     },
+    {
+      "name": "team",
+      "displayName": "Team",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Teams/team"
+    },
     {
       "name": "team_list",
       "displayName": "Team List",
@@ -735,6 +715,16 @@
       "displayName": "Team Priority Level",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/team_priority_level"
     },
+    {
+      "name": "ticket",
+      "displayName": "Ticket",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket"
+    },
+    {
+      "name": "ticket_contacts",
+      "displayName": "Contacts",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket_contacts"
+    },
     {
       "name": "ticket_custom_attributes",
       "displayName": "Ticket Attributes",
@@ -745,6 +735,11 @@
       "displayName": "Ticket List",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/ticket_list"
     },
+    {
+      "name": "ticket_part",
+      "displayName": "Ticket Part",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket_part"
+    },
     {
       "name": "ticket_part_author",
       "displayName": "Ticket part author",
@@ -765,6 +760,11 @@
       "displayName": "Ticket Attributes",
       "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Models/ticket_request_custom_attributes"
     },
+    {
+      "name": "ticket_type",
+      "displayName": "Ticket Type",
+      "url": "https://developers.intercom.com/docs/references/rest-api/api.intercom.io/Tickets/ticket_type"
+    },
     {
       "name": "ticket_type_attribute",
       "displayName": "Ticket Type Attribute",
diff --git a/providers/catalog.go b/providers/catalog.go
index 19309795..74ccc58e 100644
--- a/providers/catalog.go
+++ b/providers/catalog.go
@@ -47,6 +47,7 @@ const (
 	Ironclad                Provider = "ironclad"
 	IroncladDemo            Provider = "ironcladDemo"
 	IroncladEU              Provider = "ironcladEU"
+	Iterable                Provider = "iterable"
 	Keap                    Provider = "keap"
 	Klaviyo                 Provider = "klaviyo"
 	LinkedIn                Provider = "linkedIn"
@@ -70,6 +71,7 @@ const (
 	Smartsheet              Provider = "smartsheet"
 	SnapchatAds             Provider = "snapchatAds"
 	StackExchange           Provider = "stackExchange"
+	SurveyMonkey            Provider = "surveyMonkey"
 	TeamleaderCRM           Provider = "teamleaderCRM"
 	Timely                  Provider = "timely"
 	Typeform                Provider = "typeform"
@@ -314,7 +316,7 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 		},
 	},
 
-	// Wrikle configuration
+	// Wrike configuration
 	Wrike: {
 		AuthType: Oauth2,
 		BaseURL:  "https://www.wrike.com/api",
@@ -2096,4 +2098,51 @@ var catalog = CatalogType{ // nolint:gochecknoglobals
 			Write:     false,
 		},
 	},
+
+	// SurveyMonkey configuration file
+	SurveyMonkey: {
+		AuthType: Oauth2,
+		BaseURL:  "https://api.surveymonkey.com",
+		OauthOpts: &OauthOpts{
+			AuthURL:                   "https://api.surveymonkey.com/oauth/authorize",
+			TokenURL:                  "https://api.surveymonkey.com/oauth/token",
+			ExplicitScopesRequired:    false,
+			ExplicitWorkspaceRequired: false,
+			GrantType:                 AuthorizationCode,
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
+
+	// Iterable API Key authentication
+	Iterable: {
+		AuthType: ApiKey,
+		BaseURL:  "https://api.iterable.com",
+		ApiKeyOpts: &ApiKeyOpts{
+			HeaderName: "Api-Key",
+			DocsURL:    "https://app.iterable.com/settings/apiKeys",
+		},
+		Support: Support{
+			BulkWrite: BulkWriteSupport{
+				Insert: false,
+				Update: false,
+				Upsert: false,
+				Delete: false,
+			},
+			Proxy:     false,
+			Read:      false,
+			Subscribe: false,
+			Write:     false,
+		},
+	},
 }
diff --git a/providers/types.gen.go b/providers/types.gen.go
index 3306c205..bb44e512 100644
--- a/providers/types.gen.go
+++ b/providers/types.gen.go
@@ -42,12 +42,13 @@ type CatalogType map[string]ProviderInfo
 
 // OauthOpts defines model for OauthOpts.
 type OauthOpts struct {
-	AuthURL                   string              `json:"authURL" validate:"required"`
-	TokenURL                  string              `json:"tokenURL" validate:"required"`
+	Audience                  string              `json:"audience,omitempty"`
+	AuthURL                   string              `json:"authURL,omitempty"`
 	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.
@@ -65,7 +66,7 @@ type ProviderInfo struct {
 	// DisplayName The display name of the provider, if omitted, defaults to provider name.
 	DisplayName string     `json:"displayName,omitempty"`
 	Name        string     `json:"name"`
-	OauthOpts   *OauthOpts `json:"oauthOpts,omitempty" validate:"required"`
+	OauthOpts   *OauthOpts `json:"oauthOpts,omitempty"`
 
 	// PostAuthInfoNeeded If true, we require additional information after auth to start making requests.
 	PostAuthInfoNeeded bool         `json:"postAuthInfoNeeded,omitempty"`
diff --git a/providers/types.yaml b/providers/types.yaml
index e386e3da..1fc9e8e1 100644
--- a/providers/types.yaml
+++ b/providers/types.yaml
@@ -77,11 +77,8 @@ components:
 
     OauthOpts:
       type: object
-      x-oapi-codegen-extra-tags:
-        validate: required
       required:
           - grantType
-          - authURL
           - tokenURL
           - explicitScopesRequired
           - explicitWorkspaceRequired
@@ -93,8 +90,7 @@ components:
         authURL:
           type: string
           example: https://login.salesforce.com/services/oauth2/authorize
-          x-oapi-codegen-extra-tags:
-            validate: required
+          x-go-type-skip-optional-pointer: true
         tokenURL:
           type: string
           example: https://login.salesforce.com/services/oauth2/token
@@ -106,6 +102,10 @@ components:
         explicitWorkspaceRequired:
           type: boolean
           example: true
+        audience:
+          type: string
+          example: https://api.mparticle.com
+          x-go-type-skip-optional-pointer: true
         tokenMetadataFields:
           $ref: '#/components/schemas/TokenMetadataFields'
 
diff --git a/salesloft/metadata/index.json b/salesloft/metadata/index.json
index 6f40c265..d2cc133f 100755
--- a/salesloft/metadata/index.json
+++ b/salesloft/metadata/index.json
@@ -1,20 +1,5 @@
 {
   "data": [
-    {
-      "name": "me-index",
-      "displayName": "Fetch current user",
-      "url": "https://developers.salesloft.com/docs/api/me-index"
-    },
-    {
-      "name": "team-index",
-      "displayName": "Fetch current team",
-      "url": "https://developers.salesloft.com/docs/api/team-index"
-    },
-    {
-      "name": "data-control-account-redaction-create",
-      "displayName": "Execute an account redaction workflow",
-      "url": "https://developers.salesloft.com/docs/api/data-control-account-redaction-create"
-    },
     {
       "name": "account-stages-index",
       "displayName": "List account stages",
@@ -41,20 +26,20 @@
       "url": "https://developers.salesloft.com/docs/api/account-upserts-create"
     },
     {
-      "name": "data-control-account-and-people-redaction-create",
-      "displayName": "Submit an account and people redaction  request",
-      "url": "https://developers.salesloft.com/docs/api/data-control-account-and-people-redaction-create"
+      "name": "accounts-create",
+      "displayName": "Create an account",
+      "url": "https://developers.salesloft.com/docs/api/accounts-create"
+    },
+    {
+      "name": "accounts-destroy",
+      "displayName": "Delete an account",
+      "url": "https://developers.salesloft.com/docs/api/accounts-destroy"
     },
     {
       "name": "accounts-index",
       "displayName": "List accounts",
       "url": "https://developers.salesloft.com/docs/api/accounts-index"
     },
-    {
-      "name": "accounts-create",
-      "displayName": "Create an account",
-      "url": "https://developers.salesloft.com/docs/api/accounts-create"
-    },
     {
       "name": "accounts-show",
       "displayName": "Fetch an account",
@@ -66,9 +51,14 @@
       "url": "https://developers.salesloft.com/docs/api/accounts-update"
     },
     {
-      "name": "accounts-destroy",
-      "displayName": "Delete an account",
-      "url": "https://developers.salesloft.com/docs/api/accounts-destroy"
+      "name": "action-details-call-instructions-index",
+      "displayName": "List call instructions",
+      "url": "https://developers.salesloft.com/docs/api/action-details-call-instructions-index"
+    },
+    {
+      "name": "action-details-call-instructions-show",
+      "displayName": "Fetch a call instructions",
+      "url": "https://developers.salesloft.com/docs/api/action-details-call-instructions-show"
     },
     {
       "name": "actions-index",
@@ -80,25 +70,40 @@
       "displayName": "Fetch an action",
       "url": "https://developers.salesloft.com/docs/api/actions-show"
     },
+    {
+      "name": "activities-calls-create",
+      "displayName": "Create a call",
+      "url": "https://developers.salesloft.com/docs/api/activities-calls-create"
+    },
+    {
+      "name": "activities-calls-index",
+      "displayName": "List calls",
+      "url": "https://developers.salesloft.com/docs/api/activities-calls-index"
+    },
+    {
+      "name": "activities-calls-show",
+      "displayName": "Fetch a call",
+      "url": "https://developers.salesloft.com/docs/api/activities-calls-show"
+    },
     {
       "name": "activities-create",
       "displayName": "Create an activity",
       "url": "https://developers.salesloft.com/docs/api/activities-create"
     },
     {
-      "name": "activity-histories-index",
-      "displayName": "List Past Activities",
-      "url": "https://developers.salesloft.com/docs/api/activity-histories-index"
+      "name": "activities-emails-index",
+      "displayName": "List emails",
+      "url": "https://developers.salesloft.com/docs/api/activities-emails-index"
     },
     {
-      "name": "bulk-jobs-update",
-      "displayName": "Update a bulk job",
-      "url": "https://developers.salesloft.com/docs/api/bulk-jobs-update"
+      "name": "activities-emails-show",
+      "displayName": "Fetch an email",
+      "url": "https://developers.salesloft.com/docs/api/activities-emails-show"
     },
     {
-      "name": "bulk-jobs-show",
-      "displayName": "Fetch a bulk job",
-      "url": "https://developers.salesloft.com/docs/api/bulk-jobs-show"
+      "name": "activity-histories-index",
+      "displayName": "List Past Activities",
+      "url": "https://developers.salesloft.com/docs/api/activity-histories-index"
     },
     {
       "name": "bulk-jobs-create",
@@ -125,6 +130,16 @@
       "displayName": "List job data for a completed bulk job.",
       "url": "https://developers.salesloft.com/docs/api/bulk-jobs-results-index"
     },
+    {
+      "name": "bulk-jobs-show",
+      "displayName": "Fetch a bulk job",
+      "url": "https://developers.salesloft.com/docs/api/bulk-jobs-show"
+    },
+    {
+      "name": "bulk-jobs-update",
+      "displayName": "Update a bulk job",
+      "url": "https://developers.salesloft.com/docs/api/bulk-jobs-update"
+    },
     {
       "name": "bulk-reschedule-tasks-create",
       "displayName": "Reschedule many tasks at once",
@@ -140,26 +155,26 @@
       "displayName": "Import cadences from JSON",
       "url": "https://developers.salesloft.com/docs/api/cadence-imports-create"
     },
-    {
-      "name": "cadence-memberships-index",
-      "displayName": "List cadence memberships",
-      "url": "https://developers.salesloft.com/docs/api/cadence-memberships-index"
-    },
     {
       "name": "cadence-memberships-create",
       "displayName": "Create a cadence membership",
       "url": "https://developers.salesloft.com/docs/api/cadence-memberships-create"
     },
-    {
-      "name": "cadence-memberships-show",
-      "displayName": "Fetch a cadence membership",
-      "url": "https://developers.salesloft.com/docs/api/cadence-memberships-show"
-    },
     {
       "name": "cadence-memberships-destroy",
       "displayName": "Delete a cadence membership",
       "url": "https://developers.salesloft.com/docs/api/cadence-memberships-destroy"
     },
+    {
+      "name": "cadence-memberships-index",
+      "displayName": "List cadence memberships",
+      "url": "https://developers.salesloft.com/docs/api/cadence-memberships-index"
+    },
+    {
+      "name": "cadence-memberships-show",
+      "displayName": "Fetch a cadence membership",
+      "url": "https://developers.salesloft.com/docs/api/cadence-memberships-show"
+    },
     {
       "name": "cadences-index",
       "displayName": "List cadences",
@@ -170,16 +185,16 @@
       "displayName": "Fetch a cadence",
       "url": "https://developers.salesloft.com/docs/api/cadences-show"
     },
-    {
-      "name": "calendar-events-upsert-create",
-      "displayName": "Upsert a calendar event",
-      "url": "https://developers.salesloft.com/docs/api/calendar-events-upsert-create"
-    },
     {
       "name": "calendar-events-index",
       "displayName": "List calendar events",
       "url": "https://developers.salesloft.com/docs/api/calendar-events-index"
     },
+    {
+      "name": "calendar-events-upsert-create",
+      "displayName": "Upsert a calendar event",
+      "url": "https://developers.salesloft.com/docs/api/calendar-events-upsert-create"
+    },
     {
       "name": "call-data-records-index",
       "displayName": "List call data records",
@@ -195,51 +210,16 @@
       "displayName": "List call dispositions",
       "url": "https://developers.salesloft.com/docs/api/call-dispositions-index"
     },
-    {
-      "name": "action-details-call-instructions-index",
-      "displayName": "List call instructions",
-      "url": "https://developers.salesloft.com/docs/api/action-details-call-instructions-index"
-    },
-    {
-      "name": "action-details-call-instructions-show",
-      "displayName": "Fetch a call instructions",
-      "url": "https://developers.salesloft.com/docs/api/action-details-call-instructions-show"
-    },
     {
       "name": "call-sentiments-index",
       "displayName": "List call sentiments",
       "url": "https://developers.salesloft.com/docs/api/call-sentiments-index"
     },
-    {
-      "name": "phone-numbers-caller-ids-index",
-      "displayName": "List caller ids",
-      "url": "https://developers.salesloft.com/docs/api/phone-numbers-caller-ids-index"
-    },
-    {
-      "name": "activities-calls-index",
-      "displayName": "List calls",
-      "url": "https://developers.salesloft.com/docs/api/activities-calls-index"
-    },
-    {
-      "name": "activities-calls-create",
-      "displayName": "Create a call",
-      "url": "https://developers.salesloft.com/docs/api/activities-calls-create"
-    },
-    {
-      "name": "activities-calls-show",
-      "displayName": "Fetch a call",
-      "url": "https://developers.salesloft.com/docs/api/activities-calls-show"
-    },
     {
       "name": "create-conversations-call",
       "displayName": "Create Conversations Call",
       "url": "https://developers.salesloft.com/docs/api/create-conversations-call"
     },
-    {
-      "name": "tasks-counts-index",
-      "displayName": "Fetch task counts",
-      "url": "https://developers.salesloft.com/docs/api/tasks-counts-index"
-    },
     {
       "name": "crm-activities-index",
       "displayName": "List crm activities",
@@ -260,26 +240,26 @@
       "displayName": "List crm users",
       "url": "https://developers.salesloft.com/docs/api/crm-users-index"
     },
-    {
-      "name": "custom-fields-index",
-      "displayName": "List custom fields",
-      "url": "https://developers.salesloft.com/docs/api/custom-fields-index"
-    },
     {
       "name": "custom-fields-create",
       "displayName": "Create a custom field",
       "url": "https://developers.salesloft.com/docs/api/custom-fields-create"
     },
-    {
-      "name": "custom-fields-show",
-      "displayName": "Fetch a custom field",
-      "url": "https://developers.salesloft.com/docs/api/custom-fields-show"
-    },
     {
       "name": "custom-fields-destroy",
       "displayName": "Delete a custom field",
       "url": "https://developers.salesloft.com/docs/api/custom-fields-destroy"
     },
+    {
+      "name": "custom-fields-index",
+      "displayName": "List custom fields",
+      "url": "https://developers.salesloft.com/docs/api/custom-fields-index"
+    },
+    {
+      "name": "custom-fields-show",
+      "displayName": "Fetch a custom field",
+      "url": "https://developers.salesloft.com/docs/api/custom-fields-show"
+    },
     {
       "name": "custom-roles-index",
       "displayName": "List custom roles",
@@ -290,6 +270,36 @@
       "displayName": "Fetch a custom role",
       "url": "https://developers.salesloft.com/docs/api/custom-roles-show"
     },
+    {
+      "name": "data-control-account-and-people-redaction-create",
+      "displayName": "Submit an account and people redaction  request",
+      "url": "https://developers.salesloft.com/docs/api/data-control-account-and-people-redaction-create"
+    },
+    {
+      "name": "data-control-account-redaction-create",
+      "displayName": "Execute an account redaction workflow",
+      "url": "https://developers.salesloft.com/docs/api/data-control-account-redaction-create"
+    },
+    {
+      "name": "data-control-people-soft-deletion-create",
+      "displayName": "Submit a people soft deletion request",
+      "url": "https://developers.salesloft.com/docs/api/data-control-people-soft-deletion-create"
+    },
+    {
+      "name": "data-control-requests-index",
+      "displayName": "Retrieve a list of Requests",
+      "url": "https://developers.salesloft.com/docs/api/data-control-requests-index"
+    },
+    {
+      "name": "data-control-requests-show",
+      "displayName": "Fetch a Request record",
+      "url": "https://developers.salesloft.com/docs/api/data-control-requests-show"
+    },
+    {
+      "name": "data-control-right-to-be-forgotten-create",
+      "displayName": "Submit a right to be forgotten request",
+      "url": "https://developers.salesloft.com/docs/api/data-control-right-to-be-forgotten-create"
+    },
     {
       "name": "email-missing-tags-create",
       "displayName": "Requests a check of the template for missed tags",
@@ -310,16 +320,6 @@
       "displayName": "Fetch an email template",
       "url": "https://developers.salesloft.com/docs/api/email-templates-show"
     },
-    {
-      "name": "activities-emails-index",
-      "displayName": "List emails",
-      "url": "https://developers.salesloft.com/docs/api/activities-emails-index"
-    },
-    {
-      "name": "activities-emails-show",
-      "displayName": "Fetch an email",
-      "url": "https://developers.salesloft.com/docs/api/activities-emails-show"
-    },
     {
       "name": "external-emails-create",
       "displayName": "Create an External Email",
@@ -330,6 +330,11 @@
       "displayName": "Create a group",
       "url": "https://developers.salesloft.com/docs/api/groups-create"
     },
+    {
+      "name": "groups-destroy",
+      "displayName": "Deletes a Group by ID",
+      "url": "https://developers.salesloft.com/docs/api/groups-destroy"
+    },
     {
       "name": "groups-index",
       "displayName": "List groups",
@@ -346,20 +351,20 @@
       "url": "https://developers.salesloft.com/docs/api/groups-update"
     },
     {
-      "name": "groups-destroy",
-      "displayName": "Deletes a Group by ID",
-      "url": "https://developers.salesloft.com/docs/api/groups-destroy"
+      "name": "imports-create",
+      "displayName": "Create an import",
+      "url": "https://developers.salesloft.com/docs/api/imports-create"
+    },
+    {
+      "name": "imports-destroy",
+      "displayName": "Delete an import",
+      "url": "https://developers.salesloft.com/docs/api/imports-destroy"
     },
     {
       "name": "imports-index",
       "displayName": "List imports",
       "url": "https://developers.salesloft.com/docs/api/imports-index"
     },
-    {
-      "name": "imports-create",
-      "displayName": "Create an import",
-      "url": "https://developers.salesloft.com/docs/api/imports-create"
-    },
     {
       "name": "imports-show",
       "displayName": "Fetch an import",
@@ -371,25 +376,85 @@
       "url": "https://developers.salesloft.com/docs/api/imports-update"
     },
     {
-      "name": "imports-destroy",
-      "displayName": "Delete an import",
-      "url": "https://developers.salesloft.com/docs/api/imports-destroy"
+      "name": "integrations-signals-registrations-create",
+      "displayName": "Create a Signal Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-create"
     },
     {
-      "name": "third-party-live-feed-items-create",
-      "displayName": "Create a live feed item",
-      "url": "https://developers.salesloft.com/docs/api/third-party-live-feed-items-create"
+      "name": "integrations-signals-registrations-destroy",
+      "displayName": "Deletes a Signal Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-destroy"
+    },
+    {
+      "name": "integrations-signals-registrations-index",
+      "displayName": "List Signal Registrations",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-index"
+    },
+    {
+      "name": "integrations-signals-registrations-plays-create",
+      "displayName": "Create a Play Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-create"
+    },
+    {
+      "name": "integrations-signals-registrations-plays-destroy",
+      "displayName": "Delete a Play Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-destroy"
+    },
+    {
+      "name": "integrations-signals-registrations-plays-index",
+      "displayName": "List Play Registrations",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-index"
+    },
+    {
+      "name": "integrations-signals-registrations-plays-show",
+      "displayName": "Show a Play Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-show"
+    },
+    {
+      "name": "integrations-signals-registrations-plays-update",
+      "displayName": "Update a Play Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-update"
+    },
+    {
+      "name": "integrations-signals-registrations-show",
+      "displayName": "Fetch a Signal Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-show"
+    },
+    {
+      "name": "integrations-signals-registrations-update",
+      "displayName": "Update a Signal Registration",
+      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-update"
     },
     {
       "name": "live-website-tracking-parameters-create",
       "displayName": "Create an Live Website Tracking Parameter",
       "url": "https://developers.salesloft.com/docs/api/live-website-tracking-parameters-create"
     },
+    {
+      "name": "me-index",
+      "displayName": "Fetch current user",
+      "url": "https://developers.salesloft.com/docs/api/me-index"
+    },
     {
       "name": "meetings-index",
       "displayName": "List meetings",
       "url": "https://developers.salesloft.com/docs/api/meetings-index"
     },
+    {
+      "name": "meetings-reschedule-links-show",
+      "displayName": "Fetch a reschedule meeting link",
+      "url": "https://developers.salesloft.com/docs/api/meetings-reschedule-links-show"
+    },
+    {
+      "name": "meetings-settings-searches-create",
+      "displayName": "List meeting settings",
+      "url": "https://developers.salesloft.com/docs/api/meetings-settings-searches-create"
+    },
+    {
+      "name": "meetings-settings-update",
+      "displayName": "Update a meeting setting",
+      "url": "https://developers.salesloft.com/docs/api/meetings-settings-update"
+    },
     {
       "name": "meetings-update",
       "displayName": "Update a meeting",
@@ -400,16 +465,21 @@
       "displayName": "Fetch the MIME content for email",
       "url": "https://developers.salesloft.com/docs/api/mime-email-payloads-show"
     },
-    {
-      "name": "notes-index",
-      "displayName": "List notes",
-      "url": "https://developers.salesloft.com/docs/api/notes-index"
-    },
     {
       "name": "notes-create",
       "displayName": "Create a note",
       "url": "https://developers.salesloft.com/docs/api/notes-create"
     },
+    {
+      "name": "notes-destroy",
+      "displayName": "Delete a note",
+      "url": "https://developers.salesloft.com/docs/api/notes-destroy"
+    },
+    {
+      "name": "notes-index",
+      "displayName": "List notes",
+      "url": "https://developers.salesloft.com/docs/api/notes-index"
+    },
     {
       "name": "notes-show",
       "displayName": "Fetch a note",
@@ -420,11 +490,6 @@
       "displayName": "Update a note",
       "url": "https://developers.salesloft.com/docs/api/notes-update"
     },
-    {
-      "name": "notes-destroy",
-      "displayName": "Delete a note",
-      "url": "https://developers.salesloft.com/docs/api/notes-destroy"
-    },
     {
       "name": "ongoing-actions-create",
       "displayName": "Create an ongoing action",
@@ -440,16 +505,21 @@
       "displayName": "Update a pending email",
       "url": "https://developers.salesloft.com/docs/api/pending-emails-update"
     },
-    {
-      "name": "people-index",
-      "displayName": "List people",
-      "url": "https://developers.salesloft.com/docs/api/people-index"
-    },
     {
       "name": "people-create",
       "displayName": "Create a person",
       "url": "https://developers.salesloft.com/docs/api/people-create"
     },
+    {
+      "name": "people-destroy",
+      "displayName": "Delete a person",
+      "url": "https://developers.salesloft.com/docs/api/people-destroy"
+    },
+    {
+      "name": "people-index",
+      "displayName": "List people",
+      "url": "https://developers.salesloft.com/docs/api/people-index"
+    },
     {
       "name": "people-show",
       "displayName": "Fetch a person",
@@ -461,25 +531,20 @@
       "url": "https://developers.salesloft.com/docs/api/people-update"
     },
     {
-      "name": "people-destroy",
-      "displayName": "Delete a person",
-      "url": "https://developers.salesloft.com/docs/api/people-destroy"
+      "name": "person-stages-create",
+      "displayName": "Create a person stage",
+      "url": "https://developers.salesloft.com/docs/api/person-stages-create"
     },
     {
-      "name": "data-control-people-soft-deletion-create",
-      "displayName": "Submit a people soft deletion request",
-      "url": "https://developers.salesloft.com/docs/api/data-control-people-soft-deletion-create"
+      "name": "person-stages-destroy",
+      "displayName": "Delete an person stage",
+      "url": "https://developers.salesloft.com/docs/api/person-stages-destroy"
     },
     {
       "name": "person-stages-index",
       "displayName": "List person stages",
       "url": "https://developers.salesloft.com/docs/api/person-stages-index"
     },
-    {
-      "name": "person-stages-create",
-      "displayName": "Create a person stage",
-      "url": "https://developers.salesloft.com/docs/api/person-stages-create"
-    },
     {
       "name": "person-stages-show",
       "displayName": "Fetch a person stage",
@@ -490,11 +555,6 @@
       "displayName": "Update a person stage",
       "url": "https://developers.salesloft.com/docs/api/person-stages-update"
     },
-    {
-      "name": "person-stages-destroy",
-      "displayName": "Delete an person stage",
-      "url": "https://developers.salesloft.com/docs/api/person-stages-destroy"
-    },
     {
       "name": "person-upserts-create",
       "displayName": "Upsert a person",
@@ -511,29 +571,9 @@
       "url": "https://developers.salesloft.com/docs/api/phone-number-assignments-show"
     },
     {
-      "name": "integrations-signals-registrations-plays-update",
-      "displayName": "Update a Play Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-update"
-    },
-    {
-      "name": "integrations-signals-registrations-plays-show",
-      "displayName": "Show a Play Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-show"
-    },
-    {
-      "name": "integrations-signals-registrations-plays-destroy",
-      "displayName": "Delete a Play Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-destroy"
-    },
-    {
-      "name": "integrations-signals-registrations-plays-create",
-      "displayName": "Create a Play Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-create"
-    },
-    {
-      "name": "integrations-signals-registrations-plays-index",
-      "displayName": "List Play Registrations",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-plays-index"
+      "name": "phone-numbers-caller-ids-index",
+      "displayName": "List caller ids",
+      "url": "https://developers.salesloft.com/docs/api/phone-numbers-caller-ids-index"
     },
     {
       "name": "phone-numbers-recording-settings-show",
@@ -541,85 +581,30 @@
       "url": "https://developers.salesloft.com/docs/api/phone-numbers-recording-settings-show"
     },
     {
-      "name": "data-control-requests-show",
-      "displayName": "Fetch a Request record",
-      "url": "https://developers.salesloft.com/docs/api/data-control-requests-show"
-    },
-    {
-      "name": "data-control-requests-index",
-      "displayName": "Retrieve a list of Requests",
-      "url": "https://developers.salesloft.com/docs/api/data-control-requests-index"
-    },
-    {
-      "name": "meetings-reschedule-links-show",
-      "displayName": "Fetch a reschedule meeting link",
-      "url": "https://developers.salesloft.com/docs/api/meetings-reschedule-links-show"
+      "name": "saved-list-views-create",
+      "displayName": "Create a saved list view",
+      "url": "https://developers.salesloft.com/docs/api/saved-list-views-create"
     },
     {
-      "name": "data-control-right-to-be-forgotten-create",
-      "displayName": "Submit a right to be forgotten request",
-      "url": "https://developers.salesloft.com/docs/api/data-control-right-to-be-forgotten-create"
+      "name": "saved-list-views-destroy",
+      "displayName": "Delete a saved list view",
+      "url": "https://developers.salesloft.com/docs/api/saved-list-views-destroy"
     },
     {
       "name": "saved-list-views-index",
       "displayName": "List saved list views",
       "url": "https://developers.salesloft.com/docs/api/saved-list-views-index"
     },
-    {
-      "name": "saved-list-views-create",
-      "displayName": "Create a saved list view",
-      "url": "https://developers.salesloft.com/docs/api/saved-list-views-create"
-    },
     {
       "name": "saved-list-views-show",
       "displayName": "Fetch a saved list view",
       "url": "https://developers.salesloft.com/docs/api/saved-list-views-show"
     },
-    {
-      "name": "saved-list-views-destroy",
-      "displayName": "Delete a saved list view",
-      "url": "https://developers.salesloft.com/docs/api/saved-list-views-destroy"
-    },
     {
       "name": "saved-list-views-update",
       "displayName": "Update a saved list view",
       "url": "https://developers.salesloft.com/docs/api/saved-list-views-update"
     },
-    {
-      "name": "meetings-settings-searches-create",
-      "displayName": "List meeting settings",
-      "url": "https://developers.salesloft.com/docs/api/meetings-settings-searches-create"
-    },
-    {
-      "name": "meetings-settings-update",
-      "displayName": "Update a meeting setting",
-      "url": "https://developers.salesloft.com/docs/api/meetings-settings-update"
-    },
-    {
-      "name": "integrations-signals-registrations-update",
-      "displayName": "Update a Signal Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-update"
-    },
-    {
-      "name": "integrations-signals-registrations-show",
-      "displayName": "Fetch a Signal Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-show"
-    },
-    {
-      "name": "integrations-signals-registrations-destroy",
-      "displayName": "Deletes a Signal Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-destroy"
-    },
-    {
-      "name": "integrations-signals-registrations-create",
-      "displayName": "Create a Signal Registration",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-create"
-    },
-    {
-      "name": "integrations-signals-registrations-index",
-      "displayName": "List Signal Registrations",
-      "url": "https://developers.salesloft.com/docs/api/integrations-signals-registrations-index"
-    },
     {
       "name": "signals-create",
       "displayName": "Create a Signal",
@@ -645,6 +630,11 @@
       "displayName": "List team tags",
       "url": "https://developers.salesloft.com/docs/api/tags-index"
     },
+    {
+      "name": "tasks-counts-index",
+      "displayName": "Fetch task counts",
+      "url": "https://developers.salesloft.com/docs/api/tasks-counts-index"
+    },
     {
       "name": "tasks-create",
       "displayName": "Create a Task",
@@ -665,6 +655,11 @@
       "displayName": "Update a Task",
       "url": "https://developers.salesloft.com/docs/api/tasks-update"
     },
+    {
+      "name": "team-index",
+      "displayName": "Fetch current team",
+      "url": "https://developers.salesloft.com/docs/api/team-index"
+    },
     {
       "name": "team-template-attachments-index",
       "displayName": "List team template attachments",
@@ -680,6 +675,11 @@
       "displayName": "Fetch a team template",
       "url": "https://developers.salesloft.com/docs/api/team-templates-show"
     },
+    {
+      "name": "third-party-live-feed-items-create",
+      "displayName": "Create a live feed item",
+      "url": "https://developers.salesloft.com/docs/api/third-party-live-feed-items-create"
+    },
     {
       "name": "users-index",
       "displayName": "List users",
@@ -696,29 +696,29 @@
       "url": "https://developers.salesloft.com/docs/api/users-update"
     },
     {
-      "name": "webhook-subscriptions-update",
-      "displayName": "Update a webhook subscription",
-      "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-update"
-    },
-    {
-      "name": "webhook-subscriptions-show",
-      "displayName": "Fetch a webhook subscription",
-      "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-show"
+      "name": "webhook-subscriptions-create",
+      "displayName": "Create a webhook subscription",
+      "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-create"
     },
     {
       "name": "webhook-subscriptions-destroy",
       "displayName": "Delete a webhook subscription",
       "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-destroy"
     },
-    {
-      "name": "webhook-subscriptions-create",
-      "displayName": "Create a webhook subscription",
-      "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-create"
-    },
     {
       "name": "webhook-subscriptions-index",
       "displayName": "List webhook subscriptions",
       "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-index"
+    },
+    {
+      "name": "webhook-subscriptions-show",
+      "displayName": "Fetch a webhook subscription",
+      "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-show"
+    },
+    {
+      "name": "webhook-subscriptions-update",
+      "displayName": "Update a webhook subscription",
+      "url": "https://developers.salesloft.com/docs/api/webhook-subscriptions-update"
     }
   ]
 }
\ No newline at end of file
diff --git a/salesloft/metadata/schemas.json b/salesloft/metadata/schemas.json
index ce3c12ee..b69e2ff1 100755
--- a/salesloft/metadata/schemas.json
+++ b/salesloft/metadata/schemas.json
@@ -1,6 +1,6 @@
 {
   "data": {
-    "account-stages": {
+    "account_stages": {
       "displayName": "List account stages",
       "fields": {
         "active": "active",
@@ -11,7 +11,7 @@
         "updated_at": "updated_at"
       }
     },
-    "account-tiers": {
+    "account_tiers": {
       "displayName": "List Account Tiers",
       "fields": {
         "created_at": "created_at",
@@ -66,7 +66,7 @@
         "website": "website"
       }
     },
-    "action-details-call-instructions": {
+    "action_details_call_instructions": {
       "displayName": "List call instructions",
       "fields": {
         "created_at": "created_at",
@@ -94,7 +94,7 @@
         "user": "user"
       }
     },
-    "activities-calls": {
+    "activities_calls": {
       "displayName": "List calls",
       "fields": {
         "action": "action",
@@ -115,7 +115,7 @@
         "user": "user"
       }
     },
-    "activities-emails": {
+    "activities_emails": {
       "displayName": "List emails",
       "fields": {
         "action": "action",
@@ -127,6 +127,7 @@
         "counts": "counts",
         "created_at": "created_at",
         "crm_activity": "crm_activity",
+        "draft_with_ai": "draft_with_ai",
         "email_template": "email_template",
         "error_message": "error_message",
         "headers": "headers",
@@ -146,7 +147,7 @@
         "view_tracking": "view_tracking"
       }
     },
-    "activity-histories": {
+    "activity_histories": {
       "displayName": "List Past Activities",
       "fields": {
         "created_at": "created_at",
@@ -164,7 +165,7 @@
         "user_guid": "user_guid"
       }
     },
-    "bulk-jobs": {
+    "bulk_jobs": {
       "displayName": "List bulk jobs",
       "fields": {
         "created_at": "created_at",
@@ -183,7 +184,7 @@
         "updated_at": "updated_at"
       }
     },
-    "bulk-jobs-job-data": {
+    "bulk_jobs_job_data": {
       "displayName": "List job data for a bulk job",
       "fields": {
         "error": "error",
@@ -193,7 +194,7 @@
         "status": "status"
       }
     },
-    "bulk-jobs-results": {
+    "bulk_jobs_results": {
       "displayName": "List job data for a completed bulk job.",
       "fields": {
         "error": "error",
@@ -203,7 +204,7 @@
         "status": "status"
       }
     },
-    "cadence-memberships": {
+    "cadence_memberships": {
       "displayName": "List cadence memberships",
       "fields": {
         "added_at": "added_at",
@@ -252,7 +253,7 @@
         "updated_at": "updated_at"
       }
     },
-    "calendar-events": {
+    "calendar_events": {
       "displayName": "List calendar events",
       "fields": {
         "all_day": "all_day",
@@ -285,7 +286,7 @@
         "user_guid": "user_guid"
       }
     },
-    "call-data-records": {
+    "call_data_records": {
       "displayName": "List call data records",
       "fields": {
         "call": "call",
@@ -307,7 +308,7 @@
         "user": "user"
       }
     },
-    "call-dispositions": {
+    "call_dispositions": {
       "displayName": "List call dispositions",
       "fields": {
         "created_at": "created_at",
@@ -316,7 +317,7 @@
         "updated_at": "updated_at"
       }
     },
-    "call-sentiments": {
+    "call_sentiments": {
       "displayName": "List call sentiments",
       "fields": {
         "created_at": "created_at",
@@ -325,7 +326,7 @@
         "updated_at": "updated_at"
       }
     },
-    "crm-activities": {
+    "crm_activities": {
       "displayName": "List crm activities",
       "fields": {
         "activity_type": "activity_type",
@@ -341,7 +342,7 @@
         "user": "user"
       }
     },
-    "crm-activity-fields": {
+    "crm_activity_fields": {
       "displayName": "List crm activity fields",
       "fields": {
         "created_at": "created_at",
@@ -357,7 +358,7 @@
         "value": "value"
       }
     },
-    "crm-users": {
+    "crm_users": {
       "displayName": "List crm users",
       "fields": {
         "created_at": "created_at",
@@ -370,7 +371,7 @@
         "user": "user"
       }
     },
-    "custom-fields": {
+    "custom_fields": {
       "displayName": "List custom fields",
       "fields": {
         "created_at": "created_at",
@@ -381,14 +382,14 @@
         "value_type": "value_type"
       }
     },
-    "custom-roles": {
+    "custom_roles": {
       "displayName": "List custom roles",
       "fields": {
         "id": "id",
         "name": "name"
       }
     },
-    "data-control-requests": {
+    "data_control_requests": {
       "displayName": "Retrieve a list of Requests",
       "fields": {
         "dry_run": "dry_run",
@@ -400,7 +401,7 @@
         "user_guid": "user_guid"
       }
     },
-    "email-template-attachments": {
+    "email_template_attachments": {
       "displayName": "List email template attachments",
       "fields": {
         "attachment_content_type": "attachment_content_type",
@@ -414,7 +415,7 @@
         "scanned": "scanned"
       }
     },
-    "email-templates": {
+    "email_templates": {
       "displayName": "List email templates",
       "fields": {
         "_links": "_links",
@@ -461,7 +462,7 @@
         "user_id": "user_id"
       }
     },
-    "integrations-signals-registrations": {
+    "integrations_signals_registrations": {
       "displayName": "List Signal Registrations",
       "fields": {
         "attribution": "attribution",
@@ -477,7 +478,7 @@
         "type": "type"
       }
     },
-    "integrations-signals-registrations-plays": {
+    "integrations_signals_registrations_plays": {
       "displayName": "List Play Registrations",
       "fields": {
         "attributes": "attributes",
@@ -522,6 +523,7 @@
         "last_name": "last_name",
         "local_dial_enabled": "local_dial_enabled",
         "locale_utc_offset": "locale_utc_offset",
+        "manager_user_guid": "manager_user_guid",
         "name": "name",
         "phone_client": "phone_client",
         "phone_number_assignment": "phone_number_assignment",
@@ -597,7 +599,7 @@
         "user": "user"
       }
     },
-    "pending-emails": {
+    "pending_emails": {
       "displayName": "List pending emails",
       "fields": {
         "id": "id",
@@ -667,7 +669,7 @@
         "work_state": "work_state"
       }
     },
-    "person-stages": {
+    "person_stages": {
       "displayName": "List person stages",
       "fields": {
         "active": "active",
@@ -678,7 +680,7 @@
         "updated_at": "updated_at"
       }
     },
-    "phone-number-assignments": {
+    "phone_number_assignments": {
       "displayName": "List phone number assignments",
       "fields": {
         "id": "id",
@@ -686,7 +688,7 @@
         "user": "user"
       }
     },
-    "phone-numbers-caller-ids": {
+    "phone_numbers_caller_ids": {
       "displayName": "List caller ids",
       "fields": {
         "account_name": "account_name",
@@ -695,7 +697,7 @@
         "title": "title"
       }
     },
-    "saved-list-views": {
+    "saved_list_views": {
       "displayName": "List saved list views",
       "fields": {
         "id": "id",
@@ -769,13 +771,14 @@
         "user": "user"
       }
     },
-    "tasks-counts": {
+    "tasks_counts": {
       "displayName": "Fetch task counts",
       "fields": {
         "call": "call",
         "email": "email",
         "general": "general",
         "integration": "integration",
+        "other": "other",
         "total": "total"
       }
     },
@@ -803,7 +806,7 @@
         "updated_at": "updated_at"
       }
     },
-    "team-template-attachments": {
+    "team_template_attachments": {
       "displayName": "List team template attachments",
       "fields": {
         "attachment_file_size": "attachment_file_size",
@@ -814,7 +817,7 @@
         "team_template": "team_template"
       }
     },
-    "team-templates": {
+    "team_templates": {
       "displayName": "List team templates",
       "fields": {
         "_links": "_links",
@@ -860,6 +863,7 @@
         "last_name": "last_name",
         "local_dial_enabled": "local_dial_enabled",
         "locale_utc_offset": "locale_utc_offset",
+        "manager_user_guid": "manager_user_guid",
         "name": "name",
         "phone_client": "phone_client",
         "phone_number_assignment": "phone_number_assignment",
@@ -874,7 +878,7 @@
         "work_country": "work_country"
       }
     },
-    "webhook-subscriptions": {
+    "webhook_subscriptions": {
       "displayName": "List webhook subscriptions",
       "fields": {
         "callback_token": "callback_token",
diff --git a/salesloft/read.go b/salesloft/read.go
index 02a96e37..916dbdf9 100644
--- a/salesloft/read.go
+++ b/salesloft/read.go
@@ -3,6 +3,7 @@ package salesloft
 import (
 	"context"
 	"strconv"
+	"time"
 
 	"github.com/amp-labs/connectors/common"
 	"github.com/amp-labs/connectors/common/urlbuilder"
@@ -43,5 +44,14 @@ func (c *Connector) buildReadURL(config common.ReadParams) (*urlbuilder.URL, err
 
 	link.WithQueryParam("per_page", strconv.Itoa(DefaultPageSize))
 
+	if !config.Since.IsZero() {
+		// Documentation states ISO8601, while server accepts different formats
+		// but for consistency we are sticking to one format to be sent.
+		// For the reference any API resource that includes time data type mentions iso8601 string format.
+		// One example, say accounts is https://developers.salesloft.com/docs/api/accounts-index
+		updatedSince := config.Since.Format(time.RFC3339Nano)
+		link.WithQueryParam("updated_at[gte]", updatedSince)
+	}
+
 	return link, nil
 }
diff --git a/scripts/catalog/json.go b/scripts/catalog/json.go
new file mode 100644
index 00000000..d584df75
--- /dev/null
+++ b/scripts/catalog/json.go
@@ -0,0 +1,30 @@
+package main
+
+import (
+	"encoding/json"
+	"log"
+	"os"
+
+	"github.com/amp-labs/connectors/providers"
+)
+
+func main() {
+	catalog, err := providers.ReadCatalog()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	bytes, err := json.Marshal(catalog)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	tempFile := "providers/catalog.json"
+
+	err = os.WriteFile(tempFile, bytes, 0o644)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	log.Printf("Catalog successfully written to: %s\n", tempFile)
+}
diff --git a/scripts/oauth/token.go b/scripts/oauth/token.go
index 06f9f519..e219d345 100644
--- a/scripts/oauth/token.go
+++ b/scripts/oauth/token.go
@@ -2,6 +2,7 @@
 package main
 
 import (
+	"context"
 	"encoding/base64"
 	"encoding/json"
 	"flag"
@@ -9,6 +10,7 @@ import (
 	"log"
 	"log/slog"
 	"net/http"
+	"net/url"
 	"os"
 	"os/exec"
 	"runtime"
@@ -19,6 +21,7 @@ import (
 	"github.com/amp-labs/connectors/providers"
 	"github.com/amp-labs/connectors/utils"
 	"golang.org/x/oauth2"
+	"golang.org/x/oauth2/clientcredentials"
 )
 
 // ================================
@@ -96,14 +99,16 @@ var readers = []utils.Reader{
 
 // OAuthApp is a simple OAuth app that can be used to get an OAuth token.
 type OAuthApp struct {
-	Callback string
-	Port     int
-	Config   *oauth2.Config
-	Options  []oauth2.AuthCodeOption
-	State    string
-	Proto    string
-	SSLCert  string
-	SSLKey   string
+	GrantType         providers.OauthOptsGrantType
+	Callback          string
+	Port              int
+	Config            *oauth2.Config
+	ClientCredsConfig *clientcredentials.Config
+	Options           []oauth2.AuthCodeOption
+	State             string
+	Proto             string
+	SSLCert           string
+	SSLKey            string
 }
 
 // ServeHTTP implements the http.Handler interface.
@@ -193,25 +198,40 @@ func (a *OAuthApp) processCallback(writer http.ResponseWriter, request *http.Req
 
 // Run executes the OAuth flow to get a token.
 func (a *OAuthApp) Run() error {
-	slog.Info("starting OAuth app", "port", a.Port)
+	if a.GrantType == providers.ClientCredentials {
+		src := a.ClientCredsConfig.TokenSource(context.Background())
 
-	http.Handle("/", a)
-
-	go func() {
-		time.Sleep(1 * time.Second)
-		openBrowser(fmt.Sprintf("%s://localhost:%d", a.Proto, a.Port))
-	}()
+		tok, err := src.Token()
+		if err != nil {
+			return err
+		}
 
-	server := &http.Server{
-		Addr:              fmt.Sprintf("0.0.0.0:%d", a.Port),
-		ReadHeaderTimeout: ReadHeaderTimeoutSeconds * time.Second,
-	}
+		header := tok.Type() + " " + tok.AccessToken
+		fmt.Println("Expiry: " + tok.Expiry.String())
+		fmt.Println("Authorization: " + header)
 
-	if a.Proto == HttpProtocol {
-		// nosemgrep: go.lang.security.audit.net.use-tls.use-tls
-		return server.ListenAndServe()
+		return nil
 	} else {
-		return server.ListenAndServeTLS(a.SSLCert, a.SSLKey)
+		slog.Info("starting OAuth app", "port", a.Port)
+
+		http.Handle("/", a)
+
+		go func() {
+			time.Sleep(1 * time.Second)
+			openBrowser(fmt.Sprintf("%s://localhost:%d", a.Proto, a.Port))
+		}()
+
+		server := &http.Server{
+			Addr:              fmt.Sprintf("0.0.0.0:%d", a.Port),
+			ReadHeaderTimeout: ReadHeaderTimeoutSeconds * time.Second,
+		}
+
+		if a.Proto == HttpProtocol {
+			// nosemgrep: go.lang.security.audit.net.use-tls.use-tls
+			return server.ListenAndServe()
+		} else {
+			return server.ListenAndServeTLS(a.SSLCert, a.SSLKey)
+		}
 	}
 }
 
@@ -248,24 +268,46 @@ func setup() *OAuthApp {
 	callback := flag.String("callback", DefaultCallbackPath, "the full OAuth callback path (arbitrary)")
 	flag.Parse()
 
-	err := registry.AddReaders(readers...)
+	substitutions, err := registry.GetMap("Substitutions")
 	if err != nil {
-		return nil
+		slog.Warn("no substitutions, ensure that the provider info doesn't have any {{variables}}")
 	}
 
-	// Determine the OAuth redirect URL.
-	redirect := fmt.Sprintf("%s://localhost:%d%s", *proto, *port, *callback)
+	// Cast the substitutions to a map[string]string
+	substitutionsMap := make(map[string]string)
+	for key, val := range substitutions {
+		substitutionsMap[key] = val.MustString()
+	}
+
+	if err = registry.AddReaders(readers...); err != nil {
+		return nil
+	}
 
-	// Get the OAuth scopes from the flag.
 	provider := registry.MustString("Provider")
-	clientId := registry.MustString("ClientId")
-	clientSecret := registry.MustString("ClientSecret")
 
-	state, err := registry.GetString("State")
+	providerInfo, err := providers.ReadInfo(provider, &substitutionsMap)
 	if err != nil {
-		slog.Warn("no state attached, ensure that the provider doesn't require state")
+		slog.Error("failed to read provider config", "error", err)
+
+		os.Exit(1)
+	}
+
+	if providerInfo.AuthType != providers.Oauth2 {
+		slog.Error("provider does not support OAuth2, not compatible with this script", "provider", provider)
+
+		os.Exit(1)
+	}
+
+	if providerInfo.OauthOpts == nil {
+		slog.Error("provider does not have OAuth2 options, not compatible with this script", "provider", provider)
+
+		os.Exit(1)
 	}
 
+	// Get the OAuth scopes from the flag.
+	clientId := registry.MustString("ClientId")
+	clientSecret := registry.MustString("ClientSecret")
+
 	scopes, err := registry.GetString("Scopes")
 	if err != nil {
 		slog.Warn("no scopes attached, ensure that the provider doesn't require scopes")
@@ -273,50 +315,83 @@ func setup() *OAuthApp {
 
 	oauthScopes := strings.Split(scopes, ",")
 
-	// Create the OAuth app.
-	app := &OAuthApp{
-		Callback: *callback,
-		Port:     *port,
-		Proto:    *proto,
-		SSLCert:  *SSLCert,
-		SSLKey:   *SSLKey,
-		Config: &oauth2.Config{
-			ClientID:     clientId,
-			ClientSecret: clientSecret,
-			RedirectURL:  redirect,
-			Scopes:       oauthScopes,
-		},
-	}
-	if state != "" {
-		app.State = state
-	}
+	switch providerInfo.OauthOpts.GrantType {
+	case providers.AuthorizationCode:
+		if providerInfo.OauthOpts.AuthURL == "" {
+			slog.Error("provider does not have an AuthURL, not compatible with this script", "provider", provider)
 
-	substitutions, err := registry.GetMap("Substitutions")
-	if err != nil {
-		slog.Warn("no substitutions, ensure that the provider info doesn't have any {{variables}}")
-	}
+			os.Exit(1)
+		}
 
-	// Cast the substitutions to a map[string]string
-	substitutionsMap := make(map[string]string)
-	for key, val := range substitutions {
-		substitutionsMap[key] = val.MustString()
-	}
+		// Determine the OAuth redirect URL.
+		redirect := fmt.Sprintf("%s://localhost:%d%s", *proto, *port, *callback)
 
-	providerInfo, err := providers.ReadInfo(provider, &substitutionsMap)
-	if err != nil {
-		slog.Error("failed to read provider config", "error", err)
+		state, err := registry.GetString("State")
+		if err != nil {
+			slog.Warn("no state attached, ensure that the provider doesn't require state")
+		}
 
-		os.Exit(1)
-	}
+		// Create the OAuth app.
+		app := &OAuthApp{
+			GrantType: providers.AuthorizationCode,
+			Callback:  *callback,
+			Port:      *port,
+			Proto:     *proto,
+			SSLCert:   *SSLCert,
+			SSLKey:    *SSLKey,
+			Config: &oauth2.Config{
+				ClientID:     clientId,
+				ClientSecret: clientSecret,
+				RedirectURL:  redirect,
+				Scopes:       oauthScopes,
+			},
+		}
+		if state != "" {
+			app.State = state
+		}
+
+		// Set up the OAuth config based on the provider.
+		app.Config.Endpoint = oauth2.Endpoint{
+			AuthURL:   providerInfo.OauthOpts.AuthURL,
+			TokenURL:  providerInfo.OauthOpts.TokenURL,
+			AuthStyle: oauth2.AuthStyleAutoDetect,
+		}
 
-	// Set up the OAuth config based on the provider.
-	app.Config.Endpoint = oauth2.Endpoint{
-		AuthURL:   providerInfo.OauthOpts.AuthURL,
-		TokenURL:  providerInfo.OauthOpts.TokenURL,
-		AuthStyle: oauth2.AuthStyleAutoDetect,
+		return app
+	case providers.ClientCredentials:
+		state, err := registry.GetString("State")
+		if err != nil {
+			slog.Warn("no state attached, ensure that the provider doesn't require state")
+		}
+
+		// Create the OAuth app.
+		app := &OAuthApp{
+			GrantType: providers.ClientCredentials,
+			ClientCredsConfig: &clientcredentials.Config{
+				ClientID:     clientId,
+				ClientSecret: clientSecret,
+				TokenURL:     providerInfo.OauthOpts.TokenURL,
+				Scopes:       oauthScopes,
+				AuthStyle:    oauth2.AuthStyleAutoDetect,
+			},
+		}
+		if state != "" {
+			app.State = state
+		}
+
+		if providerInfo.OauthOpts.Audience != "" {
+			aud := providerInfo.OauthOpts.Audience
+			app.ClientCredsConfig.EndpointParams = url.Values{"audience": {aud}}
+		}
+
+		return app
+	default:
+		slog.Error("provider does not support authorization code or client credentials grant, not compatible with this script", "provider", provider)
+
+		os.Exit(1)
 	}
 
-	return app
+	return nil
 }
 
 func main() {
diff --git a/scripts/proxy/proxy.go b/scripts/proxy/proxy.go
index 8b6a4d03..b96a08d0 100644
--- a/scripts/proxy/proxy.go
+++ b/scripts/proxy/proxy.go
@@ -190,7 +190,7 @@ func mainOAuth2ClientCreds(ctx context.Context, provider string, substitutionsMa
 
 	oauthScopes := strings.Split(scopes, ",")
 
-	validateRequiredOAuth2Flags(ctx, provider, clientId, clientSecret)
+	validateRequiredOAuth2Flags(provider, clientId, clientSecret)
 	startOAuthClientCredsProxy(ctx, provider, oauthScopes, clientId, clientSecret, substitutionsMap, DefaultPort)
 }
 
@@ -206,7 +206,7 @@ func mainOAuth2AuthCode(ctx context.Context, provider string, substitutionsMap m
 
 	oauthScopes := strings.Split(scopes, ",")
 
-	validateRequiredOAuth2Flags(ctx, provider, clientId, clientSecret)
+	validateRequiredOAuth2Flags(provider, clientId, clientSecret)
 	startOAuthAuthCodeProxy(ctx, provider, oauthScopes, clientId, clientSecret, substitutionsMap, DefaultPort, tokens)
 }
 
@@ -287,7 +287,7 @@ func parseAccessTokenExpiry(expiryStr, timeFormat string) time.Time {
 	return expiry
 }
 
-func validateRequiredOAuth2Flags(ctx context.Context, provider, clientId, clientSecret string) {
+func validateRequiredOAuth2Flags(provider, clientId, clientSecret string) {
 	if provider == "" || clientId == "" || clientSecret == "" {
 		_, _ = fmt.Fprintln(os.Stderr, "Missing required flags: -provider, -client-id, -client-secret")
 
@@ -434,12 +434,22 @@ func getProviderConfig(provider string, substitutions map[string]string) *provid
 }
 
 func configureOAuthClientCredentials(clientId, clientSecret string, scopes []string, providerInfo *providers.ProviderInfo) *clientcredentials.Config {
-	return &clientcredentials.Config{
+	cfg := &clientcredentials.Config{
 		ClientID:     clientId,
 		ClientSecret: clientSecret,
-		Scopes:       scopes,
 		TokenURL:     providerInfo.OauthOpts.TokenURL,
 	}
+
+	if providerInfo.OauthOpts.ExplicitScopesRequired {
+		cfg.Scopes = scopes
+	}
+
+	if providerInfo.OauthOpts.Audience != "" {
+		aud := providerInfo.OauthOpts.Audience
+		cfg.EndpointParams = url.Values{"audience": {aud}}
+	}
+
+	return cfg
 }
 
 func configureOAuthAuthCode(clientId, clientSecret string, scopes []string, providerInfo *providers.ProviderInfo) *oauth2.Config {
diff --git a/scripts/scrapper/salesloft/metadata/main.go b/scripts/scrapper/salesloft/metadata/main.go
index 720f1acd..aab96f77 100644
--- a/scripts/scrapper/salesloft/metadata/main.go
+++ b/scripts/scrapper/salesloft/metadata/main.go
@@ -7,6 +7,7 @@ import (
 	"github.com/PuerkitoBio/goquery"
 	"github.com/amp-labs/connectors/salesloft/metadata"
 	"github.com/amp-labs/connectors/tools/scrapper"
+	"github.com/iancoleman/strcase"
 )
 
 const (
@@ -56,6 +57,8 @@ func createSchemas() {
 		doc := scrapper.QueryHTML(model.URL)
 
 		// There are 2 unordered lists that describe response schema
+		modelName := strcase.ToSnake(model.Name)
+
 		doc.Find(`.openapi-tabs__schema-container ul`).
 			Each(func(i int, list *goquery.Selection) {
 				list.Children().Each(func(i int, property *goquery.Selection) {
@@ -63,12 +66,12 @@ func createSchemas() {
 					// Only the first most field represents top level fields of response payload
 					fieldName := property.Find(`strong`).First().Text()
 					if len(fieldName) != 0 {
-						schemas.Add(model.Name, model.DisplayName, fieldName)
+						schemas.Add(modelName, model.DisplayName, fieldName)
 					}
 				})
 			})
 
-		log.Printf("Schemas completed %.2f%% [%v]\n", getPercentage(i, len(filteredListDocs)), model.Name)
+		log.Printf("Schemas completed %.2f%% [%v]\n", getPercentage(i, len(filteredListDocs)), modelName)
 	}
 
 	must(metadata.FileManager.SaveSchemas(schemas))
diff --git a/tools/scrapper/files.go b/tools/scrapper/files.go
index 5396388e..594efe02 100644
--- a/tools/scrapper/files.go
+++ b/tools/scrapper/files.go
@@ -26,6 +26,8 @@ func NewMetadataFileManager(schemas []byte, locator MetadataFileLocator) *Metada
 }
 
 func (m MetadataFileManager) SaveIndex(index *ModelURLRegistry) error {
+	index.Sort()
+
 	return FlushToFile(m.locator.AbsPathTo(IndexFile), index)
 }
 
diff --git a/tools/scrapper/models.go b/tools/scrapper/models.go
index bde481cb..da9a9618 100644
--- a/tools/scrapper/models.go
+++ b/tools/scrapper/models.go
@@ -1,6 +1,7 @@
 package scrapper
 
 import (
+	"sort"
 	"strings"
 )
 
@@ -49,6 +50,12 @@ func (r *ModelURLRegistry) Add(displayName, url string) {
 	})
 }
 
+func (r *ModelURLRegistry) Sort() {
+	sort.Slice(r.ModelDocs, func(i, j int) bool {
+		return r.ModelDocs[i].Name < r.ModelDocs[j].Name
+	})
+}
+
 type ObjectMetadataResult struct {
 	// Result is a map of object names to object metadata
 	Result map[string]ObjectMetadata `json:"data"`


Test patch:
diff --git a/salesloft/metadata_test.go b/salesloft/metadata_test.go
index 456dd5f4..e1d91a77 100644
--- a/salesloft/metadata_test.go
+++ b/salesloft/metadata_test.go
@@ -42,13 +42,13 @@ func TestListObjectMetadata(t *testing.T) { // nolint:funlen,gocognit,cyclop
 		},
 		{
 			name:  "Successfully describe one object with metadata",
-			input: []string{"bulk-jobs-results"},
+			input: []string{"bulk_jobs_results"},
 			server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				w.WriteHeader(http.StatusTeapot)
 			})),
 			expected: &common.ListObjectMetadataResult{
 				Result: map[string]common.ObjectMetadata{
-					"bulk-jobs-results": {
+					"bulk_jobs_results": {
 						DisplayName: "List job data for a completed bulk job.",
 						FieldsMap: map[string]string{
 							"error":    "error",
@@ -65,13 +65,13 @@ func TestListObjectMetadata(t *testing.T) { // nolint:funlen,gocognit,cyclop
 		},
 		{
 			name:  "Successfully describe multiple objects with metadata",
-			input: []string{"account-tiers", "actions"},
+			input: []string{"account_tiers", "actions"},
 			server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 				w.WriteHeader(http.StatusTeapot)
 			})),
 			expected: &common.ListObjectMetadataResult{
 				Result: map[string]common.ObjectMetadata{
-					"account-tiers": {
+					"account_tiers": {
 						DisplayName: "List Account Tiers",
 						FieldsMap: map[string]string{
 							"created_at": "created_at",
diff --git a/salesloft/read_test.go b/salesloft/read_test.go
index 8f36650a..a0bb2ed5 100644
--- a/salesloft/read_test.go
+++ b/salesloft/read_test.go
@@ -5,9 +5,11 @@ import (
 	"errors"
 	"net/http"
 	"net/http/httptest"
+	"net/url"
 	"reflect"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/amp-labs/connectors/common"
 	"github.com/amp-labs/connectors/common/interpreter"
@@ -22,6 +24,10 @@ func TestRead(t *testing.T) { //nolint:funlen,gocognit,cyclop,maintidx
 	responseEmptyRead := mockutils.DataFromFile(t, "read-empty.json")
 	responseListPeople := mockutils.DataFromFile(t, "read-list-people.json")
 	responseListUsers := mockutils.DataFromFile(t, "read-list-users.json")
+	responseListAccounts := mockutils.DataFromFile(t, "read-list-accounts.json")
+	responseListAccountsSince := mockutils.DataFromFile(t, "read-list-accounts-since.json")
+	accountsSince, err := time.Parse(time.RFC3339Nano, "2024-06-07T10:51:20.851224-04:00")
+	mockutils.NoErrors(t, err)
 
 	tests := []struct {
 		name         string
@@ -193,6 +199,47 @@ func TestRead(t *testing.T) { //nolint:funlen,gocognit,cyclop,maintidx
 			},
 			expectedErrs: nil,
 		},
+		{
+			name:  "Successful read accounts without since query",
+			input: common.ReadParams{ObjectName: "accounts"},
+			server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+				w.Header().Set("Content-Type", "application/json")
+				mockutils.RespondToMissingQueryParameters(w, r, []string{"updated_at[gte]"}, func() {
+					w.WriteHeader(http.StatusOK)
+					_, _ = w.Write(responseListAccounts)
+				})
+			})),
+			comparator: func(baseURL string, actual, expected *common.ReadResult) bool {
+				return actual.Rows == expected.Rows
+			},
+			expected: &common.ReadResult{
+				Rows: 4,
+			},
+			expectedErrs: nil,
+		},
+		{
+			name: "Successful read accounts since point in time",
+			input: common.ReadParams{
+				ObjectName: "accounts",
+				Since:      accountsSince,
+			},
+			server: httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+				w.Header().Set("Content-Type", "application/json")
+				mockutils.RespondToQueryParameters(w, r, url.Values{
+					"updated_at[gte]": []string{"2024-06-07T10:51:20.851224-04:00"},
+				}, func() {
+					w.WriteHeader(http.StatusOK)
+					_, _ = w.Write(responseListAccountsSince)
+				})
+			})),
+			comparator: func(baseURL string, actual, expected *common.ReadResult) bool {
+				return actual.Rows == expected.Rows
+			},
+			expected: &common.ReadResult{
+				Rows: 2,
+			},
+			expectedErrs: nil,
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/salesloft/test/read-list-accounts-since.json b/salesloft/test/read-list-accounts-since.json
new file mode 100644
index 00000000..4c2f3568
--- /dev/null
+++ b/salesloft/test/read-list-accounts-since.json
@@ -0,0 +1,67 @@
+{
+  "metadata": {
+    "filtering": {
+      "updated_at": {
+        "gte": "2024-06-07T14:51:20.851224Z"
+      }
+    },
+    "paging": {
+      "per_page": 25,
+      "current_page": 1,
+      "next_page": null,
+      "prev_page": null
+    },
+    "sorting": {
+      "sort_by": "updated_at",
+      "sort_direction": "DESC NULLS LAST"
+    }
+  },
+  "data": [
+    {
+      "id": 48371814,
+      "created_at": "2024-06-07T10:51:48.966580-04:00",
+      "updated_at": "2024-06-07T10:51:48.966580-04:00",
+      "name": "Reebok",
+      "domain": "https://www.reebok.eu/en-gb/",
+      "crm_object_type": "account",
+      "do_not_contact": false,
+      "custom_fields": {},
+      "user_relationships": [],
+      "tags": [],
+      "counts": {
+        "people": null
+      },
+      "owner": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      },
+      "creator": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      }
+    },
+    {
+      "id": 48371806,
+      "created_at": "2024-06-07T10:51:20.851224-04:00",
+      "updated_at": "2024-06-07T10:51:20.851224-04:00",
+      "name": "Asics",
+      "domain": "https://www.asics.com/gb/en-gb/",
+      "crm_object_type": "account",
+      "do_not_contact": false,
+      "custom_fields": {},
+      "user_relationships": [],
+      "tags": [],
+      "counts": {
+        "people": null
+      },
+      "owner": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      },
+      "creator": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/salesloft/test/read-list-accounts.json b/salesloft/test/read-list-accounts.json
new file mode 100644
index 00000000..9fea1223
--- /dev/null
+++ b/salesloft/test/read-list-accounts.json
@@ -0,0 +1,109 @@
+{
+  "metadata": {
+    "filtering": {},
+    "paging": {
+      "per_page": 25,
+      "current_page": 1,
+      "next_page": null,
+      "prev_page": null
+    },
+    "sorting": {
+      "sort_by": "updated_at",
+      "sort_direction": "DESC NULLS LAST"
+    }
+  },
+  "data": [
+    {
+      "id": 48371814,
+      "created_at": "2024-06-07T10:51:48.966580-04:00",
+      "updated_at": "2024-06-07T10:51:48.966580-04:00",
+      "name": "Reebok",
+      "domain": "https://www.reebok.eu/en-gb/",
+      "crm_object_type": "account",
+      "do_not_contact": false,
+      "custom_fields": {},
+      "user_relationships": [],
+      "tags": [],
+      "counts": {
+        "people": null
+      },
+      "owner": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      },
+      "creator": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      }
+    },
+    {
+      "id": 48371806,
+      "created_at": "2024-06-07T10:51:20.851224-04:00",
+      "updated_at": "2024-06-07T10:51:20.851224-04:00",
+      "name": "Asics",
+      "domain": "https://www.asics.com/gb/en-gb/",
+      "crm_object_type": "account",
+      "do_not_contact": false,
+      "custom_fields": {},
+      "user_relationships": [],
+      "tags": [],
+      "counts": {
+        "people": null
+      },
+      "owner": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      },
+      "creator": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      }
+    },
+    {
+      "id": 48371772,
+      "created_at": "2024-06-07T10:50:43.502576-04:00",
+      "updated_at": "2024-06-07T10:50:43.502576-04:00",
+      "name": "Puma",
+      "domain": "https://us.puma.com/us/en",
+      "crm_object_type": "account",
+      "do_not_contact": false,
+      "custom_fields": {},
+      "user_relationships": [],
+      "tags": [],
+      "counts": {
+        "people": null
+      },
+      "owner": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      },
+      "creator": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      }
+    },
+    {
+      "id": 48316458,
+      "created_at": "2024-06-06T12:35:41.051972-04:00",
+      "updated_at": "2024-06-06T12:35:41.051972-04:00",
+      "name": "Nike",
+      "domain": "https://www.nike.com",
+      "crm_object_type": "account",
+      "do_not_contact": false,
+      "custom_fields": {},
+      "user_relationships": [],
+      "tags": [],
+      "counts": {
+        "people": null
+      },
+      "owner": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      },
+      "creator": {
+        "_href": "https://api.salesloft.com/v2/users/49067",
+        "id": 49067
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/test/utils/mockutils/checks.go b/test/utils/mockutils/checks.go
index 0c20b837..e1b8d5a1 100644
--- a/test/utils/mockutils/checks.go
+++ b/test/utils/mockutils/checks.go
@@ -1,6 +1,9 @@
 package mockutils
 
-import "fmt"
+import (
+	"fmt"
+	"testing"
+)
 
 func DoesObjectCorrespondToString(object any, correspondent string) bool {
 	if object == nil && len(correspondent) == 0 {
@@ -9,3 +12,9 @@ func DoesObjectCorrespondToString(object any, correspondent string) bool {
 
 	return fmt.Sprintf("%v", object) == correspondent
 }
+
+func NoErrors(t *testing.T, err error) {
+	if err != nil {
+		t.Fatalf("failed to start test, %v", err)
+	}
+}
diff --git a/test/utils/mockutils/server.go b/test/utils/mockutils/server.go
index 66124a3c..9743a7e7 100644
--- a/test/utils/mockutils/server.go
+++ b/test/utils/mockutils/server.go
@@ -3,6 +3,7 @@ package mockutils
 import (
 	"fmt"
 	"net/http"
+	"net/url"
 )
 
 func RespondNoContentForMethod(w http.ResponseWriter, r *http.Request, methodName string) {
@@ -42,6 +43,36 @@ func RespondToHeader(w http.ResponseWriter, r *http.Request, header http.Header,
 	}
 }
 
+func RespondToQueryParameters(w http.ResponseWriter, r *http.Request, queries url.Values, onSuccess func()) {
+	// if some query parameters are mismatching return error code so the test will fail
+	if queryParam, ok := queryParamsAreSubset(r.URL.Query(), queries); ok {
+		// if method is matching headers
+		onSuccess()
+	} else {
+		w.WriteHeader(http.StatusBadRequest)
+		WriteBody(w, fmt.Sprintf(`{
+			"error": {
+				"code": "from test",
+				"message": "test server mismatching [%v] query parameter"
+			}}`, queryParam))
+	}
+}
+
+func RespondToMissingQueryParameters(w http.ResponseWriter, r *http.Request, missingQueries []string, onSuccess func()) {
+	// if at least one query parameter exists return error code so the test will fail
+	if queryParam, ok := queryParamsMissing(r.URL.Query(), missingQueries); ok {
+		// if method is matching headers
+		onSuccess()
+	} else {
+		w.WriteHeader(http.StatusBadRequest)
+		WriteBody(w, fmt.Sprintf(`{
+			"error": {
+				"code": "from test",
+				"message": "test server found [%v] query parameter"
+			}}`, queryParam))
+	}
+}
+
 func WriteBody(w http.ResponseWriter, body string) {
 	_, _ = w.Write([]byte(body))
 }
@@ -59,5 +90,40 @@ func headerIsSubset(superset, subset http.Header) (string, bool) {
 			}
 		}
 	}
+
+	return "", true
+}
+
+func queryParamsAreSubset(superset, subset url.Values) (string, bool) {
+	for param, values := range subset {
+		superValues := make(map[string]bool)
+
+		strings, ok := superset[param]
+		if !ok {
+			return param, false
+		}
+
+		for _, v := range strings {
+			superValues[v] = true
+		}
+
+		for _, value := range values {
+			if _, found := superValues[value]; !found {
+				return param, false
+			}
+		}
+	}
+
+	return "", true
+}
+
+func queryParamsMissing(superset url.Values, missing []string) (string, bool) {
+	for _, param := range missing {
+		if superset.Has(param) {
+			// query was found, while should be missing
+			return param, false
+		}
+	}
+
 	return "", true
 }