diff --git a/utils/utils.go b/utils/utils.go
index 19b1b77e37f57bc3c2ad16354bda87ec6401f355..40bf5be0176584e384ddefcffa08af245a60f84d 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -212,6 +212,30 @@ func FormatPhoneNumber(phoneNumber string) string {
 	return phoneNumber
 }
 
+func ValidatePhoneNumber(phoneNumber string) (string, error) {
+	phoneNumber = string_utils.RemoveAllWhiteSpaces(phoneNumber)
+
+	for _, char := range string_utils.NonOfficialWhitespaceChars {
+		phoneNumber = strings.ReplaceAll(phoneNumber, char, "")
+	}
+
+	if phoneNumber == "" {
+		return "", errors.Error("phone number is empty")
+	}
+
+	if !isPhoneNumber(phoneNumber) {
+		return "", errors.Error("phone number is invalid")
+	}
+
+	return phoneNumber, nil
+}
+
+// isPhoneNumber checks if a string is a valid phone number. It only allows numbers and a leading "+". Remove whitespace before calling this function. Note: it does not validate the length of the phone number.
+func isPhoneNumber(phoneNumber string) bool {
+	phoneRegex := regexp.MustCompile(`^\+?[0-9]+$`)
+	return phoneRegex.MatchString(phoneNumber)
+}
+
 func insertInto(s string, index int, characters string) string {
 	return s[:index] + characters + s[index:]
 }
diff --git a/utils/utils_test.go b/utils/utils_test.go
index b1a07699ec800d5f43bea7aef7aef65d843a992d..5eafa56ac391ad979a93c0bb8045010028b61223 100644
--- a/utils/utils_test.go
+++ b/utils/utils_test.go
@@ -146,3 +146,73 @@ func TestValidateIPAddress(t *testing.T) {
 		})
 	}
 }
+
+func TestValidatePhoneNumber(t *testing.T) {
+	tests := []struct {
+		name        string
+		phoneNumber string
+		want        string
+		wantErr     error
+	}{
+		{
+			name:        "Valid phone number with country code",
+			phoneNumber: "+27123456789",
+			want:        "+27123456789",
+			wantErr:     nil,
+		},
+		{
+			name:        "Valid phone number with country code and spaces",
+			phoneNumber: " + 271 2345 6789",
+			want:        "+27123456789",
+			wantErr:     nil,
+		},
+		{
+			name:        "Valid phone number without country code",
+			phoneNumber: "0123456789",
+			want:        "0123456789",
+			wantErr:     nil,
+		},
+		{
+			name:        "Phone number with spaces",
+			phoneNumber: "012 345 6789",
+			want:        "0123456789",
+			wantErr:     nil,
+		},
+		{
+			name:        "Phone number with non-official whitespaces",
+			phoneNumber: "012\u00A0345\u00A06789",
+			want:        "0123456789",
+			wantErr:     nil,
+		},
+		{
+			name:        "Empty phone number",
+			phoneNumber: "",
+			want:        "",
+			wantErr:     errors.Error("phone number is empty"),
+		},
+		{
+			name:        "Invalid phone number with letters",
+			phoneNumber: "01234abcde",
+			want:        "",
+			wantErr:     errors.Error("phone number is invalid"),
+		},
+		{
+			name:        "Phone number with special characters",
+			phoneNumber: "01234!@#$%",
+			want:        "",
+			wantErr:     errors.Error("phone number is invalid"),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := ValidatePhoneNumber(tt.phoneNumber)
+			if got != tt.want {
+				t.Errorf("ValidatePhoneNumber() got = %v, want %v", got, tt.want)
+			}
+			if err != nil && err.Error() != tt.wantErr.Error() {
+				t.Errorf("ValidatePhoneNumber() err = %v, want %v", err, tt.wantErr)
+			}
+		})
+	}
+}