diff --git a/pkg/id/id.go b/pkg/id/id.go
index cfb8b6390ac48e50ed5fb899db11316b3f1df31c..2f3a9adda1b3ad0cccd15db8f14881d22533fb24 100644
--- a/pkg/id/id.go
+++ b/pkg/id/id.go
@@ -1,7 +1,52 @@
 package id
 
-import "github.com/rs/xid"
+import (
+	"regexp"
+	"strings"
+
+	"git.perx.ru/perxis/perxis-go/pkg/errors"
+	"github.com/rs/xid"
+)
+
+const (
+	MaxLengthID   = 64
+	MaxLengthName = 256
+)
+
+var (
+	ErrEmptyID    = errors.New("empty id")
+	ErrNotValidID = errors.New("id contains invalid characters")
+	ErrLongID     = errors.Errorf("id too long (max %d symbols)", MaxLengthID)
+	ErrEmptyName  = errors.New("empty name")
+	ErrLongName   = errors.Errorf("name too long (max %d symbols)", MaxLengthName)
+	isValidID     = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9-_]*$`).MatchString
+)
 
 func GenerateNewID() string {
 	return xid.New().String()
 }
+
+func ValidateID(id string) (string, error) {
+	trimmedID := strings.TrimSpace(id)
+	if trimmedID == "" {
+		return trimmedID, ErrEmptyID
+	}
+	if len(trimmedID) > MaxLengthID {
+		return trimmedID, ErrLongID
+	}
+	if !isValidID(trimmedID) {
+		return trimmedID, errors.WithDetail(ErrNotValidID, "must begin with latin letters and contain latin letters, numbers or '-', '_'")
+	}
+	return trimmedID, nil
+}
+
+func ValidateName(name string) (string, error) {
+	trimmedName := strings.TrimSpace(name)
+	if trimmedName == "" {
+		return trimmedName, ErrEmptyName
+	}
+	if len(trimmedName) > MaxLengthName {
+		return trimmedName, ErrLongName
+	}
+	return trimmedName, nil
+}
diff --git a/pkg/id/id_test.go b/pkg/id/id_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..f778e3a9d70b1711d05e983fcc2ac0c43bfd61ff
--- /dev/null
+++ b/pkg/id/id_test.go
@@ -0,0 +1,135 @@
+package id
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestValidateID(t *testing.T) {
+	tests := []struct {
+		name    string
+		id      string
+		result  string
+		wantErr bool
+	}{
+		{
+			"Correct ID #1",
+			"test",
+			"test",
+			false,
+		},
+		{
+			"Correct ID #2",
+			"test_1",
+			"test_1",
+			false,
+		},
+		{
+			"Correct ID #3",
+			"test_1-2",
+			"test_1-2",
+			false,
+		},
+		{
+			"Trimmed ID #1",
+			" test_1-2 ",
+			"test_1-2",
+			false,
+		},
+		{
+			"Trimmed ID #2",
+			"test_1-2 			",
+			"test_1-2",
+			false,
+		},
+		{
+			"Fail, ID starts with number",
+			"1test",
+			"1test",
+			true,
+		},
+		{
+			"Fail, ID to long",
+			"9QoulAlFbIcnQYLSudMistN1IczCWrXUTtN5EgNQJd516DN9UjXYJxieJ1RcsNcs1",
+			"9QoulAlFbIcnQYLSudMistN1IczCWrXUTtN5EgNQJd516DN9UjXYJxieJ1RcsNcs1",
+			true,
+		},
+		{
+			"Fail, ID with symbols",
+			"test!_)(&&",
+			"test!_)(&&",
+			true,
+		},
+		{
+			"Fail, ID is empty",
+			"   ",
+			"",
+			true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			res, err := ValidateID(tt.id)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("ValidateID() error = %v, wantErr %v", err, tt.wantErr)
+			}
+			require.Equal(t, tt.result, res)
+		})
+	}
+}
+
+func TestValidateName(t *testing.T) {
+	tests := []struct {
+		nameTest string
+		name     string
+		result   string
+		wantErr  bool
+	}{
+		{
+			"Correct name #1",
+			"test",
+			"test",
+			false,
+		},
+		{
+			"Correct name #2",
+			"test_1",
+			"test_1",
+			false,
+		},
+		{
+			"Correct name #3",
+			"test_1-2",
+			"test_1-2",
+			false,
+		},
+		{
+			"Trimmed name #1",
+			" test_1-3 ",
+			"test_1-3",
+			false,
+		},
+		{
+			"Trimmed name #2",
+			"test_1234 			",
+			"test_1234",
+			false,
+		},
+		{
+			"Fail, name to long",
+			"ChKRLdvWi0wYYPazuBXrIRtNFy96qGrhBDkuKQNd6N2DPV86IGdXVkeTjWj7qezKreIFUp9IUn03A8WJTTORHkgXAvkPuDVM8tVMcnHbR2hznooJ3gGUsXpn4uXo2QhsviHPyUKmE10GnkCOv9FgAMILNoFVHnIiSHI3cjWlGJglpS9YAMXFB1phOIRF5yol3jmPE7EeU1uZPUw9C2PChuksGsOuJQov07Zom0b13r6wOJv8PZVa4IKmjDDLGKlq1",
+			"ChKRLdvWi0wYYPazuBXrIRtNFy96qGrhBDkuKQNd6N2DPV86IGdXVkeTjWj7qezKreIFUp9IUn03A8WJTTORHkgXAvkPuDVM8tVMcnHbR2hznooJ3gGUsXpn4uXo2QhsviHPyUKmE10GnkCOv9FgAMILNoFVHnIiSHI3cjWlGJglpS9YAMXFB1phOIRF5yol3jmPE7EeU1uZPUw9C2PChuksGsOuJQov07Zom0b13r6wOJv8PZVa4IKmjDDLGKlq1",
+			true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			res, err := ValidateName(tt.name)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("ValidateName() error = %v, wantErr %v", err, tt.wantErr)
+			}
+			require.Equal(t, tt.result, res)
+		})
+	}
+}