diff --git a/pkg/delivery/mocks/Delivery.go b/pkg/delivery/mocks/Delivery.go
new file mode 100644
index 0000000000000000000000000000000000000000..5cd13757a86e0ee7cf7c3180053e65299558178a
--- /dev/null
+++ b/pkg/delivery/mocks/Delivery.go
@@ -0,0 +1,200 @@
+// Code generated by mockery v2.7.4. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	collections "git.perx.ru/perxis/perxis-go/pkg/collections"
+	environments "git.perx.ru/perxis/perxis-go/pkg/environments"
+	items "git.perx.ru/perxis/perxis-go/pkg/items"
+	locales "git.perx.ru/perxis/perxis-go/pkg/locales"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// Delivery is an autogenerated mock type for the Delivery type
+type Delivery struct {
+	mock.Mock
+}
+
+// FindItems provides a mock function with given fields: ctx, spaceId, envId, collectionId, filter, options
+func (_m *Delivery) FindItems(ctx context.Context, spaceId string, envId string, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) ([]*items.Item, int, error) {
+	_va := make([]interface{}, len(options))
+	for _i := range options {
+		_va[_i] = options[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, spaceId, envId, collectionId, filter)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 []*items.Item
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, *items.Filter, ...*items.FindPublishedOptions) []*items.Item); ok {
+		r0 = rf(ctx, spaceId, envId, collectionId, filter, options...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]*items.Item)
+		}
+	}
+
+	var r1 int
+	if rf, ok := ret.Get(1).(func(context.Context, string, string, string, *items.Filter, ...*items.FindPublishedOptions) int); ok {
+		r1 = rf(ctx, spaceId, envId, collectionId, filter, options...)
+	} else {
+		r1 = ret.Get(1).(int)
+	}
+
+	var r2 error
+	if rf, ok := ret.Get(2).(func(context.Context, string, string, string, *items.Filter, ...*items.FindPublishedOptions) error); ok {
+		r2 = rf(ctx, spaceId, envId, collectionId, filter, options...)
+	} else {
+		r2 = ret.Error(2)
+	}
+
+	return r0, r1, r2
+}
+
+// GetCollection provides a mock function with given fields: ctx, spaceId, envId, collectionId
+func (_m *Delivery) GetCollection(ctx context.Context, spaceId string, envId string, collectionId string) (*collections.Collection, error) {
+	ret := _m.Called(ctx, spaceId, envId, collectionId)
+
+	var r0 *collections.Collection
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) *collections.Collection); ok {
+		r0 = rf(ctx, spaceId, envId, collectionId)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*collections.Collection)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok {
+		r1 = rf(ctx, spaceId, envId, collectionId)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetEnvironment provides a mock function with given fields: ctx, spaceId, envId
+func (_m *Delivery) GetEnvironment(ctx context.Context, spaceId string, envId string) (*environments.Environment, error) {
+	ret := _m.Called(ctx, spaceId, envId)
+
+	var r0 *environments.Environment
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) *environments.Environment); ok {
+		r0 = rf(ctx, spaceId, envId)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*environments.Environment)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
+		r1 = rf(ctx, spaceId, envId)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// GetItem provides a mock function with given fields: ctx, spaceId, envId, collectionId, itemId, options
+func (_m *Delivery) GetItem(ctx context.Context, spaceId string, envId string, collectionId string, itemId string, options ...*items.GetPublishedOptions) (*items.Item, error) {
+	_va := make([]interface{}, len(options))
+	for _i := range options {
+		_va[_i] = options[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, spaceId, envId, collectionId, itemId)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *items.Item
+	if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, ...*items.GetPublishedOptions) *items.Item); ok {
+		r0 = rf(ctx, spaceId, envId, collectionId, itemId, options...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*items.Item)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string, ...*items.GetPublishedOptions) error); ok {
+		r1 = rf(ctx, spaceId, envId, collectionId, itemId, options...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListCollections provides a mock function with given fields: ctx, spaceId, envId
+func (_m *Delivery) ListCollections(ctx context.Context, spaceId string, envId string) ([]*collections.Collection, error) {
+	ret := _m.Called(ctx, spaceId, envId)
+
+	var r0 []*collections.Collection
+	if rf, ok := ret.Get(0).(func(context.Context, string, string) []*collections.Collection); ok {
+		r0 = rf(ctx, spaceId, envId)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]*collections.Collection)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
+		r1 = rf(ctx, spaceId, envId)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListEnvironments provides a mock function with given fields: ctx, spaceId
+func (_m *Delivery) ListEnvironments(ctx context.Context, spaceId string) ([]*environments.Environment, error) {
+	ret := _m.Called(ctx, spaceId)
+
+	var r0 []*environments.Environment
+	if rf, ok := ret.Get(0).(func(context.Context, string) []*environments.Environment); ok {
+		r0 = rf(ctx, spaceId)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]*environments.Environment)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+		r1 = rf(ctx, spaceId)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// ListLocales provides a mock function with given fields: ctx, spaceId
+func (_m *Delivery) ListLocales(ctx context.Context, spaceId string) ([]*locales.Locale, error) {
+	ret := _m.Called(ctx, spaceId)
+
+	var r0 []*locales.Locale
+	if rf, ok := ret.Get(0).(func(context.Context, string) []*locales.Locale); ok {
+		r0 = rf(ctx, spaceId)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]*locales.Locale)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
+		r1 = rf(ctx, spaceId)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
diff --git a/pkg/delivery/service.go b/pkg/delivery/service.go
new file mode 100644
index 0000000000000000000000000000000000000000..9f084740499a5d620d158c4ef97555d4ed5acca6
--- /dev/null
+++ b/pkg/delivery/service.go
@@ -0,0 +1,28 @@
+package delivery
+
+import (
+	"context"
+
+	"git.perx.ru/perxis/perxis-go/pkg/collections"
+	"git.perx.ru/perxis/perxis-go/pkg/environments"
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/locales"
+)
+
+// @microgen grpc
+// @protobuf git.perx.ru/perxis/perxis-go/proto/delivery
+// @grpc-addr delivery.Delivery
+type Delivery interface {
+	ListLocales(ctx context.Context, spaceId string) (locales []*locales.Locale, err error)
+
+	GetEnvironment(ctx context.Context, spaceId, envId string) (env *environments.Environment, err error)
+	ListEnvironments(ctx context.Context, spaceId string) (envs []*environments.Environment, err error)
+
+	GetCollection(ctx context.Context, spaceId, envId, collectionId string) (collection *collections.Collection, err error)
+	ListCollections(ctx context.Context, spaceId, envId string) (collections []*collections.Collection, err error)
+
+	GetItem(ctx context.Context, spaceId, envId, collectionId, itemId string, options ...*items.GetPublishedOptions) (item *items.Item, err error)
+	FindItems(ctx context.Context, spaceId, envId, collectionId string, filter *items.Filter, options ...*items.FindPublishedOptions) (items []*items.Item, total int, err error)
+
+	Aggregate(ctx context.Context, spaceId, envId, collectionId string, filter *items.Filter, options ...*items.AggregatePublishedOptions) (result map[string]interface{}, err error)
+}
diff --git a/pkg/delivery/transport/client.microgen.go b/pkg/delivery/transport/client.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..8f2e1216f49441cf14afe4fe2fe509ba9898bca9
--- /dev/null
+++ b/pkg/delivery/transport/client.microgen.go
@@ -0,0 +1,139 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	"context"
+	"errors"
+
+	collections "git.perx.ru/perxis/perxis-go/pkg/collections"
+	environments "git.perx.ru/perxis/perxis-go/pkg/environments"
+	items "git.perx.ru/perxis/perxis-go/pkg/items"
+	locales "git.perx.ru/perxis/perxis-go/pkg/locales"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+func (set EndpointsSet) ListLocales(arg0 context.Context, arg1 string) (res0 []*locales.Locale, res1 error) {
+	request := ListLocalesRequest{SpaceId: arg1}
+	response, res1 := set.ListLocalesEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*ListLocalesResponse).Locales, res1
+}
+
+func (set EndpointsSet) GetEnvironment(arg0 context.Context, arg1 string, arg2 string) (res0 *environments.Environment, res1 error) {
+	request := GetEnvironmentRequest{
+		EnvId:   arg2,
+		SpaceId: arg1,
+	}
+	response, res1 := set.GetEnvironmentEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*GetEnvironmentResponse).Env, res1
+}
+
+func (set EndpointsSet) ListEnvironments(arg0 context.Context, arg1 string) (res0 []*environments.Environment, res1 error) {
+	request := ListEnvironmentsRequest{SpaceId: arg1}
+	response, res1 := set.ListEnvironmentsEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*ListEnvironmentsResponse).Envs, res1
+}
+
+func (set EndpointsSet) GetCollection(arg0 context.Context, arg1 string, arg2 string, arg3 string) (res0 *collections.Collection, res1 error) {
+	request := GetCollectionRequest{
+		CollectionId: arg3,
+		EnvId:        arg2,
+		SpaceId:      arg1,
+	}
+	response, res1 := set.GetCollectionEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*GetCollectionResponse).Collection, res1
+}
+
+func (set EndpointsSet) ListCollections(arg0 context.Context, arg1 string, arg2 string) (res0 []*collections.Collection, res1 error) {
+	request := ListCollectionsRequest{
+		EnvId:   arg2,
+		SpaceId: arg1,
+	}
+	response, res1 := set.ListCollectionsEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*ListCollectionsResponse).Collections, res1
+}
+
+func (set EndpointsSet) GetItem(arg0 context.Context, arg1 string, arg2 string, arg3 string, arg4 string, arg5 ...*items.GetPublishedOptions) (res0 *items.Item, res1 error) {
+	request := GetItemRequest{
+		CollectionId: arg3,
+		EnvId:        arg2,
+		ItemId:       arg4,
+		Options:      arg5,
+		SpaceId:      arg1,
+	}
+	response, res1 := set.GetItemEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*GetItemResponse).Item, res1
+}
+
+func (set EndpointsSet) FindItems(arg0 context.Context, arg1 string, arg2 string, arg3 string, arg4 *items.Filter, arg5 ...*items.FindPublishedOptions) (res0 []*items.Item, res1 int, res2 error) {
+	request := FindItemsRequest{
+		CollectionId: arg3,
+		EnvId:        arg2,
+		Filter:       arg4,
+		Options:      arg5,
+		SpaceId:      arg1,
+	}
+	response, res2 := set.FindItemsEndpoint(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.(*FindItemsResponse).Items, response.(*FindItemsResponse).Total, res2
+}
+
+func (set EndpointsSet) Aggregate(arg0 context.Context, arg1 string, arg2 string, arg3 string, arg4 *items.Filter, arg5 ...*items.AggregatePublishedOptions) (res0 map[string]interface{}, res1 error) {
+	request := AggregateRequest{
+		CollectionId: arg3,
+		EnvId:        arg2,
+		Filter:       arg4,
+		Options:      arg5,
+		SpaceId:      arg1,
+	}
+	response, res1 := set.AggregateEndpoint(arg0, &request)
+	if res1 != nil {
+		if e, ok := status.FromError(res1); ok || e.Code() == codes.Internal || e.Code() == codes.Unknown {
+			res1 = errors.New(e.Message())
+		}
+		return
+	}
+	return response.(*AggregateResponse).Result, res1
+}
diff --git a/pkg/delivery/transport/endpoints.microgen.go b/pkg/delivery/transport/endpoints.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..a76d9c168ad5242df0fda62d3ca7f16b324f4ae8
--- /dev/null
+++ b/pkg/delivery/transport/endpoints.microgen.go
@@ -0,0 +1,17 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import endpoint "github.com/go-kit/kit/endpoint"
+
+// EndpointsSet implements Delivery API and used for transport purposes.
+type EndpointsSet struct {
+	ListLocalesEndpoint      endpoint.Endpoint
+	GetEnvironmentEndpoint   endpoint.Endpoint
+	ListEnvironmentsEndpoint endpoint.Endpoint
+	GetCollectionEndpoint    endpoint.Endpoint
+	ListCollectionsEndpoint  endpoint.Endpoint
+	GetItemEndpoint          endpoint.Endpoint
+	FindItemsEndpoint        endpoint.Endpoint
+	AggregateEndpoint        endpoint.Endpoint
+}
diff --git a/pkg/delivery/transport/exchanges.microgen.go b/pkg/delivery/transport/exchanges.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..3e0f4c8958cc3cb58608e4e6676c8c4163a83cd0
--- /dev/null
+++ b/pkg/delivery/transport/exchanges.microgen.go
@@ -0,0 +1,85 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	collections "git.perx.ru/perxis/perxis-go/pkg/collections"
+	environments "git.perx.ru/perxis/perxis-go/pkg/environments"
+	items "git.perx.ru/perxis/perxis-go/pkg/items"
+	locales "git.perx.ru/perxis/perxis-go/pkg/locales"
+)
+
+type (
+	ListLocalesRequest struct {
+		SpaceId string `json:"space_id"`
+	}
+	ListLocalesResponse struct {
+		Locales []*locales.Locale `json:"locales"`
+	}
+
+	GetEnvironmentRequest struct {
+		SpaceId string `json:"space_id"`
+		EnvId   string `json:"env_id"`
+	}
+	GetEnvironmentResponse struct {
+		Env *environments.Environment `json:"env"`
+	}
+
+	ListEnvironmentsRequest struct {
+		SpaceId string `json:"space_id"`
+	}
+	ListEnvironmentsResponse struct {
+		Envs []*environments.Environment `json:"envs"`
+	}
+
+	GetCollectionRequest struct {
+		SpaceId      string `json:"space_id"`
+		EnvId        string `json:"env_id"`
+		CollectionId string `json:"collection_id"`
+	}
+	GetCollectionResponse struct {
+		Collection *collections.Collection `json:"collection"`
+	}
+
+	ListCollectionsRequest struct {
+		SpaceId string `json:"space_id"`
+		EnvId   string `json:"env_id"`
+	}
+	ListCollectionsResponse struct {
+		Collections []*collections.Collection `json:"collections"`
+	}
+
+	GetItemRequest struct {
+		SpaceId      string                       `json:"space_id"`
+		EnvId        string                       `json:"env_id"`
+		CollectionId string                       `json:"collection_id"`
+		ItemId       string                       `json:"item_id"`
+		Options      []*items.GetPublishedOptions `json:"options"` // This field was defined with ellipsis (...).
+	}
+	GetItemResponse struct {
+		Item *items.Item `json:"item"`
+	}
+
+	FindItemsRequest struct {
+		SpaceId      string                        `json:"space_id"`
+		EnvId        string                        `json:"env_id"`
+		CollectionId string                        `json:"collection_id"`
+		Filter       *items.Filter                 `json:"filter"`
+		Options      []*items.FindPublishedOptions `json:"options"` // This field was defined with ellipsis (...).
+	}
+	FindItemsResponse struct {
+		Items []*items.Item `json:"items"`
+		Total int           `json:"total"`
+	}
+
+	AggregateRequest struct {
+		SpaceId      string                             `json:"space_id"`
+		EnvId        string                             `json:"env_id"`
+		CollectionId string                             `json:"collection_id"`
+		Filter       *items.Filter                      `json:"filter"`
+		Options      []*items.AggregatePublishedOptions `json:"options"` // This field was defined with ellipsis (...).
+	}
+	AggregateResponse struct {
+		Result map[string]interface{} `json:"result"`
+	}
+)
diff --git a/pkg/delivery/transport/grpc/client.microgen.go b/pkg/delivery/transport/grpc/client.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..6a038379e065b12934f76e25102d425930ad072d
--- /dev/null
+++ b/pkg/delivery/transport/grpc/client.microgen.go
@@ -0,0 +1,74 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transportgrpc
+
+import (
+	transport "git.perx.ru/perxis/perxis-go/pkg/delivery/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/delivery"
+	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 = "delivery.Delivery"
+	}
+	return transport.EndpointsSet{
+		AggregateEndpoint: grpckit.NewClient(
+			conn, addr, "Aggregate",
+			_Encode_Aggregate_Request,
+			_Decode_Aggregate_Response,
+			pb.AggregateResponse{},
+			opts...,
+		).Endpoint(),
+		FindItemsEndpoint: grpckit.NewClient(
+			conn, addr, "FindItems",
+			_Encode_FindItems_Request,
+			_Decode_FindItems_Response,
+			pb.FindItemsResponse{},
+			opts...,
+		).Endpoint(),
+		GetCollectionEndpoint: grpckit.NewClient(
+			conn, addr, "GetCollection",
+			_Encode_GetCollection_Request,
+			_Decode_GetCollection_Response,
+			pb.GetCollectionResponse{},
+			opts...,
+		).Endpoint(),
+		GetEnvironmentEndpoint: grpckit.NewClient(
+			conn, addr, "GetEnvironment",
+			_Encode_GetEnvironment_Request,
+			_Decode_GetEnvironment_Response,
+			pb.GetEnvironmentResponse{},
+			opts...,
+		).Endpoint(),
+		GetItemEndpoint: grpckit.NewClient(
+			conn, addr, "GetItem",
+			_Encode_GetItem_Request,
+			_Decode_GetItem_Response,
+			pb.GetItemResponse{},
+			opts...,
+		).Endpoint(),
+		ListCollectionsEndpoint: grpckit.NewClient(
+			conn, addr, "ListCollections",
+			_Encode_ListCollections_Request,
+			_Decode_ListCollections_Response,
+			pb.ListCollectionsResponse{},
+			opts...,
+		).Endpoint(),
+		ListEnvironmentsEndpoint: grpckit.NewClient(
+			conn, addr, "ListEnvironments",
+			_Encode_ListEnvironments_Request,
+			_Decode_ListEnvironments_Response,
+			pb.ListEnvironmentsResponse{},
+			opts...,
+		).Endpoint(),
+		ListLocalesEndpoint: grpckit.NewClient(
+			conn, addr, "ListLocales",
+			_Encode_ListLocales_Request,
+			_Decode_ListLocales_Response,
+			pb.ListLocalesResponse{},
+			opts...,
+		).Endpoint(),
+	}
+}
diff --git a/pkg/delivery/transport/grpc/protobuf_endpoint_converters.microgen.go b/pkg/delivery/transport/grpc/protobuf_endpoint_converters.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..83f2869edbd101135a854e1c5a8542ed7ba28a7b
--- /dev/null
+++ b/pkg/delivery/transport/grpc/protobuf_endpoint_converters.microgen.go
@@ -0,0 +1,434 @@
+// 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/delivery/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/delivery"
+)
+
+func _Encode_ListLocales_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil ListLocalesRequest")
+	}
+	req := request.(*transport.ListLocalesRequest)
+	return &pb.ListLocalesRequest{SpaceId: req.SpaceId}, nil
+}
+
+func _Encode_GetEnvironment_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetEnvironmentRequest")
+	}
+	req := request.(*transport.GetEnvironmentRequest)
+	return &pb.GetEnvironmentRequest{
+		EnvId:   req.EnvId,
+		SpaceId: req.SpaceId,
+	}, nil
+}
+
+func _Encode_ListEnvironments_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil ListEnvironmentsRequest")
+	}
+	req := request.(*transport.ListEnvironmentsRequest)
+	return &pb.ListEnvironmentsRequest{SpaceId: req.SpaceId}, nil
+}
+
+func _Encode_GetCollection_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetCollectionRequest")
+	}
+	req := request.(*transport.GetCollectionRequest)
+	return &pb.GetCollectionRequest{
+		CollectionId: req.CollectionId,
+		EnvId:        req.EnvId,
+		SpaceId:      req.SpaceId,
+	}, nil
+}
+
+func _Encode_ListCollections_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil ListCollectionsRequest")
+	}
+	req := request.(*transport.ListCollectionsRequest)
+	return &pb.ListCollectionsRequest{
+		EnvId:   req.EnvId,
+		SpaceId: req.SpaceId,
+	}, nil
+}
+
+func _Encode_GetItem_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetItemRequest")
+	}
+	req := request.(*transport.GetItemRequest)
+	reqOptions, err := ElPtrItemsGetPublishedOptionsToProto(req.Options)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetItemRequest{
+		CollectionId: req.CollectionId,
+		EnvId:        req.EnvId,
+		ItemId:       req.ItemId,
+		SpaceId:      req.SpaceId,
+		Options:      reqOptions,
+	}, nil
+}
+
+func _Encode_FindItems_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil FindItemsRequest")
+	}
+	req := request.(*transport.FindItemsRequest)
+	reqFilter, err := PtrItemsFilterToProto(req.Filter)
+	if err != nil {
+		return nil, err
+	}
+	reqOptions, err := ElPtrItemsFindPublishedOptionsToProto(req.Options)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.FindItemsRequest{
+		CollectionId: req.CollectionId,
+		EnvId:        req.EnvId,
+		Filter:       reqFilter,
+		Options:      reqOptions,
+		SpaceId:      req.SpaceId,
+	}, nil
+}
+
+func _Encode_ListLocales_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil ListLocalesResponse")
+	}
+	resp := response.(*transport.ListLocalesResponse)
+	respLocales, err := ListPtrLocalesLocaleToProto(resp.Locales)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.ListLocalesResponse{Locales: respLocales}, nil
+}
+
+func _Encode_GetEnvironment_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetEnvironmentResponse")
+	}
+	resp := response.(*transport.GetEnvironmentResponse)
+	respEnv, err := PtrEnvironmentsEnvironmentToProto(resp.Env)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetEnvironmentResponse{Env: respEnv}, nil
+}
+
+func _Encode_ListEnvironments_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil ListEnvironmentsResponse")
+	}
+	resp := response.(*transport.ListEnvironmentsResponse)
+	respEnvs, err := ListPtrEnvironmentsEnvironmentToProto(resp.Envs)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.ListEnvironmentsResponse{Envs: respEnvs}, nil
+}
+
+func _Encode_GetCollection_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetCollectionResponse")
+	}
+	resp := response.(*transport.GetCollectionResponse)
+	respCollection, err := PtrCollectionsCollectionToProto(resp.Collection)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetCollectionResponse{Collection: respCollection}, nil
+}
+
+func _Encode_ListCollections_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil ListCollectionsResponse")
+	}
+	resp := response.(*transport.ListCollectionsResponse)
+	respCollections, err := ListPtrCollectionsCollectionToProto(resp.Collections)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.ListCollectionsResponse{Collections: respCollections}, nil
+}
+
+func _Encode_GetItem_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetItemResponse")
+	}
+	resp := response.(*transport.GetItemResponse)
+	respItem, err := PtrItemsItemToProto(resp.Item)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.GetItemResponse{Item: respItem}, nil
+}
+
+func _Encode_FindItems_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil FindItemsResponse")
+	}
+	resp := response.(*transport.FindItemsResponse)
+	respItem, err := ListPtrItemsItemToProto(resp.Items)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.FindItemsResponse{
+		Items: respItem,
+		Total: int32(resp.Total),
+	}, nil
+}
+
+func _Decode_ListLocales_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil ListLocalesRequest")
+	}
+	req := request.(*pb.ListLocalesRequest)
+	return &transport.ListLocalesRequest{SpaceId: string(req.SpaceId)}, nil
+}
+
+func _Decode_GetEnvironment_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetEnvironmentRequest")
+	}
+	req := request.(*pb.GetEnvironmentRequest)
+	return &transport.GetEnvironmentRequest{
+		EnvId:   string(req.EnvId),
+		SpaceId: string(req.SpaceId),
+	}, nil
+}
+
+func _Decode_ListEnvironments_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil ListEnvironmentsRequest")
+	}
+	req := request.(*pb.ListEnvironmentsRequest)
+	return &transport.ListEnvironmentsRequest{SpaceId: string(req.SpaceId)}, nil
+}
+
+func _Decode_GetCollection_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetCollectionRequest")
+	}
+	req := request.(*pb.GetCollectionRequest)
+	return &transport.GetCollectionRequest{
+		CollectionId: string(req.CollectionId),
+		EnvId:        string(req.EnvId),
+		SpaceId:      string(req.SpaceId),
+	}, nil
+}
+
+func _Decode_ListCollections_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil ListCollectionsRequest")
+	}
+	req := request.(*pb.ListCollectionsRequest)
+	return &transport.ListCollectionsRequest{
+		EnvId:   string(req.EnvId),
+		SpaceId: string(req.SpaceId),
+	}, nil
+}
+
+func _Decode_GetItem_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil GetItemRequest")
+	}
+	req := request.(*pb.GetItemRequest)
+	reqOptions, err := ProtoToElPtrItemsGetPublishedOptions(req.Options)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetItemRequest{
+		CollectionId: string(req.CollectionId),
+		EnvId:        string(req.EnvId),
+		ItemId:       string(req.ItemId),
+		SpaceId:      string(req.SpaceId),
+		Options:      reqOptions,
+	}, nil
+}
+
+func _Decode_FindItems_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil FindItemsRequest")
+	}
+	req := request.(*pb.FindItemsRequest)
+	reqFilter, err := ProtoToPtrItemsFilter(req.Filter)
+	if err != nil {
+		return nil, err
+	}
+	reqOptions, err := ProtoToElPtrItemsFindPublishedOptions(req.Options)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.FindItemsRequest{
+		CollectionId: string(req.CollectionId),
+		EnvId:        string(req.EnvId),
+		Filter:       reqFilter,
+		Options:      reqOptions,
+		SpaceId:      string(req.SpaceId),
+	}, nil
+}
+
+func _Decode_ListLocales_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil ListLocalesResponse")
+	}
+	resp := response.(*pb.ListLocalesResponse)
+	respLocales, err := ProtoToListPtrLocalesLocale(resp.Locales)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.ListLocalesResponse{Locales: respLocales}, nil
+}
+
+func _Decode_GetEnvironment_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetEnvironmentResponse")
+	}
+	resp := response.(*pb.GetEnvironmentResponse)
+	respEnv, err := ProtoToPtrEnvironmentsEnvironment(resp.Env)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetEnvironmentResponse{Env: respEnv}, nil
+}
+
+func _Decode_ListEnvironments_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil ListEnvironmentsResponse")
+	}
+	resp := response.(*pb.ListEnvironmentsResponse)
+	respEnvs, err := ProtoToListPtrEnvironmentsEnvironment(resp.Envs)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.ListEnvironmentsResponse{Envs: respEnvs}, nil
+}
+
+func _Decode_GetCollection_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetCollectionResponse")
+	}
+	resp := response.(*pb.GetCollectionResponse)
+	respCollection, err := ProtoToPtrCollectionsCollection(resp.Collection)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetCollectionResponse{Collection: respCollection}, nil
+}
+
+func _Decode_ListCollections_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil ListCollectionsResponse")
+	}
+	resp := response.(*pb.ListCollectionsResponse)
+	respCollections, err := ProtoToListPtrCollectionsCollection(resp.Collections)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.ListCollectionsResponse{Collections: respCollections}, nil
+}
+
+func _Decode_GetItem_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil GetItemResponse")
+	}
+	resp := response.(*pb.GetItemResponse)
+	respItem, err := ProtoToPtrItemsItem(resp.Item)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.GetItemResponse{Item: respItem}, nil
+}
+
+func _Decode_FindItems_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil FindItemsResponse")
+	}
+	resp := response.(*pb.FindItemsResponse)
+	respItem, err := ProtoToListPtrItemsItem(resp.Items)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.FindItemsResponse{
+		Items: respItem,
+		Total: int(resp.Total),
+	}, nil
+}
+
+func _Encode_Aggregate_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil AggregateRequest")
+	}
+	req := request.(*transport.AggregateRequest)
+	reqFilter, err := PtrItemsFilterToProto(req.Filter)
+	if err != nil {
+		return nil, err
+	}
+	reqOptions, err := ElPtrItemsAggregateOptionsToProto(req.Options)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.AggregateRequest{
+		CollectionId: req.CollectionId,
+		EnvId:        req.EnvId,
+		Filter:       reqFilter,
+		Options:      reqOptions,
+		SpaceId:      req.SpaceId,
+	}, nil
+}
+
+func _Encode_Aggregate_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil AggregateResponse")
+	}
+	resp := response.(*transport.AggregateResponse)
+	respResult, err := MapStringInterfaceToProto(resp.Result)
+	if err != nil {
+		return nil, err
+	}
+	return &pb.AggregateResponse{Result: respResult}, nil
+}
+
+func _Decode_Aggregate_Request(ctx context.Context, request interface{}) (interface{}, error) {
+	if request == nil {
+		return nil, errors.New("nil AggregateRequest")
+	}
+	req := request.(*pb.AggregateRequest)
+	reqFilter, err := ProtoToPtrItemsFilter(req.Filter)
+	if err != nil {
+		return nil, err
+	}
+	reqOptions, err := ProtoToElPtrItemsAggregateOptions(req.Options)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.AggregateRequest{
+		CollectionId: string(req.CollectionId),
+		EnvId:        string(req.EnvId),
+		Filter:       reqFilter,
+		Options:      reqOptions,
+		SpaceId:      string(req.SpaceId),
+	}, nil
+}
+
+func _Decode_Aggregate_Response(ctx context.Context, response interface{}) (interface{}, error) {
+	if response == nil {
+		return nil, errors.New("nil AggregateResponse")
+	}
+	resp := response.(*pb.AggregateResponse)
+	respResult, err := ProtoToMapStringInterface(resp.Result)
+	if err != nil {
+		return nil, err
+	}
+	return &transport.AggregateResponse{Result: respResult}, nil
+}
diff --git a/pkg/delivery/transport/grpc/protobuf_type_converters.microgen.go b/pkg/delivery/transport/grpc/protobuf_type_converters.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..dbbb951d484c903909bf774295ff1851a30995be
--- /dev/null
+++ b/pkg/delivery/transport/grpc/protobuf_type_converters.microgen.go
@@ -0,0 +1,486 @@
+// 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 (
+	"fmt"
+
+	collections "git.perx.ru/perxis/perxis-go/pkg/collections"
+	environments "git.perx.ru/perxis/perxis-go/pkg/environments"
+	"git.perx.ru/perxis/perxis-go/pkg/filter"
+	items "git.perx.ru/perxis/perxis-go/pkg/items"
+	locales "git.perx.ru/perxis/perxis-go/pkg/locales"
+	services "git.perx.ru/perxis/perxis-go/pkg/options"
+	"git.perx.ru/perxis/perxis-go/pkg/schema"
+	collectionspb "git.perx.ru/perxis/perxis-go/proto/collections"
+	"git.perx.ru/perxis/perxis-go/proto/common"
+	"git.perx.ru/perxis/perxis-go/proto/delivery"
+	environmentspb "git.perx.ru/perxis/perxis-go/proto/environments"
+	itemspb "git.perx.ru/perxis/perxis-go/proto/items"
+	localespb "git.perx.ru/perxis/perxis-go/proto/locales"
+	"github.com/golang/protobuf/ptypes"
+	"google.golang.org/protobuf/types/known/structpb"
+)
+
+func ListPtrLocalesLocaleToProto(locales []*locales.Locale) ([]*localespb.Locale, error) {
+	protoLocales := make([]*localespb.Locale, 0, len(locales))
+	for _, l := range locales {
+		protoLocales = append(protoLocales, &localespb.Locale{Id: l.ID, Name: l.Name, SpaceId: l.SpaceID})
+	}
+	return protoLocales, nil
+}
+
+func ProtoToListPtrLocalesLocale(protoLocales []*localespb.Locale) ([]*locales.Locale, error) {
+	ls := make([]*locales.Locale, 0, len(protoLocales))
+	for _, pl := range protoLocales {
+		ls = append(ls, &locales.Locale{ID: pl.Id, Name: pl.Name, SpaceID: pl.SpaceId})
+	}
+	return ls, nil
+}
+
+func PtrEnvironmentsEnvironmentToProto(env *environments.Environment) (*environmentspb.Environment, error) {
+	if env == nil {
+		return nil, nil
+	}
+	protoEnvironment := &environmentspb.Environment{
+		Id:          env.ID,
+		SpaceId:     env.SpaceID,
+		Description: env.Description,
+		Aliases:     env.Aliases,
+	}
+	if env.StateInfo != nil {
+		protoEnvironment.StateInfo = &environmentspb.StateInfo{
+			State: environmentspb.StateInfo_State(env.StateInfo.State),
+			Info:  env.StateInfo.Info,
+		}
+		protoEnvironment.StateInfo.StartedAt, _ = ptypes.TimestampProto(env.StateInfo.StartedAt)
+	}
+	if env.Config != nil {
+		protoEnvironment.Config = &environmentspb.Config{
+			SourceId: env.Config.SourceID,
+			Features: env.Config.Features,
+		}
+	}
+	return protoEnvironment, nil
+}
+
+func ProtoToPtrEnvironmentsEnvironment(protoEnv *environmentspb.Environment) (*environments.Environment, error) {
+	if protoEnv == nil {
+		return nil, nil
+	}
+	env := &environments.Environment{
+		ID:          protoEnv.Id,
+		SpaceID:     protoEnv.SpaceId,
+		Description: protoEnv.Description,
+		Aliases:     protoEnv.Aliases,
+	}
+	if protoEnv.StateInfo != nil {
+		env.StateInfo = &environments.StateInfo{
+			State: environments.State(protoEnv.StateInfo.State),
+			Info:  protoEnv.StateInfo.Info,
+		}
+		env.StateInfo.StartedAt, _ = ptypes.Timestamp(protoEnv.StateInfo.StartedAt)
+	}
+	if protoEnv.Config != nil {
+		env.Config = &environments.Config{
+			SourceID: protoEnv.Config.SourceId,
+			Features: protoEnv.Config.Features,
+		}
+	}
+	return env, nil
+}
+
+func ListPtrEnvironmentsEnvironmentToProto(envs []*environments.Environment) ([]*environmentspb.Environment, error) {
+	protoEnvironments := make([]*environmentspb.Environment, 0, len(envs))
+	for _, environment := range envs {
+		protoEnvironment, err := PtrEnvironmentsEnvironmentToProto(environment)
+		if err != nil {
+			return nil, err
+		}
+		protoEnvironments = append(protoEnvironments, protoEnvironment)
+	}
+	return protoEnvironments, nil
+}
+
+func ProtoToListPtrEnvironmentsEnvironment(protoEnvs []*environmentspb.Environment) ([]*environments.Environment, error) {
+	environments := make([]*environments.Environment, 0, len(protoEnvs))
+	for _, protoEnvironment := range protoEnvs {
+		environment, err := ProtoToPtrEnvironmentsEnvironment(protoEnvironment)
+		if err != nil {
+			return nil, err
+		}
+		environments = append(environments, environment)
+	}
+	return environments, nil
+}
+
+func PtrCollectionsCollectionToProto(collection *collections.Collection) (*collectionspb.Collection, error) {
+	if collection == nil {
+		return nil, nil
+	}
+	protoCollection := &collectionspb.Collection{
+		Id:      collection.ID,
+		SpaceId: collection.SpaceID,
+		EnvId:   collection.EnvID,
+		Name:    collection.Name,
+		Single:  collection.Single,
+		System:  collection.System,
+	}
+	if collection.Schema != nil {
+		b, err := collection.Schema.MarshalJSON()
+		if err != nil {
+			return nil, err
+		}
+		protoCollection.Schema = string(b)
+	}
+	return protoCollection, nil
+}
+
+func ProtoToPtrCollectionsCollection(protoCollection *collectionspb.Collection) (*collections.Collection, error) {
+	if protoCollection == nil {
+		return nil, nil
+	}
+	collection := &collections.Collection{
+		ID:      protoCollection.Id,
+		SpaceID: protoCollection.SpaceId,
+		EnvID:   protoCollection.EnvId,
+		Name:    protoCollection.Name,
+		Single:  protoCollection.Single,
+		System:  protoCollection.System,
+	}
+	if protoCollection.Schema != "" {
+		sch := schema.New()
+		err := sch.UnmarshalJSON([]byte(protoCollection.Schema))
+		if err != nil {
+			return nil, fmt.Errorf("failed to decode schema. err: %s", err.Error())
+		}
+		collection.Schema = sch
+	}
+	return collection, nil
+}
+
+func ListPtrCollectionsCollectionToProto(collections []*collections.Collection) ([]*collectionspb.Collection, error) {
+	protoCollections := make([]*collectionspb.Collection, 0, len(collections))
+	for _, collection := range collections {
+		protoCollection, err := PtrCollectionsCollectionToProto(collection)
+		if err != nil {
+			return nil, err
+		}
+		protoCollections = append(protoCollections, protoCollection)
+	}
+	return protoCollections, nil
+}
+
+func ProtoToListPtrCollectionsCollection(protoCollections []*collectionspb.Collection) ([]*collections.Collection, error) {
+	collections := make([]*collections.Collection, 0, len(protoCollections))
+	for _, protoCollection := range protoCollections {
+		collection, err := ProtoToPtrCollectionsCollection(protoCollection)
+		if err != nil {
+			return nil, err
+		}
+		collections = append(collections, collection)
+	}
+	return collections, nil
+}
+
+func PtrItemsItemToProto(item *items.Item) (*itemspb.Item, error) {
+	if item == nil {
+		return nil, nil
+	}
+
+	protoItem := &itemspb.Item{
+		Id:           item.ID,
+		SpaceId:      item.SpaceID,
+		EnvId:        item.EnvID,
+		CollectionId: item.CollectionID,
+		State:        itemspb.Item_State(item.State),
+		CreatedBy:    item.CreatedBy,
+		UpdatedBy:    item.UpdatedBy,
+		RevisionId:   item.RevisionID,
+		PublishedBy:  item.PublishedBy,
+		ArchivedBy:   item.ArchivedBy,
+		Locale:       item.Locale,
+		//Hidden, Template, Deleted - не передается для delivery
+	}
+
+	var err error
+	protoItem.Data, err = MapStringInterfaceToProto(item.Data)
+	if err != nil {
+		return nil, err
+	}
+	protoItem.Translations, err = MapStringMapStringInterfaceToProto(item.Translations)
+	if err != nil {
+		return nil, err
+	}
+	//protoItem.Permissions - не передается для delivery
+
+	protoItem.CreatedRevAt, _ = ptypes.TimestampProto(item.CreatedRevAt)
+	protoItem.PublishedAt, _ = ptypes.TimestampProto(item.PublishedAt)
+	protoItem.ArchivedAt, _ = ptypes.TimestampProto(item.ArchivedAt)
+	protoItem.CreatedAt, _ = ptypes.TimestampProto(item.CreatedAt)
+	protoItem.UpdatedAt, _ = ptypes.TimestampProto(item.UpdatedAt)
+
+	return protoItem, nil
+}
+
+func ProtoToPtrItemsItem(protoItem *itemspb.Item) (*items.Item, error) {
+	if protoItem == nil {
+		return nil, nil
+	}
+
+	item := &items.Item{
+		ID:           protoItem.Id,
+		SpaceID:      protoItem.SpaceId,
+		EnvID:        protoItem.EnvId,
+		CollectionID: protoItem.CollectionId,
+		State:        items.State(protoItem.State),
+		CreatedBy:    protoItem.CreatedBy,
+		UpdatedBy:    protoItem.UpdatedBy,
+		RevisionID:   protoItem.RevisionId,
+		PublishedBy:  protoItem.PublishedBy,
+		ArchivedBy:   protoItem.ArchivedBy,
+		Locale:       protoItem.Locale,
+		//Hidden, Template, Deleted - не передается для delivery
+	}
+
+	item.Data, _ = ProtoToMapStringInterface(protoItem.Data)
+	item.Translations, _ = ProtoToMapStringMapStringInterface(protoItem.Translations)
+	//item.Permissions - не передается для delivery
+
+	item.CreatedRevAt, _ = ptypes.Timestamp(protoItem.CreatedRevAt)
+	item.PublishedAt, _ = ptypes.Timestamp(protoItem.PublishedAt)
+	item.ArchivedAt, _ = ptypes.Timestamp(protoItem.ArchivedAt)
+	item.CreatedAt, _ = ptypes.Timestamp(protoItem.CreatedAt)
+	item.UpdatedAt, _ = ptypes.Timestamp(protoItem.UpdatedAt)
+
+	return item, nil
+}
+
+func PtrItemsFilterToProto(filter *items.Filter) (*itemspb.Filter, error) {
+	if filter == nil {
+		return nil, nil
+	}
+
+	dt := make([]*common.Filter, 0, len(filter.Data))
+	for _, f := range filter.Data {
+		pf := &common.Filter{
+			Op:    string(f.Op),
+			Field: f.Field,
+		}
+
+		val, err := structpb.NewValue(f.Value)
+		if err != nil {
+			return nil, err
+		}
+		pf.Value = val
+		dt = append(dt, pf)
+	}
+
+	return &itemspb.Filter{
+		Id:   filter.ID,
+		Data: dt,
+		Q:    filter.Q,
+	}, nil
+}
+
+func ProtoToPtrItemsFilter(protoFilter *itemspb.Filter) (*items.Filter, error) {
+	if protoFilter == nil {
+		return nil, nil
+	}
+
+	dt := make([]*filter.Filter, 0, len(protoFilter.Data))
+	for _, pf := range protoFilter.Data {
+
+		f := &filter.Filter{
+			Op:    filter.Op(pf.Op),
+			Field: pf.Field,
+			Value: pf.Value.AsInterface(),
+		}
+
+		dt = append(dt, f)
+	}
+
+	return &items.Filter{
+		ID:   protoFilter.Id,
+		Data: dt,
+		Q:    protoFilter.Q,
+	}, nil
+}
+
+func PtrServicesFindOptionsToProto(options *services.FindOptions) (*common.FindOptions, error) {
+	if options == nil {
+		return nil, nil
+	}
+	return &common.FindOptions{
+		Sort:     options.Sort,
+		PageNum:  int32(options.PageNum),
+		PageSize: int32(options.PageSize),
+	}, nil
+}
+
+func ProtoToPtrServicesFindOptions(protoOptions *common.FindOptions) (*services.FindOptions, error) {
+	if protoOptions == nil {
+		return nil, nil
+	}
+	return &services.FindOptions{
+		SortOptions: services.SortOptions{
+			Sort: protoOptions.Sort,
+		},
+		PaginationOptions: services.PaginationOptions{
+			PageNum:  int(protoOptions.PageNum),
+			PageSize: int(protoOptions.PageSize),
+		},
+	}, nil
+}
+
+func ListPtrItemsItemToProto(itms []*items.Item) ([]*itemspb.Item, error) {
+	protoItems := make([]*itemspb.Item, 0, len(itms))
+	for _, itm := range itms {
+		pi, err := PtrItemsItemToProto(itm)
+		if err != nil {
+			return nil, err
+		}
+		protoItems = append(protoItems, pi)
+	}
+	return protoItems, nil
+}
+
+func ProtoToListPtrItemsItem(protoItems []*itemspb.Item) ([]*items.Item, error) {
+	items := make([]*items.Item, 0, len(protoItems))
+	for _, itm := range protoItems {
+		pi, err := ProtoToPtrItemsItem(itm)
+		if err != nil {
+			return nil, err
+		}
+		items = append(items, pi)
+	}
+	return items, nil
+}
+
+func MapStringInterfaceToProto(data map[string]interface{}) (*structpb.Struct, error) {
+	if data == nil {
+		return nil, nil
+	}
+	return structpb.NewStruct(data)
+}
+
+func ProtoToMapStringInterface(protoData *structpb.Struct) (map[string]interface{}, error) {
+	if protoData == nil {
+		return nil, nil
+	}
+	return protoData.AsMap(), nil
+}
+
+func MapStringMapStringInterfaceToProto(translations map[string]map[string]interface{}) (map[string]*structpb.Struct, error) {
+	if translations == nil {
+		return nil, nil
+	}
+	res := make(map[string]*structpb.Struct, len(translations))
+	for k, v := range translations {
+		res[k], _ = MapStringInterfaceToProto(v)
+	}
+	return res, nil
+}
+
+func ProtoToMapStringMapStringInterface(protoTranslations map[string]*structpb.Struct) (map[string]map[string]interface{}, error) {
+	if protoTranslations == nil {
+		return nil, nil
+	}
+	res := make(map[string]map[string]interface{}, len(protoTranslations))
+	for k, v := range protoTranslations {
+		res[k], _ = ProtoToMapStringInterface(v)
+	}
+	return res, nil
+}
+
+func ElPtrItemsGetPublishedOptionsToProto(options []*items.GetPublishedOptions) (*itemspb.GetPublishedOptions, error) {
+	if options == nil {
+		return nil, nil
+	}
+
+	opts := items.MergeGetPublishedOptions(options...)
+
+	return &itemspb.GetPublishedOptions{LocaleId: opts.LocaleID}, nil
+}
+
+func ProtoToElPtrItemsGetPublishedOptions(protoOptions *itemspb.GetPublishedOptions) ([]*items.GetPublishedOptions, error) {
+	if protoOptions == nil {
+		return nil, nil
+	}
+
+	return []*items.GetPublishedOptions{{LocaleID: protoOptions.LocaleId}}, nil
+}
+
+func ElPtrItemsFindPublishedOptionsToProto(options []*items.FindPublishedOptions) (*itemspb.FindPublishedOptions, error) {
+	if options == nil {
+		return nil, nil
+	}
+
+	opts := items.MergeFindPublishedOptions(options...)
+
+	var err error
+
+	fo := &itemspb.FindPublishedOptions{}
+
+	fo.Options, err = PtrServicesFindOptionsToProto(&opts.FindOptions)
+	if err != nil {
+		return nil, err
+	}
+
+	fo.LocaleId = opts.LocaleID
+
+	return fo, nil
+}
+
+func ProtoToElPtrItemsFindPublishedOptions(protoOptions *itemspb.FindPublishedOptions) ([]*items.FindPublishedOptions, error) {
+	if protoOptions == nil {
+		return nil, nil
+	}
+
+	var err error
+	fo := &items.FindPublishedOptions{}
+
+	o, err := ProtoToPtrServicesFindOptions(protoOptions.Options)
+	if err != nil {
+		return nil, err
+	}
+	if o != nil {
+		fo.FindOptions = *o
+	}
+
+	fo.LocaleID = protoOptions.LocaleId
+
+	return []*items.FindPublishedOptions{fo}, nil
+}
+
+func PtrServicesAggregateOptionsToProto(options *items.AggregatePublishedOptions) (*delivery.AggregateOptions, error) {
+	if options == nil {
+		return nil, nil
+	}
+	return &delivery.AggregateOptions{Fields: options.Fields}, nil
+}
+
+func ProtoToPtrServicesAggregateOptions(protoOptions *delivery.AggregateOptions) ([]*items.AggregatePublishedOptions, error) {
+	if protoOptions == nil {
+		return nil, nil
+	}
+	return []*items.AggregatePublishedOptions{&items.AggregatePublishedOptions{Fields: protoOptions.Fields}}, nil
+}
+
+func ElPtrItemsAggregateOptionsToProto(options []*items.AggregatePublishedOptions) (*delivery.AggregateOptions, error) {
+	if options == nil {
+		return nil, nil
+	}
+
+	opts := items.MergeAggregatePublishedOptions(options...)
+	return PtrServicesAggregateOptionsToProto(opts)
+}
+
+func ProtoToElPtrItemsAggregateOptions(protoOptions *delivery.AggregateOptions) ([]*items.AggregatePublishedOptions, error) {
+	if protoOptions == nil {
+		return nil, nil
+	}
+	return []*items.AggregatePublishedOptions{&items.AggregatePublishedOptions{Fields: protoOptions.Fields}}, nil
+}
diff --git a/pkg/delivery/transport/grpc/server.microgen.go b/pkg/delivery/transport/grpc/server.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..d815b136f2218cafecf4fac406d35d1ca6464aa5
--- /dev/null
+++ b/pkg/delivery/transport/grpc/server.microgen.go
@@ -0,0 +1,142 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+// DO NOT EDIT.
+package transportgrpc
+
+import (
+	transport "git.perx.ru/perxis/perxis-go/pkg/delivery/transport"
+	pb "git.perx.ru/perxis/perxis-go/proto/delivery"
+	grpc "github.com/go-kit/kit/transport/grpc"
+	context "golang.org/x/net/context"
+)
+
+type deliveryServer struct {
+	listLocales        grpc.Handler
+	getEnvironment     grpc.Handler
+	listEnvironments   grpc.Handler
+	getCollection      grpc.Handler
+	listCollections    grpc.Handler
+	getItem            grpc.Handler
+	findItems          grpc.Handler
+	aggregate          grpc.Handler
+	aggregatePublished grpc.Handler
+
+	pb.UnimplementedDeliveryServer
+}
+
+func NewGRPCServer(endpoints *transport.EndpointsSet, opts ...grpc.ServerOption) pb.DeliveryServer {
+	return &deliveryServer{
+		aggregate: grpc.NewServer(
+			endpoints.AggregateEndpoint,
+			_Decode_Aggregate_Request,
+			_Encode_Aggregate_Response,
+			opts...,
+		),
+		findItems: grpc.NewServer(
+			endpoints.FindItemsEndpoint,
+			_Decode_FindItems_Request,
+			_Encode_FindItems_Response,
+			opts...,
+		),
+		getCollection: grpc.NewServer(
+			endpoints.GetCollectionEndpoint,
+			_Decode_GetCollection_Request,
+			_Encode_GetCollection_Response,
+			opts...,
+		),
+		getEnvironment: grpc.NewServer(
+			endpoints.GetEnvironmentEndpoint,
+			_Decode_GetEnvironment_Request,
+			_Encode_GetEnvironment_Response,
+			opts...,
+		),
+		getItem: grpc.NewServer(
+			endpoints.GetItemEndpoint,
+			_Decode_GetItem_Request,
+			_Encode_GetItem_Response,
+			opts...,
+		),
+		listCollections: grpc.NewServer(
+			endpoints.ListCollectionsEndpoint,
+			_Decode_ListCollections_Request,
+			_Encode_ListCollections_Response,
+			opts...,
+		),
+		listEnvironments: grpc.NewServer(
+			endpoints.ListEnvironmentsEndpoint,
+			_Decode_ListEnvironments_Request,
+			_Encode_ListEnvironments_Response,
+			opts...,
+		),
+		listLocales: grpc.NewServer(
+			endpoints.ListLocalesEndpoint,
+			_Decode_ListLocales_Request,
+			_Encode_ListLocales_Response,
+			opts...,
+		),
+	}
+}
+
+func (S *deliveryServer) ListLocales(ctx context.Context, req *pb.ListLocalesRequest) (*pb.ListLocalesResponse, error) {
+	_, resp, err := S.listLocales.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.ListLocalesResponse), nil
+}
+
+func (S *deliveryServer) GetEnvironment(ctx context.Context, req *pb.GetEnvironmentRequest) (*pb.GetEnvironmentResponse, error) {
+	_, resp, err := S.getEnvironment.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.GetEnvironmentResponse), nil
+}
+
+func (S *deliveryServer) ListEnvironments(ctx context.Context, req *pb.ListEnvironmentsRequest) (*pb.ListEnvironmentsResponse, error) {
+	_, resp, err := S.listEnvironments.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.ListEnvironmentsResponse), nil
+}
+
+func (S *deliveryServer) GetCollection(ctx context.Context, req *pb.GetCollectionRequest) (*pb.GetCollectionResponse, error) {
+	_, resp, err := S.getCollection.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.GetCollectionResponse), nil
+}
+
+func (S *deliveryServer) ListCollections(ctx context.Context, req *pb.ListCollectionsRequest) (*pb.ListCollectionsResponse, error) {
+	_, resp, err := S.listCollections.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.ListCollectionsResponse), nil
+}
+
+func (S *deliveryServer) GetItem(ctx context.Context, req *pb.GetItemRequest) (*pb.GetItemResponse, error) {
+	_, resp, err := S.getItem.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.GetItemResponse), nil
+}
+
+func (S *deliveryServer) FindItems(ctx context.Context, req *pb.FindItemsRequest) (*pb.FindItemsResponse, error) {
+	_, resp, err := S.findItems.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.FindItemsResponse), nil
+}
+
+func (S *deliveryServer) Aggregate(ctx context.Context, req *pb.AggregateRequest) (*pb.AggregateResponse, error) {
+	_, resp, err := S.aggregate.ServeGRPC(ctx, req)
+	if err != nil {
+		return nil, err
+	}
+	return resp.(*pb.AggregateResponse), nil
+}
diff --git a/pkg/delivery/transport/server.microgen.go b/pkg/delivery/transport/server.microgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..a50b5316226d1b030a5ddfa05a21e1a4044c1ee5
--- /dev/null
+++ b/pkg/delivery/transport/server.microgen.go
@@ -0,0 +1,90 @@
+// Code generated by microgen 0.9.1. DO NOT EDIT.
+
+package transport
+
+import (
+	"context"
+
+	delivery "git.perx.ru/perxis/perxis-go/pkg/delivery"
+	endpoint "github.com/go-kit/kit/endpoint"
+)
+
+func Endpoints(svc delivery.Delivery) EndpointsSet {
+	return EndpointsSet{
+		AggregateEndpoint:        AggregateEndpoint(svc),
+		FindItemsEndpoint:        FindItemsEndpoint(svc),
+		GetCollectionEndpoint:    GetCollectionEndpoint(svc),
+		GetEnvironmentEndpoint:   GetEnvironmentEndpoint(svc),
+		GetItemEndpoint:          GetItemEndpoint(svc),
+		ListCollectionsEndpoint:  ListCollectionsEndpoint(svc),
+		ListEnvironmentsEndpoint: ListEnvironmentsEndpoint(svc),
+		ListLocalesEndpoint:      ListLocalesEndpoint(svc),
+	}
+}
+
+func ListLocalesEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*ListLocalesRequest)
+		res0, res1 := svc.ListLocales(arg0, req.SpaceId)
+		return &ListLocalesResponse{Locales: res0}, res1
+	}
+}
+
+func GetEnvironmentEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*GetEnvironmentRequest)
+		res0, res1 := svc.GetEnvironment(arg0, req.SpaceId, req.EnvId)
+		return &GetEnvironmentResponse{Env: res0}, res1
+	}
+}
+
+func ListEnvironmentsEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*ListEnvironmentsRequest)
+		res0, res1 := svc.ListEnvironments(arg0, req.SpaceId)
+		return &ListEnvironmentsResponse{Envs: res0}, res1
+	}
+}
+
+func GetCollectionEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*GetCollectionRequest)
+		res0, res1 := svc.GetCollection(arg0, req.SpaceId, req.EnvId, req.CollectionId)
+		return &GetCollectionResponse{Collection: res0}, res1
+	}
+}
+
+func ListCollectionsEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*ListCollectionsRequest)
+		res0, res1 := svc.ListCollections(arg0, req.SpaceId, req.EnvId)
+		return &ListCollectionsResponse{Collections: res0}, res1
+	}
+}
+
+func GetItemEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*GetItemRequest)
+		res0, res1 := svc.GetItem(arg0, req.SpaceId, req.EnvId, req.CollectionId, req.ItemId, req.Options...)
+		return &GetItemResponse{Item: res0}, res1
+	}
+}
+
+func FindItemsEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*FindItemsRequest)
+		res0, res1, res2 := svc.FindItems(arg0, req.SpaceId, req.EnvId, req.CollectionId, req.Filter, req.Options...)
+		return &FindItemsResponse{
+			Items: res0,
+			Total: res1,
+		}, res2
+	}
+}
+
+func AggregateEndpoint(svc delivery.Delivery) endpoint.Endpoint {
+	return func(arg0 context.Context, request interface{}) (interface{}, error) {
+		req := request.(*AggregateRequest)
+		res0, res1 := svc.Aggregate(arg0, req.SpaceId, req.EnvId, req.CollectionId, req.Filter, req.Options...)
+		return &AggregateResponse{Result: res0}, res1
+	}
+}