diff --git a/cli/main.go b/cli/main.go
index 22c28c09..cb544b1b 100644
--- a/cli/main.go
+++ b/cli/main.go
@@ -6,14 +6,16 @@ import (
 	"github.com/containrrr/shoutrrr/cli/cmd/generate"
 	"github.com/containrrr/shoutrrr/cli/cmd/send"
 	"github.com/containrrr/shoutrrr/cli/cmd/verify"
+	"github.com/containrrr/shoutrrr/internal/meta"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"
 	"os"
 )
 
 var cmd = &cobra.Command{
-	Use:   "shoutrrr",
-	Short: "Notification library for gophers and their furry friends",
+	Use:     "shoutrrr",
+	Version: meta.Version,
+	Short:   "Shoutrrr CLI",
 }
 
 func init() {
diff --git a/internal/meta/version.go b/internal/meta/version.go
new file mode 100644
index 00000000..b60e41aa
--- /dev/null
+++ b/internal/meta/version.go
@@ -0,0 +1,7 @@
+package meta
+
+// Version of Shoutrrr
+const Version = `0.5-dev`
+
+// DocsVersion is prepended to documentation URLs and usually equals MAJOR.MINOR of Version
+const DocsVersion = `dev`
diff --git a/pkg/services/teams/teams.go b/pkg/services/teams/teams.go
index 151b1aad..0c59ba67 100644
--- a/pkg/services/teams/teams.go
+++ b/pkg/services/teams/teams.go
@@ -4,13 +4,14 @@ import (
 	"bytes"
 	"encoding/json"
 	"fmt"
-	"github.com/containrrr/shoutrrr/pkg/format"
 	"net/http"
 	"net/url"
 	"strings"
 
+	"github.com/containrrr/shoutrrr/pkg/format"
 	"github.com/containrrr/shoutrrr/pkg/services/standard"
 	"github.com/containrrr/shoutrrr/pkg/types"
+	"github.com/containrrr/shoutrrr/pkg/util"
 )
 
 // Service providing teams as a notification service
@@ -35,7 +36,7 @@ func (service *Service) Send(message string, params *types.Params) error {
 func (service *Service) Initialize(configURL *url.URL, logger types.StdLogger) error {
 	service.Logger.SetLogger(logger)
 	service.config = &Config{
-		Host: DefaultHost,
+		Host: LegacyHost,
 	}
 
 	service.pkr = format.NewPropKeyResolver(service.config)
@@ -93,9 +94,12 @@ func (service *Service) doSend(config *Config, message string) error {
 
 	host := config.Host
 	if host == "" {
-		host = DefaultHost
+		host = LegacyHost
+		// Emit a warning to the log for now.
+		// TODO(v0.6): Remove legacy support as it should be fully deprecated now
+		service.Logf(`Warning: No host specified, update your Teams URL: %s`, util.DocsURL(`services/teams`))
 	}
-	postURL := buildWebhookURL(host, config.webhookParts())
+	postURL := buildWebhookURL(host, config.Group, config.Tenant, config.AltID, config.GroupOwner)
 
 	res, err := http.Post(postURL, "application/json", bytes.NewBuffer(payload))
 	if err == nil && res.StatusCode != http.StatusOK {
diff --git a/pkg/services/teams/teams_config.go b/pkg/services/teams/teams_config.go
index c0e5e2c7..c47a420b 100644
--- a/pkg/services/teams/teams_config.go
+++ b/pkg/services/teams/teams_config.go
@@ -114,14 +114,21 @@ func (config *Config) setFromWebhookParts(parts [4]string) {
 	config.GroupOwner = parts[3]
 }
 
-func buildWebhookURL(host string, parts [4]string) string {
+func buildWebhookURL(host, group, tenant, altID, groupOwner string) string {
+	// config.Group, config.Tenant, config.AltID, config.GroupOwner
+	path := Path
+	if host == LegacyHost {
+		path = LegacyPath
+	}
 	return fmt.Sprintf(
-		"https://%s/webhook/%s@%s/IncomingWebhook/%s/%s",
+		"https://%s/%s/%s@%s/%s/%s/%s",
 		host,
-		parts[0],
-		parts[1],
-		parts[2],
-		parts[3])
+		path,
+		group,
+		tenant,
+		ProviderName,
+		altID,
+		groupOwner)
 }
 
 func parseAndVerifyWebhookURL(webhookURL string) (parts [4]string, err error) {
@@ -142,6 +149,12 @@ func parseAndVerifyWebhookURL(webhookURL string) (parts [4]string, err error) {
 const (
 	// Scheme is the identifying part of this service's configuration URL
 	Scheme = "teams"
-	// DefaultHost is the default host for the webhook request
-	DefaultHost = "outlook.office.com"
+	// LegacyHost is the default host for legacy webhook requests
+	LegacyHost = "outlook.office.com"
+	// LegacyPath is the initial path of the webhook URL for legacy webhook requests
+	LegacyPath = "webhook"
+	// Path is the initial path of the webhook URL for domain-scoped webhook requests
+	Path = "webhookb2"
+	// ProviderName is the name of the Teams integration provider
+	ProviderName = "IncomingWebhook"
 )
diff --git a/pkg/services/teams/teams_test.go b/pkg/services/teams/teams_test.go
index 48241e51..a3e3d22b 100644
--- a/pkg/services/teams/teams_test.go
+++ b/pkg/services/teams/teams_test.go
@@ -12,9 +12,11 @@ import (
 )
 
 const (
-	testWebhookURL = "https://outlook.office.com/webhook/11111111-4444-4444-8444-cccccccccccc@22222222-4444-4444-8444-cccccccccccc/IncomingWebhook/33333333012222222222333333333344/44444444-4444-4444-8444-cccccccccccc"
-	customURL      = "teams+https://publicservice.info/webhook/11111111-4444-4444-8444-cccccccccccc@22222222-4444-4444-8444-cccccccccccc/IncomingWebhook/33333333012222222222333333333344/44444444-4444-4444-8444-cccccccccccc"
-	testURLBase    = "teams://11111111-4444-4444-8444-cccccccccccc@22222222-4444-4444-8444-cccccccccccc/33333333012222222222333333333344/44444444-4444-4444-8444-cccccccccccc"
+	legacyWebhookURL = "https://outlook.office.com/webhook/11111111-4444-4444-8444-cccccccccccc@22222222-4444-4444-8444-cccccccccccc/IncomingWebhook/33333333012222222222333333333344/44444444-4444-4444-8444-cccccccccccc"
+	scopedWebhookURL = "https://test.webhook.office.com/webhookb2/11111111-4444-4444-8444-cccccccccccc@22222222-4444-4444-8444-cccccccccccc/IncomingWebhook/33333333012222222222333333333344/44444444-4444-4444-8444-cccccccccccc"
+	scopedDomainHost = "test.webhook.office.com"
+	testURLBase      = "teams://11111111-4444-4444-8444-cccccccccccc@22222222-4444-4444-8444-cccccccccccc/33333333012222222222333333333344/44444444-4444-4444-8444-cccccccccccc"
+	scopedURLBase    = testURLBase + `?host=` + scopedDomainHost
 )
 
 var logger = log.New(GinkgoWriter, "Test", log.LstdFlags)
@@ -24,9 +26,9 @@ func TestTeams(t *testing.T) {
 	RunSpecs(t, "Shoutrrr Teams Suite")
 }
 
-var _ = Describe("the teams plugin", func() {
+var _ = Describe("the teams service", func() {
 	When("creating the webhook URL", func() {
-		It("should match the expected output", func() {
+		It("should match the expected output for legacy URLs", func() {
 			config := Config{}
 			config.setFromWebhookParts([4]string{
 				"11111111-4444-4444-8444-cccccccccccc",
@@ -34,8 +36,23 @@ var _ = Describe("the teams plugin", func() {
 				"33333333012222222222333333333344",
 				"44444444-4444-4444-8444-cccccccccccc",
 			})
-			apiURL := buildWebhookURL(DefaultHost, config.webhookParts())
-			Expect(apiURL).To(Equal(testWebhookURL))
+			apiURL := buildWebhookURL(LegacyHost, config.Group, config.Tenant, config.AltID, config.GroupOwner)
+			Expect(apiURL).To(Equal(legacyWebhookURL))
+
+			parts, err := parseAndVerifyWebhookURL(apiURL)
+			Expect(err).ToNot(HaveOccurred())
+			Expect(parts).To(Equal(config.webhookParts()))
+		})
+		It("should match the expected output for custom URLs", func() {
+			config := Config{}
+			config.setFromWebhookParts([4]string{
+				"11111111-4444-4444-8444-cccccccccccc",
+				"22222222-4444-4444-8444-cccccccccccc",
+				"33333333012222222222333333333344",
+				"44444444-4444-4444-8444-cccccccccccc",
+			})
+			apiURL := buildWebhookURL(scopedDomainHost, config.Group, config.Tenant, config.AltID, config.GroupOwner)
+			Expect(apiURL).To(Equal(scopedWebhookURL))
 
 			parts, err := parseAndVerifyWebhookURL(apiURL)
 			Expect(err).ToNot(HaveOccurred())
@@ -46,18 +63,17 @@ var _ = Describe("the teams plugin", func() {
 	Describe("creating a config", func() {
 		When("parsing the configuration URL", func() {
 			It("should be identical after de-/serialization", func() {
-				testURL := testURLBase + "?color=aabbcc&host=notdefault.outlook.office.com&title=Test+title"
+				testURL := testURLBase + "?color=aabbcc&host=test.outlook.office.com&title=Test+title"
 
 				url, err := url.Parse(testURL)
 				Expect(err).NotTo(HaveOccurred(), "parsing")
 
-				config := &Config{Host: DefaultHost}
+				config := &Config{Host: LegacyHost}
 				err = config.SetURL(url)
 				Expect(err).NotTo(HaveOccurred(), "verifying")
 
 				outputURL := config.GetURL()
 				Expect(outputURL.String()).To(Equal(testURL))
-
 			})
 		})
 	})
@@ -78,7 +94,7 @@ var _ = Describe("the teams plugin", func() {
 		When("a valid custom URL is provided", func() {
 			It("should set the host field from the custom URL", func() {
 				service := Service{}
-				testURL := customURL
+				testURL := `teams+` + scopedWebhookURL
 
 				customURL, err := url.Parse(testURL)
 				Expect(err).NotTo(HaveOccurred(), "parsing")
@@ -86,11 +102,11 @@ var _ = Describe("the teams plugin", func() {
 				serviceURL, err := service.GetConfigURLFromCustom(customURL)
 				Expect(err).NotTo(HaveOccurred(), "converting")
 
-				Expect(serviceURL.String()).To(Equal(testURLBase + "?host=publicservice.info"))
+				Expect(serviceURL.String()).To(Equal(scopedURLBase))
 			})
 			It("should preserve the query params in the generated service URL", func() {
 				service := Service{}
-				testURL := "teams+" + testWebhookURL + "?color=f008c1&title=TheTitle"
+				testURL := "teams+" + legacyWebhookURL + "?color=f008c1&title=TheTitle"
 
 				customURL, err := url.Parse(testURL)
 				Expect(err).NotTo(HaveOccurred(), "parsing")
@@ -113,11 +129,11 @@ var _ = Describe("the teams plugin", func() {
 			httpmock.DeactivateAndReset()
 		})
 		It("should not report an error if the server accepts the payload", func() {
-			serviceURL, _ := url.Parse(testURLBase)
+			serviceURL, _ := url.Parse(scopedURLBase)
 			err = service.Initialize(serviceURL, logger)
 			Expect(err).NotTo(HaveOccurred())
 
-			httpmock.RegisterResponder("POST", testWebhookURL, httpmock.NewStringResponder(200, ""))
+			httpmock.RegisterResponder("POST", scopedWebhookURL, httpmock.NewStringResponder(200, ""))
 
 			err = service.Send("Message", nil)
 			Expect(err).NotTo(HaveOccurred())
@@ -127,7 +143,7 @@ var _ = Describe("the teams plugin", func() {
 			err = service.Initialize(serviceURL, logger)
 			Expect(err).NotTo(HaveOccurred())
 
-			httpmock.RegisterResponder("POST", testWebhookURL, httpmock.NewErrorResponder(errors.New("dummy error")))
+			httpmock.RegisterResponder("POST", legacyWebhookURL, httpmock.NewErrorResponder(errors.New("dummy error")))
 
 			err = service.Send("Message", nil)
 			Expect(err).To(HaveOccurred())
diff --git a/pkg/util/docs.go b/pkg/util/docs.go
new file mode 100644
index 00000000..2d137e1a
--- /dev/null
+++ b/pkg/util/docs.go
@@ -0,0 +1,17 @@
+package util
+
+import (
+	"fmt"
+
+	"github.com/containrrr/shoutrrr/internal/meta"
+)
+
+// DocsURL returns a full documentation URL for the current version of Shoutrrr with the path appended.
+// If the path contains a leading slash, it is stripped.
+func DocsURL(path string) string {
+	// strip leading slash if present
+	if len(path) > 0 && path[0] == '/' {
+		path = path[1:]
+	}
+	return fmt.Sprintf("https://containrrr.dev/shoutrrr/%s/%s", meta.DocsVersion, path)
+}
diff --git a/pkg/util/partition_message_test.go b/pkg/util/partition_message_test.go
index fb0ace3a..e3201616 100644
--- a/pkg/util/partition_message_test.go
+++ b/pkg/util/partition_message_test.go
@@ -118,14 +118,10 @@ func testPartitionMessage(hundreds int, limits types.MessageLimit, distance int)
 
 	items, omitted = PartitionMessage(builder.String(), limits, distance)
 
-	println(hundreds, len(items), omitted)
-
 	contentSize := Min(hundreds*100, limits.TotalChunkSize)
 	expectedChunkCount := CeilDiv(contentSize, limits.ChunkSize-1)
 	expectedOmitted := Max(0, (hundreds*100)-contentSize)
 
-	println(contentSize, expectedChunkCount, expectedOmitted)
-
 	Expect(omitted).To(Equal(expectedOmitted))
 	Expect(len(items)).To(Equal(expectedChunkCount))
 
diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go
index f789a913..34f58b4c 100644
--- a/pkg/util/util_test.go
+++ b/pkg/util/util_test.go
@@ -1,12 +1,14 @@
 package util_test
 
 import (
+	"fmt"
 	"reflect"
 	"testing"
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
+	"github.com/containrrr/shoutrrr/internal/meta"
 	. "github.com/containrrr/shoutrrr/pkg/util"
 )
 
@@ -91,4 +93,15 @@ var _ = Describe("the util package", func() {
 			Expect(IsNumeric(reflect.TypeOf("3").Kind())).To(BeFalse())
 		})
 	})
+
+	When("calling function DocsURL", func() {
+		It("should return the expected URL", func() {
+			expectedBase := fmt.Sprintf(`https://containrrr.dev/shoutrrr/%s/`, meta.DocsVersion)
+			Expect(DocsURL(``)).To(Equal(expectedBase))
+			Expect(DocsURL(`services/logger`)).To(Equal(expectedBase + `services/logger`))
+		})
+		It("should strip the leading slash from the path", func() {
+			Expect(DocsURL(`/foo`)).To(Equal(DocsURL(`foo`)))
+		})
+	})
 })
diff --git a/shoutrrr.go b/shoutrrr.go
index 8e005409..30dd897b 100644
--- a/shoutrrr.go
+++ b/shoutrrr.go
@@ -1,6 +1,7 @@
 package shoutrrr
 
 import (
+	"github.com/containrrr/shoutrrr/internal/meta"
 	"github.com/containrrr/shoutrrr/pkg/router"
 	"github.com/containrrr/shoutrrr/pkg/types"
 )
@@ -32,3 +33,8 @@ func CreateSender(rawURLs ...string) (*router.ServiceRouter, error) {
 func NewSender(logger types.StdLogger, serviceURLs ...string) (*router.ServiceRouter, error) {
 	return router.New(logger, serviceURLs...)
 }
+
+// Version returns the shoutrrr version
+func Version() string {
+	return meta.Version
+}