diff --git a/pkg/references/field.go b/pkg/references/field.go
new file mode 100644
index 0000000000000000000000000000000000000000..c98ed2298150e012545d55d5364f62c4f44eac1b
--- /dev/null
+++ b/pkg/references/field.go
@@ -0,0 +1,143 @@
+package references
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+
+	"git.perx.ru/perxis/perxis-go/pkg/data"
+	"git.perx.ru/perxis/perxis-go/pkg/errors"
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/schema/field"
+)
+
+const ReferenceTypeName = "reference"
+
+type ReferenceParameters struct {
+	AllowedCollections []string `json:"allowedCollections"`
+}
+
+func (p ReferenceParameters) Type() field.Type { return &ReferenceType{} }
+
+func (p ReferenceParameters) Clone(reset bool) field.Parameters {
+	if p.AllowedCollections != nil {
+		cols := make([]string, 0, len(p.AllowedCollections))
+		for _, c := range p.AllowedCollections {
+			cols = append(cols, c)
+		}
+		p.AllowedCollections = cols
+	}
+	return &p
+}
+
+type ReferenceType struct{}
+
+func NewReferenceType() *ReferenceType {
+	return &ReferenceType{}
+}
+
+func (t ReferenceType) Name() string { return ReferenceTypeName }
+
+func (t *ReferenceType) NewParameters() field.Parameters {
+	return &ReferenceParameters{}
+}
+
+func (t ReferenceType) Decode(_ context.Context, fld *field.Field, v interface{}) (interface{}, error) {
+	if v == nil {
+		return nil, nil
+	}
+
+	r, ok := v.(map[string]interface{})
+	if !ok {
+		return nil, errors.Errorf("ReferenceField decode error: incorrect type: \"%s\", expected \"map[string]interface{}\"", reflect.ValueOf(v).Kind())
+	}
+	id, ok1 := r["id"].(string)
+	if !ok1 || id == "" {
+		return nil, errors.Errorf("ReferenceField decode error: field \"id\" required")
+	}
+	collID, ok2 := r["collection_id"].(string)
+	if !ok2 || collID == "" {
+		return nil, errors.Errorf("ReferenceField decode error: field \"collection_id\" required")
+	}
+	disabled, _ := r["disabled"].(bool)
+
+	return &Reference{ID: id, CollectionID: collID, Disabled: disabled}, nil
+}
+
+func (t ReferenceType) Encode(_ context.Context, fld *field.Field, v interface{}) (interface{}, error) {
+	if v == nil {
+		return nil, nil
+	}
+
+	val, ok := v.(*Reference)
+
+	if !ok {
+		return nil, errors.Errorf("ReferenceField encode error: incorrect type: \"%s\", expected \"*Reference\"", reflect.ValueOf(v).Kind())
+	}
+	if val == nil {
+		return nil, nil
+	}
+	ref := map[string]interface{}{
+		"id":            val.ID,
+		"collection_id": val.CollectionID,
+		"disabled":      val.Disabled,
+	}
+	return ref, nil
+}
+
+func (t *ReferenceType) PreSave(ctx context.Context, f *field.Field, v interface{}, itemCtx *items.Context) (interface{}, bool, error) {
+	params, ok := f.Params.(*ReferenceParameters)
+	if !ok {
+		return nil, false, errors.New("field parameters required")
+	}
+
+	if v == nil {
+		return nil, false, nil
+	}
+	ref, ok := v.(*Reference)
+	if !ok {
+		return nil, false, fmt.Errorf("ReferenceField presave error: incorrect type: \"%s\", expected \"*Reference\"", reflect.ValueOf(v).Kind())
+	}
+
+	// Проверка на наличие ссылок заданных типов
+	if len(params.AllowedCollections) > 0 {
+		ok := false
+		for _, allowed := range params.AllowedCollections {
+
+			if data.GlobMatch(ref.CollectionID, allowed) {
+				ok = true
+				break
+			}
+		}
+		if !ok {
+			return nil, false, errors.Errorf("usage of collection \"%s\" not allowed", ref.CollectionID)
+		}
+	}
+
+	return ref, false, nil
+}
+
+// Field - создает новое поле Field типа ReferenceType
+// ReferenceType должен быть предварительно создан через `NewReferenceType` и зарегистрирован `field.Register`
+func Field(allowedColls []string, o ...interface{}) *field.Field {
+	_, ok := field.GetType(ReferenceTypeName)
+	if !ok {
+		panic("field reference type not registered")
+	}
+
+	return field.NewField(&ReferenceParameters{AllowedCollections: allowedColls}, o...)
+}
+
+func (t *ReferenceType) IsEmpty(v interface{}) bool {
+	if v == nil {
+		return true
+	}
+
+	ref, ok := v.(*Reference)
+
+	return !ok || ref.ID == "" && ref.CollectionID == ""
+}
+
+func init() {
+	field.Register(NewReferenceType())
+}
diff --git a/pkg/references/field_test.go b/pkg/references/field_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a51cb2ac65a3483cbe58169421734f17b6dce20c
--- /dev/null
+++ b/pkg/references/field_test.go
@@ -0,0 +1,300 @@
+package references
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"testing"
+
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/items/mocks"
+	"git.perx.ru/perxis/perxis-go/pkg/schema"
+	"git.perx.ru/perxis/perxis-go/pkg/schema/field"
+	"git.perx.ru/perxis/perxis-go/pkg/schema/validate"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+func TestReferenceField_Decode(t *testing.T) {
+
+	tests := []struct {
+		name    string
+		field   *field.Field
+		data    interface{}
+		want    interface{}
+		wantErr bool
+	}{
+		{
+			"Correct",
+			Field(nil),
+			map[string]interface{}{"collection_id": "media", "id": "11111111"},
+			&Reference{ID: "11111111", CollectionID: "media"},
+			false,
+		},
+		{
+			"Invalid CollectionID",
+			Field(nil),
+			map[string]interface{}{"collection_id": "media", "id": 11111111},
+			"decode error: ReferenceField decode error: field \"id\" required",
+			true,
+		},
+		{
+			"Extra Field",
+			Field(nil),
+			map[string]interface{}{"collection_id": "media", "id": "11111111", "extra": true},
+			&Reference{ID: "11111111", CollectionID: "media"},
+			false,
+		},
+		{
+			"Enabled",
+			Field(nil),
+			map[string]interface{}{"collection_id": "media", "id": "11111111", "disabled": true},
+			&Reference{ID: "11111111", CollectionID: "media", Disabled: true},
+			false,
+		},
+		{
+			"Disabled",
+			Field(nil),
+			map[string]interface{}{"collection_id": "media", "id": "11111111", "disabled": false},
+			&Reference{ID: "11111111", CollectionID: "media", Disabled: false},
+			false,
+		},
+		{
+			"Disabled wrong type",
+			Field(nil),
+			map[string]interface{}{"collection_id": "media", "id": "11111111", "disabled": 3},
+			&Reference{ID: "11111111", CollectionID: "media", Disabled: false},
+			false,
+		},
+		{
+			"Missing Field",
+			Field(nil),
+			map[string]interface{}{"id": "11111111"},
+			"decode error: ReferenceField decode error: field \"collection_id\" required",
+			true,
+		},
+		{
+			"Invalid type",
+			Field(nil),
+			"string",
+			"decode error: ReferenceField decode error: incorrect type: \"string\", expected \"map[string]interface{}\"",
+			true,
+		},
+		{
+			"Invalid  element type",
+			Field(nil),
+			[]interface{}{"string"},
+			"decode error: ReferenceField decode error: incorrect type: \"slice\", expected \"map[string]interface{}\"",
+			true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := schema.Decode(nil, tt.field, tt.data)
+			if tt.wantErr {
+				require.Error(t, err)
+				assert.EqualError(t, err, tt.want.(string), fmt.Sprintf("Decode() error = %v, want %v", err, tt.want.(string)))
+			}
+			if !tt.wantErr {
+				require.NoError(t, err)
+				assert.Equal(t, got, tt.want, fmt.Sprintf("Decode() got = %v, want %v", got, tt.want))
+			}
+		})
+	}
+}
+
+func TestReferenceField_Encode(t *testing.T) {
+
+	tests := []struct {
+		name    string
+		field   *field.Field
+		data    interface{}
+		want    interface{}
+		wantErr bool
+	}{
+		{
+			"Correct",
+			Field(nil),
+			&Reference{ID: "11111111", CollectionID: "media"},
+			map[string]interface{}{"collection_id": "media", "id": "11111111", "disabled": false},
+			false,
+		},
+		{
+			"Enabled",
+			Field(nil),
+			&Reference{ID: "11111111", CollectionID: "media", Disabled: true},
+			map[string]interface{}{"collection_id": "media", "id": "11111111", "disabled": true},
+			false,
+		},
+		{
+			"Disabled",
+			Field(nil),
+			&Reference{ID: "11111111", CollectionID: "media", Disabled: false},
+			map[string]interface{}{"collection_id": "media", "id": "11111111", "disabled": false},
+			false,
+		},
+		{
+			"From Map",
+			Field(nil),
+			map[string]interface{}{"id": "11111111", "collection_id": "media"},
+			"encode error: ReferenceField encode error: incorrect type: \"map\", expected \"*Reference\"",
+			true,
+		},
+		{
+			"Invalid type",
+			Field(nil),
+			"string",
+			"encode error: ReferenceField encode error: incorrect type: \"string\", expected \"*Reference\"",
+			true,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := schema.Encode(nil, tt.field, tt.data)
+			if tt.wantErr {
+				require.Error(t, err)
+				assert.EqualError(t, err, tt.want.(string), fmt.Sprintf("Encode() error = %v, want %v", err, tt.want.(string)))
+			}
+			if !tt.wantErr {
+				require.NoError(t, err)
+				assert.Equal(t, got, tt.want, fmt.Sprintf("Encode() got = %v, want %v", got, tt.want))
+			}
+		})
+	}
+}
+
+func TestReferenceField_PreSave(t *testing.T) {
+	ctx := context.Background()
+	rt := NewReferenceType()
+
+	t.Run("Nil Value", func(t *testing.T) {
+		svc := &mocks.Items{}
+		itemCtx := &items.Context{Items: svc, SpaceID: "sp", EnvID: "env"}
+		f := Field(nil)
+		_, _, err := rt.PreSave(ctx, f, nil, itemCtx)
+		require.NoError(t, err)
+		svc.AssertExpectations(t)
+	})
+	t.Run("Nil Context", func(t *testing.T) {
+		svc := &mocks.Items{}
+		f := Field(nil)
+		ref := &Reference{
+			ID: "111", CollectionID: "media",
+		}
+		_, _, err := rt.PreSave(ctx, f, ref, nil)
+		require.NoError(t, err)
+		svc.AssertExpectations(t)
+	})
+	t.Run("Referenced Items Exist", func(t *testing.T) {
+		t.Run("Correct", func(t *testing.T) {
+			svc := &mocks.Items{}
+			itemCtx := &items.Context{Items: svc, SpaceID: "sp", EnvID: "env"}
+
+			f := Field(nil)
+			ref := &Reference{
+				ID: "111", CollectionID: "media",
+			}
+			_, _, err := rt.PreSave(ctx, f, ref, itemCtx)
+			require.NoError(t, err)
+			svc.AssertExpectations(t)
+		})
+		t.Run("Item Not Found", func(t *testing.T) {
+			svc := &mocks.Items{}
+
+			itemCtx := &items.Context{Items: svc, SpaceID: "sp", EnvID: "env"}
+
+			f := Field(nil)
+			ref := &Reference{
+				ID: "111", CollectionID: "media",
+			}
+			_, _, err := rt.PreSave(ctx, f, ref, itemCtx)
+			require.NoError(t, err)
+			svc.AssertExpectations(t)
+		})
+	})
+	t.Run("Allowed Types", func(t *testing.T) {
+		t.Run("Correct", func(t *testing.T) {
+			svc := &mocks.Items{}
+
+			itemCtx := &items.Context{Items: svc, SpaceID: "sp", EnvID: "env"}
+
+			f := Field([]string{"media"})
+
+			ref := &Reference{
+				ID: "111", CollectionID: "media",
+			}
+
+			_, _, err := rt.PreSave(ctx, f, ref, itemCtx)
+			require.NoError(t, err)
+			svc.AssertExpectations(t)
+		})
+		t.Run("Not Allowed", func(t *testing.T) {
+			svc := &mocks.Items{}
+			f := Field([]string{"cars", "motorbikes"})
+			itemCtx := &items.Context{Items: svc, SpaceID: "sp", EnvID: "env"}
+			ref := &Reference{
+				ID: "111", CollectionID: "media",
+			}
+			_, _, err := rt.PreSave(ctx, f, ref, itemCtx)
+			require.Error(t, err)
+			assert.Equal(t, "usage of collection \"media\" not allowed", err.Error())
+			svc.AssertExpectations(t)
+		})
+	})
+}
+
+func TestReferenceField_Validate(t *testing.T) {
+	rt := NewReferenceType()
+	field.Register(rt)
+
+	t.Run("Max Elements", func(t *testing.T) {
+		t.Run("Correct", func(t *testing.T) {
+			f := Field(nil, validate.MaxItems(1))
+			refs := []*Reference{
+				{ID: "111", CollectionID: "media"},
+			}
+			err := validate.Validate(nil, f, refs)
+			require.NoError(t, err)
+		})
+		t.Run("Limit exceeded", func(t *testing.T) {
+			f := Field(nil, validate.MaxItems(1))
+			refs := []*Reference{
+				{ID: "111", CollectionID: "media"},
+				{ID: "222", CollectionID: "media"},
+			}
+			err := validate.Validate(nil, f, refs)
+			require.Error(t, err)
+			require.Contains(t, err.Error(), "validation error: maximum elements number is 1")
+		})
+	})
+	t.Run("Required", func(t *testing.T) {
+		t.Run("Correct", func(t *testing.T) {
+			f := Field(nil, validate.Required())
+			ref := &Reference{ID: "111", CollectionID: "media"}
+			err := validate.Validate(nil, f, ref)
+			require.NoError(t, err)
+		})
+		t.Run("Empty", func(t *testing.T) {
+			f := Field(nil, validate.Required())
+			ref := &Reference{}
+			err := validate.Validate(nil, f, ref)
+			require.Error(t, err)
+			require.Contains(t, err.Error(), "validation error: value is required")
+		})
+	})
+}
+
+func TestReference_JSON(t *testing.T) {
+	fld := Field([]string{"col1"}).AddOptions(validate.MaxItems(2))
+
+	b, err := json.MarshalIndent(fld, "", "  ")
+	require.NoError(t, err)
+
+	res := field.NewField(nil)
+	err = json.Unmarshal(b, res)
+	require.NoError(t, err)
+
+	assert.Equal(t, fld, res)
+}
diff --git a/pkg/references/mocks/References.go b/pkg/references/mocks/References.go
new file mode 100644
index 0000000000000000000000000000000000000000..c1ead2b49f11fd6492e3ce8f9eb5319cf3b208bc
--- /dev/null
+++ b/pkg/references/mocks/References.go
@@ -0,0 +1,63 @@
+// Code generated by mockery v2.14.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	items "git.perx.ru/perxis/perxis-go/pkg/items"
+	references "git.perx.ru/perxis/perxis-go/pkg/references"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// References is an autogenerated mock type for the References type
+type References struct {
+	mock.Mock
+}
+
+// Get provides a mock function with given fields: ctx, spaceId, envId, _a3
+func (_m *References) Get(ctx context.Context, spaceId string, envId string, _a3 []*references.Reference) ([]*items.Item, []*references.Reference, error) {
+	ret := _m.Called(ctx, spaceId, envId, _a3)
+
+	var r0 []*items.Item
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, []*references.Reference) []*items.Item); ok {
+		r0 = rf(ctx, spaceId, envId, _a3)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]*items.Item)
+		}
+	}
+
+	var r1 []*references.Reference
+	if rf, ok := ret.Get(1).(func(context.Context, string, string, []*references.Reference) []*references.Reference); ok {
+		r1 = rf(ctx, spaceId, envId, _a3)
+	} else {
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).([]*references.Reference)
+		}
+	}
+
+	var r2 error
+	if rf, ok := ret.Get(2).(func(context.Context, string, string, []*references.Reference) error); ok {
+		r2 = rf(ctx, spaceId, envId, _a3)
+	} else {
+		r2 = ret.Error(2)
+	}
+
+	return r0, r1, r2
+}
+
+type mockConstructorTestingTNewReferences interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewReferences creates a new instance of References. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewReferences(t mockConstructorTestingTNewReferences) *References {
+	mock := &References{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/pkg/references/reference.go b/pkg/references/reference.go
new file mode 100644
index 0000000000000000000000000000000000000000..163dceb2d6b188a7ebb21bf34dc77c8259c099d8
--- /dev/null
+++ b/pkg/references/reference.go
@@ -0,0 +1,103 @@
+package references
+
+import (
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+	pb "git.perx.ru/perxis/perxis-go/proto/references"
+	"go.mongodb.org/mongo-driver/bson"
+)
+
+type Reference struct {
+	ID           string `json:"id" bson:"id" mapstructure:"id"`
+	CollectionID string `json:"collection_id" bson:"collection_id" mapstructure:"collection_id"`
+	Disabled     bool   `json:"disabled,omitempty" bson:"disabled,omitempty" mapstructure:"disabled"`
+}
+
+func (r *Reference) MarshalBSON() ([]byte, error) {
+	d := bson.D{
+		{"id", r.ID},
+		{"collection_id", r.CollectionID},
+	}
+
+	if r.Disabled {
+		d = append(d, bson.E{Key: "disabled", Value: true})
+	}
+
+	return bson.Marshal(d)
+}
+
+func ReferenceFromPB(refPB *pb.Reference) *Reference {
+	return &Reference{
+		ID:           refPB.Id,
+		CollectionID: refPB.CollectionId,
+		Disabled:     refPB.Disabled,
+	}
+}
+
+func ReferenceFromItem(item *items.Item) *Reference {
+	if item == nil {
+		return nil
+	}
+
+	return &Reference{
+		ID:           item.ID,
+		CollectionID: item.CollectionID,
+	}
+}
+
+func ReferenceToPB(ref *Reference) *pb.Reference {
+	return &pb.Reference{
+		Id:           ref.ID,
+		CollectionId: ref.CollectionID,
+		Disabled:     ref.Disabled,
+	}
+}
+
+func ReferenceListFromPB(listPB []*pb.Reference) []*Reference {
+	list := make([]*Reference, 0, len(listPB))
+	for _, refPB := range listPB {
+		list = append(list, ReferenceFromPB(refPB))
+	}
+	return list
+}
+
+func (r *Reference) String() string {
+	if r == nil {
+		return ""
+	}
+	return r.CollectionID + "." + r.ID
+}
+
+func (r *Reference) Equal(r1 *Reference) bool {
+	return r == r1 || r != nil && r1 != nil && r.CollectionID == r1.CollectionID && r.ID == r1.ID && r.Disabled == r1.Disabled
+}
+
+func EqualArrays(sr1, sr2 []*Reference) bool {
+	if len(sr1) != len(sr2) {
+		return false
+	}
+	for i, r := range sr1 {
+		if !r.Equal(sr2[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+func (r *Reference) IsValid() bool {
+	return r != nil && r.ID != "" && r.CollectionID != "" && !r.Disabled
+}
+
+func (r *Reference) Fetch(i interface{}) interface{} {
+	p, _ := i.(string)
+	switch p {
+	case "id":
+		return r.ID
+	case "collection_id":
+		return r.CollectionID
+	case "disabled":
+		return r.Disabled
+	default:
+		panic("unknown parameter")
+	}
+	return nil
+}
diff --git a/pkg/references/service.go b/pkg/references/service.go
new file mode 100644
index 0000000000000000000000000000000000000000..14e2e8eb6f6eb0558033046840a5e9c2cda7f387
--- /dev/null
+++ b/pkg/references/service.go
@@ -0,0 +1,14 @@
+package references
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+)
+
+// @microgen grpc
+// @protobuf git.perx.ru/perxis/perxis-go/proto/references
+// @grpc-addr content.references.References
+type References interface {
+	Get(ctx context.Context, spaceId, envId string, references []*Reference) (items []*items.Item, notfound []*Reference, err error)
+}
diff --git a/pkg/references/transport/client.microgen.go b/pkg/references/transport/client.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..a79d9192b857e3360087ddae86298e880df93be9
--- /dev/null
+++ b/pkg/references/transport/client.microgen.go
@@ -0,0 +1,29 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	"context"
+	"errors"
+
+	items "git.perx.ru/perxis/perxis-go/pkg/items"
+	references "git.perx.ru/perxis/perxis-go/pkg/references"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+func (set EndpointsSet) Get(arg0 context.Context, arg1 string, arg2 string, arg3 []*references.Reference) (res0 []*items.Item, res1 []*references.Reference, res2 error) {
+	request := GetRequest{
+		EnvId:      arg2,
+		References: arg3,
+		SpaceId:    arg1,
+	}
+	response, res2 := set.GetEndpoint(arg0, &request)
+	if res2 != nil {
+		if e, ok := status.FromError(res2); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res2 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*GetResponse).Items, response.(*GetResponse).Notfound, res2
+}
diff --git a/pkg/references/transport/endpoints.microgen.go b/pkg/references/transport/endpoints.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..737752a45beef781518c38424e8fe8c31ac47d6a
--- /dev/null
+++ b/pkg/references/transport/endpoints.microgen.go
@@ -0,0 +1,10 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import endpoint "github.com/go-kit/kit/endpoint"
+
+// EndpointsSet implements References API and used for transport purposes.
+type EndpointsSet struct {
+	GetEndpoint endpoint.Endpoint
+}
diff --git a/pkg/references/transport/exchanges.microgen.go b/pkg/references/transport/exchanges.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..bd31aa2d3f78b6e0d321eb7ce602501056842d16
--- /dev/null
+++ b/pkg/references/transport/exchanges.microgen.go
@@ -0,0 +1,20 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	items "git.perx.ru/perxis/perxis-go/pkg/items"
+	references "git.perx.ru/perxis/perxis-go/pkg/references"
+)
+
+type (
+	GetRequest struct {
+		SpaceId    string                  `json:"space_id"`
+		EnvId      string                  `json:"env_id"`
+		References []*references.Reference `json:"references"`
+	}
+	GetResponse struct {
+		Items    []*items.Item           `json:"items"`
+		Notfound []*references.Reference `json:"notfound"`
+	}
+)
diff --git a/pkg/references/transport/grpc/client.microgen.go b/pkg/references/transport/grpc/client.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..f475ea9cb27f040fbcdb32a06b8893f7975c46ec
--- /dev/null
+++ b/pkg/references/transport/grpc/client.microgen.go
@@ -0,0 +1,23 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transportgrpc
+
+import (
+	transport "git.perx.ru/perxis/perxis-go/pkg/references/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/references"
+	grpckit "github.com/go-kit/kit/transport/grpc"
+	grpc "google.golang.org/grpc"
+)
+
+func NewGRPCClient(conn *grpc.ClientConn, addr string, opts ...grpckit.ClientOption) transport.EndpointsSet {
+	if addr == "" {
+		addr = "content.references.References"
+	}
+	return transport.EndpointsSet{GetEndpoint: grpckit.NewClient(
+		conn, addr, "Get",
+		_Encode_Get_Request,
+		_Decode_Get_Response,
+		pb.GetResponse{},
+		opts...,
+	).Endpoint()}
+}
diff --git a/pkg/references/transport/grpc/protobuf_endpoint_converters.microgen.go b/pkg/references/transport/grpc/protobuf_endpoint_converters.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..d47c0574bb55f654778bafac1035fbb6ba018d0d
--- /dev/null
+++ b/pkg/references/transport/grpc/protobuf_endpoint_converters.microgen.go
@@ -0,0 +1,82 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+// Please, do not change functions names!
+package transportgrpc
+
+import (
+	"context"
+	"errors"
+
+	transport "git.perx.ru/perxis/perxis-go/pkg/references/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/references"
+)
+
+func _Encode_Get_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetRequest")
+	}
+	req := request.(*transport.GetRequest)
+	reqReferences, err := ListPtrReferenceToProto(req.References)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetRequest{
+		EnvId:      req.EnvId,
+		References: reqReferences,
+		SpaceId:    req.SpaceId,
+	}, nil
+}
+
+func _Encode_Get_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetResponse")
+	}
+	resp := response.(*transport.GetResponse)
+	respItems, err := ListPtrItemsItemToProto(resp.Items)
+	if err != nil {
+		return nil, err
+	}
+	respNotfound, err := ListPtrReferenceToProto(resp.Notfound)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetResponse{
+		Items:    respItems,
+		Notfound: respNotfound,
+	}, nil
+}
+
+func _Decode_Get_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetRequest")
+	}
+	req := request.(*pb.GetRequest)
+	reqReferences, err := ProtoToListPtrReference(req.References)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetRequest{
+		EnvId:      string(req.EnvId),
+		References: reqReferences,
+		SpaceId:    string(req.SpaceId),
+	}, nil
+}
+
+func _Decode_Get_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetResponse")
+	}
+	resp := response.(*pb.GetResponse)
+	respItems, err := ProtoToListPtrItemsItem(resp.Items)
+	if err != nil {
+		return nil, err
+	}
+	respNotfound, err := ProtoToListPtrReference(resp.Notfound)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetResponse{
+		Items:    respItems,
+		Notfound: respNotfound,
+	}, nil
+}
diff --git a/pkg/references/transport/grpc/protobuf_type_converters.microgen.go b/pkg/references/transport/grpc/protobuf_type_converters.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..549d11725e085c4a35aaa047a2a4b1e9c43355df
--- /dev/null
+++ b/pkg/references/transport/grpc/protobuf_type_converters.microgen.go
@@ -0,0 +1,71 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+// It is better for you if you do not change functions names!
+// This file will never be overwritten.
+package transportgrpc
+
+import (
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+	itemstransportgrpc "git.perx.ru/perxis/perxis-go/pkg/items/transport/grpc"
+	service "git.perx.ru/perxis/perxis-go/pkg/references"
+	itemspb "git.perx.ru/perxis/perxis-go/proto/items"
+	pb "git.perx.ru/perxis/perxis-go/proto/references"
+)
+
+func PtrItemToReference(ref *service.Reference) (*pb.Reference, error) {
+	if ref == nil {
+		return nil, nil
+	}
+
+	protoRef := &pb.Reference{
+		Id:           ref.ID,
+		CollectionId: ref.CollectionID,
+	}
+
+	return protoRef, nil
+}
+
+func ListPtrReferenceToProto(refs []*service.Reference) ([]*pb.Reference, error) {
+	protoRefs := make([]*pb.Reference, 0, len(refs))
+	for _, ref := range refs {
+		pr, err := PtrItemToReference(ref)
+		if err != nil {
+			return nil, err
+		}
+		protoRefs = append(protoRefs, pr)
+	}
+	return protoRefs, nil
+}
+
+func ProtoToPtrReference(protoRef *pb.Reference) (*service.Reference, error) {
+	if protoRef == nil {
+		return nil, nil
+	}
+
+	ref := &service.Reference{
+		ID:           protoRef.Id,
+		CollectionID: protoRef.CollectionId,
+	}
+
+	return ref, nil
+}
+
+func ProtoToListPtrReference(protoRefs []*pb.Reference) ([]*service.Reference, error) {
+	refs := make([]*service.Reference, 0, len(protoRefs))
+	for _, ref := range protoRefs {
+		r, err := ProtoToPtrReference(ref)
+		if err != nil {
+			return nil, err
+		}
+		refs = append(refs, r)
+	}
+	return refs, nil
+}
+
+func ListPtrItemsItemToProto(items []*items.Item) ([]*itemspb.Item, error) {
+	return itemstransportgrpc.ListPtrItemToProto(items)
+}
+
+func ProtoToListPtrItemsItem(protoItems []*itemspb.Item) ([]*items.Item, error) {
+	return itemstransportgrpc.ProtoToListPtrItem(protoItems)
+}
diff --git a/pkg/references/transport/grpc/server.microgen.go b/pkg/references/transport/grpc/server.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..960cf20350072d36498b2bb57edb8c594d193d28
--- /dev/null
+++ b/pkg/references/transport/grpc/server.microgen.go
@@ -0,0 +1,34 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+// DO NOT EDIT.
+package transportgrpc
+
+import (
+	transport "git.perx.ru/perxis/perxis-go/pkg/references/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/references"
+	grpc "github.com/go-kit/kit/transport/grpc"
+	context "golang.org/x/net/context"
+)
+
+type referencesServer struct {
+	get grpc.Handler
+
+	pb.UnsafeReferencesServer
+}
+
+func NewGRPCServer(endpoints *transport.EndpointsSet, opts ...grpc.ServerOption) pb.ReferencesServer {
+	return &referencesServer{get: grpc.NewServer(
+		endpoints.GetEndpoint,
+		_Decode_Get_Request,
+		_Encode_Get_Response,
+		opts...,
+	)}
+}
+
+func (S *referencesServer) Get(ctx context.Context, req *pb.GetRequest) (*pb.GetResponse, error) {
+	_, resp, err := S.get.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.GetResponse), nil
+}
diff --git a/pkg/references/transport/server.microgen.go b/pkg/references/transport/server.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..f66b4c6b4b8ff529bb498f11cec2bfce8f79c2bf
--- /dev/null
+++ b/pkg/references/transport/server.microgen.go
@@ -0,0 +1,25 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	"context"
+
+	references "git.perx.ru/perxis/perxis-go/pkg/references"
+	endpoint "github.com/go-kit/kit/endpoint"
+)
+
+func Endpoints(svc references.References) EndpointsSet {
+	return EndpointsSet{GetEndpoint: GetEndpoint(svc)}
+}
+
+func GetEndpoint(svc references.References) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*GetRequest)
+		res0, res1, res2 := svc.Get(arg0, req.SpaceId, req.EnvId, req.References)
+		return &GetResponse{
+			Items:    res0,
+			Notfound: res1,
+		}, res2
+	}
+}