diff --git a/README.md b/README.md
index be574f982993bc63ce2f5848ca2b536fbabdb77e..c128eb832b764806b929ed71930a42a8aaf3ee47 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,53 @@
-# Cache
+# Cache service
 
-Cache exposes HTTP interface for working with Redis. 
\ No newline at end of file
+Cache service exposes HTTP interface for working with Redis.
+
+### Basic Architecture
+
+```mermaid
+flowchart LR
+   A[Client] -- request --> B[Cache Service] --> C[(Redis)]
+```
+
+### API Documentation
+
+The API Documentation is accessible at `/swagger-ui` path in OAS 3.0 format.
+Example: `http://localhost:8080/swagger-ui`
+
+### Dependencies
+
+There must be a running instance of [Redis](https://redis.io/) visible to the service.
+The address, username and password of the Redis in-memory store instance must be provided as environment variables.
+
+Example:
+```
+REDIS_ADDR="localhost:6379"
+REDIS_USER="user"
+REDIS_PASS="pass"
+```
+
+### Development
+
+This service uses [Goa framework](https://goa.design/) v3 as a backbone. [This](https://goa.design/learn/getting-started/) is a good starting point for learning to use the framework.
+
+### Dependencies and Vendor
+
+The project uses Go modules for managing dependencies and we commit the `vendor` directory.
+When you add/change dependencies, be sure to clean and update the `vendor` directory before
+submitting your Merge Request for review.
+```shell
+go mod tidy
+go mod vendor
+```
+
+### Tests and Linters
+
+To execute the units tests for the service go to the root project directory and run:
+```go
+go test -race ./...
+```
+
+To run the linters go to the root project directory and run:
+```go
+golangci-lint run
+```
diff --git a/design/design.go b/design/design.go
index 0617832a38b93fa17411bdfbb53bd60df6dd43c0..df4c8c84acb64044fe38b34e5487573297d43302 100644
--- a/design/design.go
+++ b/design/design.go
@@ -41,10 +41,10 @@ var _ = Service("cache", func() {
 	Description("Cache service allows storing and retrieving data from distributed cache.")
 
 	Method("Get", func() {
-		Description("Get value from the cache. The result is a sequence of bytes which the client must decode.")
+		Description("Get JSON value from the cache.")
 
 		Payload(CacheGetRequest)
-		Result(Bytes)
+		Result(Any)
 
 		HTTP(func() {
 			GET("/v1/cache")
@@ -59,7 +59,33 @@ var _ = Service("cache", func() {
 				Example("administration")
 			})
 
-			Response(StatusOK)
+			Response(StatusOK, func() {
+				ContentType("application/json")
+			})
+		})
+	})
+
+	Method("Set", func() {
+		Description("Set a JSON value in the cache.")
+
+		Payload(CacheSetRequest)
+		Result(Empty)
+
+		HTTP(func() {
+			POST("/v1/cache")
+
+			Header("key:x-cache-key", String, "Cache entry key", func() {
+				Example("did:web:example.com")
+			})
+			Header("namespace:x-cache-namespace", String, "Cache entry namespace", func() {
+				Example("Login")
+			})
+			Header("scope:x-cache-scope", String, "Cache entry scope", func() {
+				Example("administration")
+			})
+			Body("data")
+
+			Response(StatusCreated)
 		})
 	})
 })
diff --git a/design/types.go b/design/types.go
index 57789a4b12ab9bf0bfb4dd467668d950e784e2a6..3ea641e275ca9fed03207bd7d3e052865ae005c3 100644
--- a/design/types.go
+++ b/design/types.go
@@ -9,3 +9,11 @@ var CacheGetRequest = Type("CacheGetRequest", func() {
 	Field(3, "scope", String) // Initial implementation with a single scope
 	Required("key", "namespace", "scope")
 })
+
+var CacheSetRequest = Type("CacheSetRequest", func() {
+	Field(1, "data", Any)
+	Field(2, "key", String)
+	Field(3, "namespace", String)
+	Field(4, "scope", String) // Initial implementation with a single scope
+	Required("data", "key", "namespace", "scope")
+})
diff --git a/gen/cache/client.go b/gen/cache/client.go
index ec6218557a4ad5ef34f1a76161238b1105677603..d076c91f9ce19b9aa45fb2e4abeaa45e808603c3 100644
--- a/gen/cache/client.go
+++ b/gen/cache/client.go
@@ -16,21 +16,29 @@ import (
 // Client is the "cache" service client.
 type Client struct {
 	GetEndpoint goa.Endpoint
+	SetEndpoint goa.Endpoint
 }
 
 // NewClient initializes a "cache" service client given the endpoints.
-func NewClient(get goa.Endpoint) *Client {
+func NewClient(get, set goa.Endpoint) *Client {
 	return &Client{
 		GetEndpoint: get,
+		SetEndpoint: set,
 	}
 }
 
 // Get calls the "Get" endpoint of the "cache" service.
-func (c *Client) Get(ctx context.Context, p *CacheGetRequest) (res []byte, err error) {
+func (c *Client) Get(ctx context.Context, p *CacheGetRequest) (res interface{}, err error) {
 	var ires interface{}
 	ires, err = c.GetEndpoint(ctx, p)
 	if err != nil {
 		return
 	}
-	return ires.([]byte), nil
+	return ires.(interface{}), nil
+}
+
+// Set calls the "Set" endpoint of the "cache" service.
+func (c *Client) Set(ctx context.Context, p *CacheSetRequest) (err error) {
+	_, err = c.SetEndpoint(ctx, p)
+	return
 }
diff --git a/gen/cache/endpoints.go b/gen/cache/endpoints.go
index 4dfb7f41650a6bc82b6317a2aea05fba34d967b2..c3d44cb790448204680ba0f060701a6bfffede4c 100644
--- a/gen/cache/endpoints.go
+++ b/gen/cache/endpoints.go
@@ -16,18 +16,21 @@ import (
 // Endpoints wraps the "cache" service endpoints.
 type Endpoints struct {
 	Get goa.Endpoint
+	Set goa.Endpoint
 }
 
 // NewEndpoints wraps the methods of the "cache" service with endpoints.
 func NewEndpoints(s Service) *Endpoints {
 	return &Endpoints{
 		Get: NewGetEndpoint(s),
+		Set: NewSetEndpoint(s),
 	}
 }
 
 // Use applies the given middleware to all the "cache" service endpoints.
 func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) {
 	e.Get = m(e.Get)
+	e.Set = m(e.Set)
 }
 
 // NewGetEndpoint returns an endpoint function that calls the method "Get" of
@@ -38,3 +41,12 @@ func NewGetEndpoint(s Service) goa.Endpoint {
 		return s.Get(ctx, p)
 	}
 }
+
+// NewSetEndpoint returns an endpoint function that calls the method "Set" of
+// service "cache".
+func NewSetEndpoint(s Service) goa.Endpoint {
+	return func(ctx context.Context, req interface{}) (interface{}, error) {
+		p := req.(*CacheSetRequest)
+		return nil, s.Set(ctx, p)
+	}
+}
diff --git a/gen/cache/service.go b/gen/cache/service.go
index 089bd94d2623488893a2a0a9a7c2763957b84a0b..ec2b3af1d8b783c03c9ab4e4416a0d1eccac9b28 100644
--- a/gen/cache/service.go
+++ b/gen/cache/service.go
@@ -13,9 +13,10 @@ import (
 
 // Cache service allows storing and retrieving data from distributed cache.
 type Service interface {
-	// Get value from the cache. The result is a sequence of bytes which the client
-	// must decode.
-	Get(context.Context, *CacheGetRequest) (res []byte, err error)
+	// Get JSON value from the cache.
+	Get(context.Context, *CacheGetRequest) (res interface{}, err error)
+	// Set a JSON value in the cache.
+	Set(context.Context, *CacheSetRequest) (err error)
 }
 
 // ServiceName is the name of the service as defined in the design. This is the
@@ -26,7 +27,7 @@ const ServiceName = "cache"
 // MethodNames lists the service method names as defined in the design. These
 // are the same values that are set in the endpoint request contexts under the
 // MethodKey key.
-var MethodNames = [1]string{"Get"}
+var MethodNames = [2]string{"Get", "Set"}
 
 // CacheGetRequest is the payload type of the cache service Get method.
 type CacheGetRequest struct {
@@ -34,3 +35,11 @@ type CacheGetRequest struct {
 	Namespace string
 	Scope     string
 }
+
+// CacheSetRequest is the payload type of the cache service Set method.
+type CacheSetRequest struct {
+	Data      interface{}
+	Key       string
+	Namespace string
+	Scope     string
+}
diff --git a/gen/http/cache/client/cli.go b/gen/http/cache/client/cli.go
index 102424b710f74365e6125b64830218de30980a04..6502a89ae3ee866ac1389db01de6fa73d87081c5 100644
--- a/gen/http/cache/client/cli.go
+++ b/gen/http/cache/client/cli.go
@@ -8,6 +8,9 @@
 package client
 
 import (
+	"encoding/json"
+	"fmt"
+
 	cache "code.vereign.com/gaiax/tsa/cache/gen/cache"
 )
 
@@ -32,3 +35,36 @@ func BuildGetPayload(cacheGetKey string, cacheGetNamespace string, cacheGetScope
 
 	return v, nil
 }
+
+// BuildSetPayload builds the payload for the cache Set endpoint from CLI flags.
+func BuildSetPayload(cacheSetBody string, cacheSetKey string, cacheSetNamespace string, cacheSetScope string) (*cache.CacheSetRequest, error) {
+	var err error
+	var body interface{}
+	{
+		err = json.Unmarshal([]byte(cacheSetBody), &body)
+		if err != nil {
+			return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "\"Quasi ut.\"")
+		}
+	}
+	var key string
+	{
+		key = cacheSetKey
+	}
+	var namespace string
+	{
+		namespace = cacheSetNamespace
+	}
+	var scope string
+	{
+		scope = cacheSetScope
+	}
+	v := body
+	res := &cache.CacheSetRequest{
+		Data: v,
+	}
+	res.Key = key
+	res.Namespace = namespace
+	res.Scope = scope
+
+	return res, nil
+}
diff --git a/gen/http/cache/client/client.go b/gen/http/cache/client/client.go
index a909cf4774e21ad7b49f24881b0b1e2d4321f37b..f813e4412a506fd9efed09bd9b534d490a5b8576 100644
--- a/gen/http/cache/client/client.go
+++ b/gen/http/cache/client/client.go
@@ -20,6 +20,9 @@ type Client struct {
 	// Get Doer is the HTTP client used to make requests to the Get endpoint.
 	GetDoer goahttp.Doer
 
+	// Set Doer is the HTTP client used to make requests to the Set endpoint.
+	SetDoer goahttp.Doer
+
 	// RestoreResponseBody controls whether the response bodies are reset after
 	// decoding so they can be read again.
 	RestoreResponseBody bool
@@ -41,6 +44,7 @@ func NewClient(
 ) *Client {
 	return &Client{
 		GetDoer:             doer,
+		SetDoer:             doer,
 		RestoreResponseBody: restoreBody,
 		scheme:              scheme,
 		host:                host,
@@ -72,3 +76,27 @@ func (c *Client) Get() goa.Endpoint {
 		return decodeResponse(resp)
 	}
 }
+
+// Set returns an endpoint that makes HTTP requests to the cache service Set
+// server.
+func (c *Client) Set() goa.Endpoint {
+	var (
+		encodeRequest  = EncodeSetRequest(c.encoder)
+		decodeResponse = DecodeSetResponse(c.decoder, c.RestoreResponseBody)
+	)
+	return func(ctx context.Context, v interface{}) (interface{}, error) {
+		req, err := c.BuildSetRequest(ctx, v)
+		if err != nil {
+			return nil, err
+		}
+		err = encodeRequest(req, v)
+		if err != nil {
+			return nil, err
+		}
+		resp, err := c.SetDoer.Do(req)
+		if err != nil {
+			return nil, goahttp.ErrRequestError("cache", "Set", err)
+		}
+		return decodeResponse(resp)
+	}
+}
diff --git a/gen/http/cache/client/encode_decode.go b/gen/http/cache/client/encode_decode.go
index dd4550d9b4b97277842a3b9a182c872796d6ed01..be26cb474f49755658db16e76b03237c882009ed 100644
--- a/gen/http/cache/client/encode_decode.go
+++ b/gen/http/cache/client/encode_decode.go
@@ -77,7 +77,7 @@ func DecodeGetResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody
 		switch resp.StatusCode {
 		case http.StatusOK:
 			var (
-				body []byte
+				body interface{}
 				err  error
 			)
 			err = decoder(resp).Decode(&body)
@@ -91,3 +91,73 @@ func DecodeGetResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody
 		}
 	}
 }
+
+// BuildSetRequest instantiates a HTTP request object with method and path set
+// to call the "cache" service "Set" endpoint
+func (c *Client) BuildSetRequest(ctx context.Context, v interface{}) (*http.Request, error) {
+	u := &url.URL{Scheme: c.scheme, Host: c.host, Path: SetCachePath()}
+	req, err := http.NewRequest("POST", u.String(), nil)
+	if err != nil {
+		return nil, goahttp.ErrInvalidURL("cache", "Set", u.String(), err)
+	}
+	if ctx != nil {
+		req = req.WithContext(ctx)
+	}
+
+	return req, nil
+}
+
+// EncodeSetRequest returns an encoder for requests sent to the cache Set
+// server.
+func EncodeSetRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, interface{}) error {
+	return func(req *http.Request, v interface{}) error {
+		p, ok := v.(*cache.CacheSetRequest)
+		if !ok {
+			return goahttp.ErrInvalidType("cache", "Set", "*cache.CacheSetRequest", v)
+		}
+		{
+			head := p.Key
+			req.Header.Set("x-cache-key", head)
+		}
+		{
+			head := p.Namespace
+			req.Header.Set("x-cache-namespace", head)
+		}
+		{
+			head := p.Scope
+			req.Header.Set("x-cache-scope", head)
+		}
+		body := p.Data
+		if err := encoder(req).Encode(&body); err != nil {
+			return goahttp.ErrEncodingError("cache", "Set", err)
+		}
+		return nil
+	}
+}
+
+// DecodeSetResponse returns a decoder for responses returned by the cache Set
+// endpoint. restoreBody controls whether the response body should be restored
+// after having been read.
+func DecodeSetResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (interface{}, error) {
+	return func(resp *http.Response) (interface{}, error) {
+		if restoreBody {
+			b, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				return nil, err
+			}
+			resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+			defer func() {
+				resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+			}()
+		} else {
+			defer resp.Body.Close()
+		}
+		switch resp.StatusCode {
+		case http.StatusCreated:
+			return nil, nil
+		default:
+			body, _ := ioutil.ReadAll(resp.Body)
+			return nil, goahttp.ErrInvalidResponse("cache", "Set", resp.StatusCode, string(body))
+		}
+	}
+}
diff --git a/gen/http/cache/client/paths.go b/gen/http/cache/client/paths.go
index d4e85ee6fa5552f06361e65105ef5bea446e5753..90588e4bae0c42a9b125238089f4519ae1b13a5f 100644
--- a/gen/http/cache/client/paths.go
+++ b/gen/http/cache/client/paths.go
@@ -11,3 +11,8 @@ package client
 func GetCachePath() string {
 	return "/v1/cache"
 }
+
+// SetCachePath returns the URL path to the cache service Set HTTP endpoint.
+func SetCachePath() string {
+	return "/v1/cache"
+}
diff --git a/gen/http/cache/server/encode_decode.go b/gen/http/cache/server/encode_decode.go
index 6e8629d2e7494d5e077d13533ad55a83d966660f..b6587e807c913d0cd21fc1001df3baddd7353f34 100644
--- a/gen/http/cache/server/encode_decode.go
+++ b/gen/http/cache/server/encode_decode.go
@@ -9,6 +9,7 @@ package server
 
 import (
 	"context"
+	"io"
 	"net/http"
 
 	goahttp "goa.design/goa/v3/http"
@@ -19,7 +20,8 @@ import (
 // endpoint.
 func EncodeGetResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error {
 	return func(ctx context.Context, w http.ResponseWriter, v interface{}) error {
-		res, _ := v.([]byte)
+		res, _ := v.(interface{})
+		ctx = context.WithValue(ctx, goahttp.ContentTypeKey, "application/json")
 		enc := encoder(ctx, w)
 		body := res
 		w.WriteHeader(http.StatusOK)
@@ -57,3 +59,54 @@ func DecodeGetRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Dec
 		return payload, nil
 	}
 }
+
+// EncodeSetResponse returns an encoder for responses returned by the cache Set
+// endpoint.
+func EncodeSetResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error {
+	return func(ctx context.Context, w http.ResponseWriter, v interface{}) error {
+		w.WriteHeader(http.StatusCreated)
+		return nil
+	}
+}
+
+// DecodeSetRequest returns a decoder for requests sent to the cache Set
+// endpoint.
+func DecodeSetRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (interface{}, error) {
+	return func(r *http.Request) (interface{}, error) {
+		var (
+			body interface{}
+			err  error
+		)
+		err = decoder(r).Decode(&body)
+		if err != nil {
+			if err == io.EOF {
+				return nil, goa.MissingPayloadError()
+			}
+			return nil, goa.DecodePayloadError(err.Error())
+		}
+
+		var (
+			key       string
+			namespace string
+			scope     string
+		)
+		key = r.Header.Get("x-cache-key")
+		if key == "" {
+			err = goa.MergeErrors(err, goa.MissingFieldError("x-cache-key", "header"))
+		}
+		namespace = r.Header.Get("x-cache-namespace")
+		if namespace == "" {
+			err = goa.MergeErrors(err, goa.MissingFieldError("x-cache-namespace", "header"))
+		}
+		scope = r.Header.Get("x-cache-scope")
+		if scope == "" {
+			err = goa.MergeErrors(err, goa.MissingFieldError("x-cache-scope", "header"))
+		}
+		if err != nil {
+			return nil, err
+		}
+		payload := NewSetCacheSetRequest(body, key, namespace, scope)
+
+		return payload, nil
+	}
+}
diff --git a/gen/http/cache/server/paths.go b/gen/http/cache/server/paths.go
index 656155750cbb8e8932366cf94bde88f3d5e97d6f..31e15617209f7986fb54b5cf611ad1ed57c8d457 100644
--- a/gen/http/cache/server/paths.go
+++ b/gen/http/cache/server/paths.go
@@ -11,3 +11,8 @@ package server
 func GetCachePath() string {
 	return "/v1/cache"
 }
+
+// SetCachePath returns the URL path to the cache service Set HTTP endpoint.
+func SetCachePath() string {
+	return "/v1/cache"
+}
diff --git a/gen/http/cache/server/server.go b/gen/http/cache/server/server.go
index 63e8e6f0139c65f080770c08f884366d149a90b3..dd65640c9087f7a8309277bd5933ee1e75f42f4f 100644
--- a/gen/http/cache/server/server.go
+++ b/gen/http/cache/server/server.go
@@ -20,6 +20,7 @@ import (
 type Server struct {
 	Mounts []*MountPoint
 	Get    http.Handler
+	Set    http.Handler
 }
 
 // ErrorNamer is an interface implemented by generated error structs that
@@ -56,8 +57,10 @@ func New(
 	return &Server{
 		Mounts: []*MountPoint{
 			{"Get", "GET", "/v1/cache"},
+			{"Set", "POST", "/v1/cache"},
 		},
 		Get: NewGetHandler(e.Get, mux, decoder, encoder, errhandler, formatter),
+		Set: NewSetHandler(e.Set, mux, decoder, encoder, errhandler, formatter),
 	}
 }
 
@@ -67,11 +70,13 @@ func (s *Server) Service() string { return "cache" }
 // Use wraps the server handlers with the given middleware.
 func (s *Server) Use(m func(http.Handler) http.Handler) {
 	s.Get = m(s.Get)
+	s.Set = m(s.Set)
 }
 
 // Mount configures the mux to serve the cache endpoints.
 func Mount(mux goahttp.Muxer, h *Server) {
 	MountGetHandler(mux, h.Get)
+	MountSetHandler(mux, h.Set)
 }
 
 // Mount configures the mux to serve the cache endpoints.
@@ -129,3 +134,54 @@ func NewGetHandler(
 		}
 	})
 }
+
+// MountSetHandler configures the mux to serve the "cache" service "Set"
+// endpoint.
+func MountSetHandler(mux goahttp.Muxer, h http.Handler) {
+	f, ok := h.(http.HandlerFunc)
+	if !ok {
+		f = func(w http.ResponseWriter, r *http.Request) {
+			h.ServeHTTP(w, r)
+		}
+	}
+	mux.Handle("POST", "/v1/cache", f)
+}
+
+// NewSetHandler creates a HTTP handler which loads the HTTP request and calls
+// the "cache" service "Set" endpoint.
+func NewSetHandler(
+	endpoint goa.Endpoint,
+	mux goahttp.Muxer,
+	decoder func(*http.Request) goahttp.Decoder,
+	encoder func(context.Context, http.ResponseWriter) goahttp.Encoder,
+	errhandler func(context.Context, http.ResponseWriter, error),
+	formatter func(err error) goahttp.Statuser,
+) http.Handler {
+	var (
+		decodeRequest  = DecodeSetRequest(mux, decoder)
+		encodeResponse = EncodeSetResponse(encoder)
+		encodeError    = goahttp.ErrorEncoder(encoder, formatter)
+	)
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept"))
+		ctx = context.WithValue(ctx, goa.MethodKey, "Set")
+		ctx = context.WithValue(ctx, goa.ServiceKey, "cache")
+		payload, err := decodeRequest(r)
+		if err != nil {
+			if err := encodeError(ctx, w, err); err != nil {
+				errhandler(ctx, w, err)
+			}
+			return
+		}
+		res, err := endpoint(ctx, payload)
+		if err != nil {
+			if err := encodeError(ctx, w, err); err != nil {
+				errhandler(ctx, w, err)
+			}
+			return
+		}
+		if err := encodeResponse(ctx, w, res); err != nil {
+			errhandler(ctx, w, err)
+		}
+	})
+}
diff --git a/gen/http/cache/server/types.go b/gen/http/cache/server/types.go
index 4585d80628f45910bd241d0caacce974fb9766fd..c9d87f134992134625b260b82a3ceee77e0a0ee6 100644
--- a/gen/http/cache/server/types.go
+++ b/gen/http/cache/server/types.go
@@ -20,3 +20,16 @@ func NewGetCacheGetRequest(key string, namespace string, scope string) *cache.Ca
 
 	return v
 }
+
+// NewSetCacheSetRequest builds a cache service Set endpoint payload.
+func NewSetCacheSetRequest(body interface{}, key string, namespace string, scope string) *cache.CacheSetRequest {
+	v := body
+	res := &cache.CacheSetRequest{
+		Data: v,
+	}
+	res.Key = key
+	res.Namespace = namespace
+	res.Scope = scope
+
+	return res
+}
diff --git a/gen/http/cli/cache/cli.go b/gen/http/cli/cache/cli.go
index 2bfecddeacdbcbb0bd07454c0527db1669dc680a..007ace38ca77de84e7e57b6d6a23f783ef89adbe 100644
--- a/gen/http/cli/cache/cli.go
+++ b/gen/http/cli/cache/cli.go
@@ -25,14 +25,14 @@ import (
 //
 func UsageCommands() string {
 	return `health (liveness|readiness)
-cache get
+cache (get|set)
 `
 }
 
 // UsageExamples produces an example of a valid invocation of the CLI tool.
 func UsageExamples() string {
 	return os.Args[0] + ` health liveness` + "\n" +
-		os.Args[0] + ` cache get --key "Officiis fuga architecto cum." --namespace "Sint adipisci." --scope "Debitis id reprehenderit incidunt necessitatibus assumenda."` + "\n" +
+		os.Args[0] + ` cache get --key "Suscipit sed consequatur rerum occaecati in veritatis." --namespace "Repudiandae eos consequatur sint dolorum occaecati." --scope "Voluptatum modi tenetur tempore quia est ratione."` + "\n" +
 		""
 }
 
@@ -58,6 +58,12 @@ func ParseEndpoint(
 		cacheGetKeyFlag       = cacheGetFlags.String("key", "REQUIRED", "")
 		cacheGetNamespaceFlag = cacheGetFlags.String("namespace", "REQUIRED", "")
 		cacheGetScopeFlag     = cacheGetFlags.String("scope", "REQUIRED", "")
+
+		cacheSetFlags         = flag.NewFlagSet("set", flag.ExitOnError)
+		cacheSetBodyFlag      = cacheSetFlags.String("body", "REQUIRED", "")
+		cacheSetKeyFlag       = cacheSetFlags.String("key", "REQUIRED", "")
+		cacheSetNamespaceFlag = cacheSetFlags.String("namespace", "REQUIRED", "")
+		cacheSetScopeFlag     = cacheSetFlags.String("scope", "REQUIRED", "")
 	)
 	healthFlags.Usage = healthUsage
 	healthLivenessFlags.Usage = healthLivenessUsage
@@ -65,6 +71,7 @@ func ParseEndpoint(
 
 	cacheFlags.Usage = cacheUsage
 	cacheGetFlags.Usage = cacheGetUsage
+	cacheSetFlags.Usage = cacheSetUsage
 
 	if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
 		return nil, nil, err
@@ -115,6 +122,9 @@ func ParseEndpoint(
 			case "get":
 				epf = cacheGetFlags
 
+			case "set":
+				epf = cacheSetFlags
+
 			}
 
 		}
@@ -153,6 +163,9 @@ func ParseEndpoint(
 			case "get":
 				endpoint = c.Get()
 				data, err = cachec.BuildGetPayload(*cacheGetKeyFlag, *cacheGetNamespaceFlag, *cacheGetScopeFlag)
+			case "set":
+				endpoint = c.Set()
+				data, err = cachec.BuildSetPayload(*cacheSetBodyFlag, *cacheSetKeyFlag, *cacheSetNamespaceFlag, *cacheSetScopeFlag)
 			}
 		}
 	}
@@ -204,7 +217,8 @@ Usage:
     %[1]s [globalflags] cache COMMAND [flags]
 
 COMMAND:
-    get: Get value from the cache. The result is a sequence of bytes which the client must decode.
+    get: Get JSON value from the cache.
+    set: Set a JSON value in the cache.
 
 Additional help:
     %[1]s cache COMMAND --help
@@ -213,12 +227,26 @@ Additional help:
 func cacheGetUsage() {
 	fmt.Fprintf(os.Stderr, `%[1]s [flags] cache get -key STRING -namespace STRING -scope STRING
 
-Get value from the cache. The result is a sequence of bytes which the client must decode.
+Get JSON value from the cache.
+    -key STRING: 
+    -namespace STRING: 
+    -scope STRING: 
+
+Example:
+    %[1]s cache get --key "Suscipit sed consequatur rerum occaecati in veritatis." --namespace "Repudiandae eos consequatur sint dolorum occaecati." --scope "Voluptatum modi tenetur tempore quia est ratione."
+`, os.Args[0])
+}
+
+func cacheSetUsage() {
+	fmt.Fprintf(os.Stderr, `%[1]s [flags] cache set -body JSON -key STRING -namespace STRING -scope STRING
+
+Set a JSON value in the cache.
+    -body JSON: 
     -key STRING: 
     -namespace STRING: 
     -scope STRING: 
 
 Example:
-    %[1]s cache get --key "Officiis fuga architecto cum." --namespace "Sint adipisci." --scope "Debitis id reprehenderit incidunt necessitatibus assumenda."
+    %[1]s cache set --body "Quasi ut." --key "Quasi perspiciatis." --namespace "Accusantium animi non alias." --scope "Esse inventore ullam placeat aut."
 `, os.Args[0])
 }
diff --git a/gen/http/openapi.json b/gen/http/openapi.json
index b77a470aa4c05f88e90ef116416482555f7a5c90..b9d430311b5a1b01b8f6f061e08c090c3e191545 100644
--- a/gen/http/openapi.json
+++ b/gen/http/openapi.json
@@ -1 +1 @@
-{"swagger":"2.0","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":""},"host":"localhost:8083","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get value from the cache. The result is a sequence of bytes which the client must decode.","operationId":"cache#Get","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":true,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"byte"}}},"schemes":["http"]}}}}
\ No newline at end of file
+{"swagger":"2.0","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":""},"host":"localhost:8083","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get JSON value from the cache.","operationId":"cache#Get","produces":["application/json"],"parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":true,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]},"post":{"tags":["cache"],"summary":"Set cache","description":"Set a JSON value in the cache.","operationId":"cache#Set","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","required":true,"type":"string"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","required":true,"type":"string"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","required":true,"type":"string"},{"name":"any","in":"body","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"201":{"description":"Created response."}},"schemes":["http"]}}}}
\ No newline at end of file
diff --git a/gen/http/openapi.yaml b/gen/http/openapi.yaml
index 5043265f7fa571f22f8a8f96b303296e161d0cdd..b1bac2cdadd957be492a9618414d12516397b6b2 100644
--- a/gen/http/openapi.yaml
+++ b/gen/http/openapi.yaml
@@ -40,9 +40,10 @@ paths:
       tags:
       - cache
       summary: Get cache
-      description: Get value from the cache. The result is a sequence of bytes which
-        the client must decode.
+      description: Get JSON value from the cache.
       operationId: cache#Get
+      produces:
+      - application/json
       parameters:
       - name: x-cache-key
         in: header
@@ -64,6 +65,39 @@ paths:
           description: OK response.
           schema:
             type: string
-            format: byte
+            format: binary
+      schemes:
+      - http
+    post:
+      tags:
+      - cache
+      summary: Set cache
+      description: Set a JSON value in the cache.
+      operationId: cache#Set
+      parameters:
+      - name: x-cache-key
+        in: header
+        description: Cache entry key
+        required: true
+        type: string
+      - name: x-cache-namespace
+        in: header
+        description: Cache entry namespace
+        required: true
+        type: string
+      - name: x-cache-scope
+        in: header
+        description: Cache entry scope
+        required: true
+        type: string
+      - name: any
+        in: body
+        required: true
+        schema:
+          type: string
+          format: binary
+      responses:
+        "201":
+          description: Created response.
       schemes:
       - http
diff --git a/gen/http/openapi3.json b/gen/http/openapi3.json
index be3f9a4d1f1018196f1bb8c204da2f91a9434473..0ce517d7b5de2092ed45e6bb357aa14c8556a7c9 100644
--- a/gen/http/openapi3.json
+++ b/gen/http/openapi3.json
@@ -1 +1 @@
-{"openapi":"3.0.3","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":"1.0"},"servers":[{"url":"http://localhost:8083","description":"Cache Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get value from the cache. The result is a sequence of bytes which the client must decode.","operationId":"cache#Get","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"UmVwdWRpYW5kYWUgZW9zIGNvbnNlcXVhdHVyIHNpbnQgZG9sb3J1bSBvY2NhZWNhdGku","format":"binary"},"example":"Vm9sdXB0YXR1bSBtb2RpIHRlbmV0dXIgdGVtcG9yZSBxdWlhIGVzdCByYXRpb25lLg=="}}}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"cache","description":"Cache service allows storing and retrieving data from distributed cache."}]}
\ No newline at end of file
+{"openapi":"3.0.3","info":{"title":"Cache Service","description":"The cache service exposes interface for working with Redis.","version":"1.0"},"servers":[{"url":"http://localhost:8083","description":"Cache Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/cache":{"get":{"tags":["cache"],"summary":"Get cache","description":"Get JSON value from the cache.","operationId":"cache#Get","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Qui iusto enim est dolores dolorem et.","format":"binary"},"example":"Quisquam ab dolores distinctio quis."}}}}},"post":{"tags":["cache"],"summary":"Set cache","description":"Set a JSON value in the cache.","operationId":"cache#Set","parameters":[{"name":"x-cache-key","in":"header","description":"Cache entry key","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry key","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-namespace","in":"header","description":"Cache entry namespace","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry namespace","example":"Login"},"example":"Login"},{"name":"x-cache-scope","in":"header","description":"Cache entry scope","allowEmptyValue":true,"required":true,"schema":{"type":"string","description":"Cache entry scope","example":"administration"},"example":"administration"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"string","example":"Et illum fugiat ut.","format":"binary"},"example":"Optio aliquam error nam."}}},"responses":{"201":{"description":"Created response."}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"cache","description":"Cache service allows storing and retrieving data from distributed cache."}]}
\ No newline at end of file
diff --git a/gen/http/openapi3.yaml b/gen/http/openapi3.yaml
index 7fa181f0598cfd836cc793396662672f5d9f5776..b936940cde419698a7133a062edd0436c1650930 100644
--- a/gen/http/openapi3.yaml
+++ b/gen/http/openapi3.yaml
@@ -30,8 +30,7 @@ paths:
       tags:
       - cache
       summary: Get cache
-      description: Get value from the cache. The result is a sequence of bytes which
-        the client must decode.
+      description: Get JSON value from the cache.
       operationId: cache#Get
       parameters:
       - name: x-cache-key
@@ -71,109 +70,58 @@ paths:
             application/json:
               schema:
                 type: string
-                example:
-                - 82
-                - 101
-                - 112
-                - 117
-                - 100
-                - 105
-                - 97
-                - 110
-                - 100
-                - 97
-                - 101
-                - 32
-                - 101
-                - 111
-                - 115
-                - 32
-                - 99
-                - 111
-                - 110
-                - 115
-                - 101
-                - 113
-                - 117
-                - 97
-                - 116
-                - 117
-                - 114
-                - 32
-                - 115
-                - 105
-                - 110
-                - 116
-                - 32
-                - 100
-                - 111
-                - 108
-                - 111
-                - 114
-                - 117
-                - 109
-                - 32
-                - 111
-                - 99
-                - 99
-                - 97
-                - 101
-                - 99
-                - 97
-                - 116
-                - 105
-                - 46
+                example: Qui iusto enim est dolores dolorem et.
                 format: binary
-              example:
-              - 86
-              - 111
-              - 108
-              - 117
-              - 112
-              - 116
-              - 97
-              - 116
-              - 117
-              - 109
-              - 32
-              - 109
-              - 111
-              - 100
-              - 105
-              - 32
-              - 116
-              - 101
-              - 110
-              - 101
-              - 116
-              - 117
-              - 114
-              - 32
-              - 116
-              - 101
-              - 109
-              - 112
-              - 111
-              - 114
-              - 101
-              - 32
-              - 113
-              - 117
-              - 105
-              - 97
-              - 32
-              - 101
-              - 115
-              - 116
-              - 32
-              - 114
-              - 97
-              - 116
-              - 105
-              - 111
-              - 110
-              - 101
-              - 46
+              example: Quisquam ab dolores distinctio quis.
+    post:
+      tags:
+      - cache
+      summary: Set cache
+      description: Set a JSON value in the cache.
+      operationId: cache#Set
+      parameters:
+      - name: x-cache-key
+        in: header
+        description: Cache entry key
+        allowEmptyValue: true
+        required: true
+        schema:
+          type: string
+          description: Cache entry key
+          example: did:web:example.com
+        example: did:web:example.com
+      - name: x-cache-namespace
+        in: header
+        description: Cache entry namespace
+        allowEmptyValue: true
+        required: true
+        schema:
+          type: string
+          description: Cache entry namespace
+          example: Login
+        example: Login
+      - name: x-cache-scope
+        in: header
+        description: Cache entry scope
+        allowEmptyValue: true
+        required: true
+        schema:
+          type: string
+          description: Cache entry scope
+          example: administration
+        example: administration
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              type: string
+              example: Et illum fugiat ut.
+              format: binary
+            example: Optio aliquam error nam.
+      responses:
+        "201":
+          description: Created response.
 components: {}
 tags:
 - name: health
diff --git a/internal/clients/redis/client.go b/internal/clients/redis/client.go
index 84d5106ebd417ffbf82945259c2174fb0bb6abdc..0b1f1c993de879d277aa217a2876cb5dd7571375 100644
--- a/internal/clients/redis/client.go
+++ b/internal/clients/redis/client.go
@@ -41,3 +41,11 @@ func (c *Client) Get(ctx context.Context, key string) ([]byte, error) {
 	}
 	return []byte(result.Val()), nil
 }
+
+func (c *Client) Set(ctx context.Context, key string, value []byte, ttl time.Duration) error {
+	if ttl == 0 {
+		ttl = c.defaultTTL
+	}
+
+	return c.rdb.Set(ctx, key, value, ttl).Err()
+}
diff --git a/internal/service/cache/service.go b/internal/service/cache/service.go
index 0e3153a6a3ac0ed6a03720e9b617f22246b38847..4644cc015ed6f44f86ea7dc4b6ead5f73420f384 100644
--- a/internal/service/cache/service.go
+++ b/internal/service/cache/service.go
@@ -2,7 +2,9 @@ package cache
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
+	"time"
 
 	"go.uber.org/zap"
 
@@ -12,6 +14,7 @@ import (
 
 type Cache interface {
 	Get(ctx context.Context, key string) ([]byte, error)
+	Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
 }
 
 type Service struct {
@@ -26,7 +29,7 @@ func New(cache Cache, logger *zap.Logger) *Service {
 	}
 }
 
-func (s *Service) Get(ctx context.Context, req *cache.CacheGetRequest) ([]byte, error) {
+func (s *Service) Get(ctx context.Context, req *cache.CacheGetRequest) (interface{}, error) {
 	var operation = zap.String("operation", "get")
 	if req.Key == "" || req.Namespace == "" || req.Scope == "" {
 		s.logger.Error("bad request: missing key or namespace or scopes", operation)
@@ -34,7 +37,7 @@ func (s *Service) Get(ctx context.Context, req *cache.CacheGetRequest) ([]byte,
 	}
 
 	// create key from the input fields
-	key := makeCacheKey(req.Key, req.Namespace, req.Scope)
+	key := makeCacheKey(req.Namespace, req.Scope, req.Key)
 	data, err := s.cache.Get(ctx, key)
 	if err != nil {
 		s.logger.Error("error getting value from cache", zap.String("key", key), zap.Error(err))
@@ -44,7 +47,40 @@ func (s *Service) Get(ctx context.Context, req *cache.CacheGetRequest) ([]byte,
 		return nil, errors.New("error getting value from cache", err)
 	}
 
-	return data, nil
+	var decodedValue interface{}
+	if err := json.Unmarshal(data, &decodedValue); err != nil {
+		s.logger.Error("cannot decode json value from cache", zap.Error(err))
+		return nil, errors.New("cannot decode json value from cache", err)
+	}
+
+	return decodedValue, nil
+}
+
+func (s *Service) Set(ctx context.Context, req *cache.CacheSetRequest) error {
+	var operation = zap.String("operation", "set")
+
+	if req.Key == "" || req.Namespace == "" || req.Scope == "" {
+		s.logger.Error("bad request: missing key or namespace or scope or data", operation)
+		return errors.New(errors.BadRequest, "bad request")
+	}
+
+	// TODO(kinkov): issue #3 - evaluate key metadata (key, namespace and scope) and set TTL over a policy execution
+
+	// create key from the input fields
+	key := makeCacheKey(req.Namespace, req.Scope, req.Key)
+	// encode payload to json bytes for storing in cache
+	value, err := json.Marshal(req.Data)
+	if err != nil {
+		s.logger.Error("error encode payload to json", zap.Error(err), operation)
+		return errors.New("error encode payload to json", err)
+	}
+
+	if err := s.cache.Set(ctx, key, value, 0); err != nil {
+		s.logger.Error("error setting value in cache", zap.Error(err), operation)
+		return errors.New("error setting value in cache", err)
+	}
+
+	return nil
 }
 
 func makeCacheKey(namespace, scope, key string) string {