Repository: mainflux/mainflux
Pull request #1236 (2020-09-16 10:11:42)

MF-1237 - Return to transport only things service errors
Currently, we send to `transport.go` errors from different sources (db, cache, etc.). However, not all of these errors are addressed by the switch case in the `transport.go`. So we have a double problem: firstly, inconsistent error sources, secondly unaddressed errors. 

Also, we need to make swagger spec in agreement with new error handling.

manuio: > Currently, we send to `transport.go` errors from different sources (db, cache, etc.). However, not all of these errors are addressed by the switch case in the `transport.go`. So we have a double problem: firstly, inconsistent error sources, secondly unaddressed errors.
> 
> Also, we need to make swagger spec in agreement with new error handling.

@darkodraskovic It would be better to create an issue to explain this
codecov-commenter: # [Codecov](https://codecov.io/gh/mainflux/mainflux/pull/1236?src=pr&el=h1) Report
> Merging [#1236](https://codecov.io/gh/mainflux/mainflux/pull/1236?src=pr&el=desc) into [master](https://codecov.io/gh/mainflux/mainflux/commit/f18f2c1c98c9ff4384e9c7f7c5fc129818c379c4?el=desc) will **decrease** coverage by `1.82%`.
> The diff coverage is `36.69%`.

[![Impacted file tree graph](https://codecov.io/gh/mainflux/mainflux/pull/1236/graphs/tree.svg?width=650&height=150&src=pr&token=L932pGLS8b)](https://codecov.io/gh/mainflux/mainflux/pull/1236?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1236      +/-   ##
==========================================
- Coverage   76.18%   74.36%   -1.83%     
==========================================
  Files         106      106              
  Lines        6983     6159     -824     
==========================================
- Hits         5320     4580     -740     
+ Misses       1278     1194      -84     
  Partials      385      385              
```


| [Impacted Files](https://codecov.io/gh/mainflux/mainflux/pull/1236?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [things/api/auth/http/endpoint.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL2FwaS9hdXRoL2h0dHAvZW5kcG9pbnQuZ28=) | `100.00% <ø> (ø)` | |
| [things/redis/channels.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL3JlZGlzL2NoYW5uZWxzLmdv) | `64.70% <0.00%> (-9.21%)` | :arrow_down: |
| [twins/api/http/transport.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dHdpbnMvYXBpL2h0dHAvdHJhbnNwb3J0Lmdv) | `87.33% <0.00%> (-0.94%)` | :arrow_down: |
| [things/postgres/things.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL3Bvc3RncmVzL3RoaW5ncy5nbw==) | `79.42% <4.16%> (-1.38%)` | :arrow_down: |
| [things/postgres/channels.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL3Bvc3RncmVzL2NoYW5uZWxzLmdv) | `79.68% <18.18%> (-1.91%)` | :arrow_down: |
| [things/redis/things.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL3JlZGlzL3RoaW5ncy5nbw==) | `66.66% <20.00%> (-4.77%)` | :arrow_down: |
| [things/api/things/http/transport.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL2FwaS90aGluZ3MvaHR0cC90cmFuc3BvcnQuZ28=) | `87.71% <53.84%> (-0.81%)` | :arrow_down: |
| [things/service.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL3NlcnZpY2UuZ28=) | `77.68% <57.57%> (-8.65%)` | :arrow_down: |
| [things/api/auth/grpc/server.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL2FwaS9hdXRoL2dycGMvc2VydmVyLmdv) | `92.15% <100.00%> (-4.34%)` | :arrow_down: |
| [things/api/auth/http/transport.go](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree#diff-dGhpbmdzL2FwaS9hdXRoL2h0dHAvdHJhbnNwb3J0Lmdv) | `90.14% <100.00%> (+0.95%)` | :arrow_up: |
| ... and [106 more](https://codecov.io/gh/mainflux/mainflux/pull/1236/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/mainflux/mainflux/pull/1236?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/mainflux/mainflux/pull/1236?src=pr&el=footer). Last update [f18f2c1...7987e07](https://codecov.io/gh/mainflux/mainflux/pull/1236?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

darkodraskovic: @sprql we've decided to go for 401 as authn error and to use 403 with the upcoming groups feature. Maybe you could review my PR - which converts 403 to 401 as a side effect and eventually refactor your pr to match the other parts of the MF code.
sprql: @darkodraskovic that looks like a good idea

Patch:
diff --git a/things/api/auth/grpc/server.go b/things/api/auth/grpc/server.go
index b703ee08..b6abf7cd 100644
--- a/things/api/auth/grpc/server.go
+++ b/things/api/auth/grpc/server.go
@@ -105,6 +105,10 @@ func encodeError(err error) error {
 		return status.Error(codes.InvalidArgument, "received invalid can access request")
 	case things.ErrUnauthorizedAccess:
 		return status.Error(codes.PermissionDenied, "missing or invalid credentials provided")
+	case things.ErrEntityConnected:
+		return status.Error(codes.PermissionDenied, "entities are not connected")
+	case things.ErrNotFound:
+		return status.Error(codes.NotFound, "entity does not exist")
 	default:
 		return status.Error(codes.Internal, "internal server error")
 	}
diff --git a/things/api/auth/http/transport.go b/things/api/auth/http/transport.go
index d79327b7..0562701f 100644
--- a/things/api/auth/http/transport.go
+++ b/things/api/auth/http/transport.go
@@ -120,6 +120,10 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
 
 	switch err {
 	case things.ErrUnauthorizedAccess:
+		w.WriteHeader(http.StatusUnauthorized)
+	case things.ErrNotFound:
+		w.WriteHeader(http.StatusNotFound)
+	case things.ErrEntityConnected:
 		w.WriteHeader(http.StatusForbidden)
 	case errUnsupportedContentType:
 		w.WriteHeader(http.StatusUnsupportedMediaType)
diff --git a/things/api/things/http/transport.go b/things/api/things/http/transport.go
index 7eb5fdb2..0229ed3b 100644
--- a/things/api/things/http/transport.go
+++ b/things/api/things/http/transport.go
@@ -393,26 +393,41 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
 	case errors.Error:
 		w.Header().Set("Content-Type", contentType)
 		switch {
+		case errors.Contains(errorVal, things.ErrUnauthorizedAccess),
+			errors.Contains(errorVal, things.ErrEntityConnected):
+			w.WriteHeader(http.StatusUnauthorized)
+
+		case errors.Contains(errorVal, errInvalidQueryParams):
+			w.WriteHeader(http.StatusBadRequest)
+		case errors.Contains(errorVal, errUnsupportedContentType):
+			w.WriteHeader(http.StatusUnsupportedMediaType)
+
 		case errors.Contains(errorVal, things.ErrMalformedEntity):
 			w.WriteHeader(http.StatusBadRequest)
-		case errors.Contains(errorVal, things.ErrUnauthorizedAccess):
-			w.WriteHeader(http.StatusForbidden)
 		case errors.Contains(errorVal, things.ErrNotFound):
 			w.WriteHeader(http.StatusNotFound)
 		case errors.Contains(errorVal, things.ErrConflict):
+			w.WriteHeader(http.StatusConflict)
+
+		case errors.Contains(errorVal, things.ErrScanMetadata),
+			errors.Contains(errorVal, things.ErrSelectEntity):
 			w.WriteHeader(http.StatusUnprocessableEntity)
-		case errors.Contains(errorVal, errUnsupportedContentType):
-			w.WriteHeader(http.StatusUnsupportedMediaType)
-		case errors.Contains(errorVal, errInvalidQueryParams):
-			w.WriteHeader(http.StatusBadRequest)
-		case errors.Contains(errorVal, things.ErrRemoveThing):
-			w.WriteHeader(http.StatusInternalServerError)
-		case errors.Contains(errorVal, things.ErrRemoveChannel):
-			w.WriteHeader(http.StatusInternalServerError)
-		case errors.Contains(errorVal, io.ErrUnexpectedEOF):
+
+		case errors.Contains(errorVal, things.ErrCreateEntity),
+			errors.Contains(errorVal, things.ErrUpdateEntity),
+			errors.Contains(errorVal, things.ErrViewEntity),
+			errors.Contains(errorVal, things.ErrRemoveEntity),
+			errors.Contains(errorVal, things.ErrConnect),
+			errors.Contains(errorVal, things.ErrDisconnect):
 			w.WriteHeader(http.StatusBadRequest)
-		case errors.Contains(errorVal, io.EOF):
+
+		case errors.Contains(errorVal, io.ErrUnexpectedEOF),
+			errors.Contains(errorVal, io.EOF):
 			w.WriteHeader(http.StatusBadRequest)
+
+		case errors.Contains(errorVal, things.ErrCreateUUID):
+			w.WriteHeader(http.StatusInternalServerError)
+
 		default:
 			w.WriteHeader(http.StatusInternalServerError)
 		}
@@ -471,7 +486,7 @@ func readMetadataQuery(r *http.Request, key string) (map[string]interface{}, err
 	m := make(map[string]interface{})
 	err := json.Unmarshal([]byte(vals[0]), &m)
 	if err != nil {
-		return nil, err
+		return nil, errors.Wrap(errInvalidQueryParams, err)
 	}
 
 	return m, nil
diff --git a/things/mocks/channels.go b/things/mocks/channels.go
index 0ddf169b..e658acc7 100644
--- a/things/mocks/channels.go
+++ b/things/mocks/channels.go
@@ -230,16 +230,16 @@ func (crm *channelRepositoryMock) Disconnect(_ context.Context, owner, chanID, t
 func (crm *channelRepositoryMock) HasThing(_ context.Context, chanID, token string) (string, error) {
 	tid, err := crm.things.RetrieveByKey(context.Background(), token)
 	if err != nil {
-		return "", things.ErrNotFound
+		return "", err
 	}
 
 	chans, ok := crm.cconns[tid]
 	if !ok {
-		return "", things.ErrNotFound
+		return "", things.ErrEntityConnected
 	}
 
 	if _, ok := chans[chanID]; !ok {
-		return "", things.ErrNotFound
+		return "", things.ErrEntityConnected
 	}
 
 	return tid, nil
@@ -248,11 +248,11 @@ func (crm *channelRepositoryMock) HasThing(_ context.Context, chanID, token stri
 func (crm *channelRepositoryMock) HasThingByID(_ context.Context, chanID, thingID string) error {
 	chans, ok := crm.cconns[thingID]
 	if !ok {
-		return things.ErrNotFound
+		return things.ErrEntityConnected
 	}
 
 	if _, ok := chans[chanID]; !ok {
-		return things.ErrNotFound
+		return things.ErrEntityConnected
 	}
 
 	return nil
diff --git a/things/postgres/channels.go b/things/postgres/channels.go
index d77e9c36..0fc170ba 100644
--- a/things/postgres/channels.go
+++ b/things/postgres/channels.go
@@ -17,25 +17,6 @@ import (
 	"github.com/mainflux/mainflux/things"
 )
 
-var (
-	// ErrSaveChannel indicates error while saving to database
-	ErrSaveChannel = errors.New("save channel to db error")
-	// ErrUpdateChannel indicates error while updating channel in database
-	ErrUpdateChannel = errors.New("update channel to db error")
-	// ErrDeleteChannel indicates error while deleting channel in database
-	ErrDeleteChannel = errors.New("delete channel from db error")
-	// ErrSelectChannel indicates error while reading channel from database
-	ErrSelectChannel = errors.New("select channel from db error")
-	// ErrDeleteConnection indicates error while deleting connection in database
-	ErrDeleteConnection = errors.New("unmarshal json error")
-	// ErrHasThing indicates error while checking connection in database
-	ErrHasThing = errors.New("check thing-channel connection in database error")
-	//ErrScan indicates error in database scanner
-	ErrScan = errors.New("database scanner error")
-	//ErrValue indicates error in database valuer
-	ErrValue = errors.New("database valuer error")
-)
-
 var _ things.ChannelRepository = (*channelRepository)(nil)
 
 type channelRepository struct {
@@ -59,7 +40,7 @@ func NewChannelRepository(db Database) things.ChannelRepository {
 func (cr channelRepository) Save(ctx context.Context, channels ...things.Channel) ([]things.Channel, error) {
 	tx, err := cr.db.BeginTxx(ctx, nil)
 	if err != nil {
-		return nil, errors.Wrap(ErrSaveChannel, err)
+		return nil, errors.Wrap(things.ErrCreateEntity, err)
 	}
 
 	q := `INSERT INTO channels (id, owner, name, metadata)
@@ -80,12 +61,12 @@ func (cr channelRepository) Save(ctx context.Context, channels ...things.Channel
 					return []things.Channel{}, things.ErrConflict
 				}
 			}
-			return []things.Channel{}, errors.Wrap(ErrSaveChannel, err)
+			return []things.Channel{}, errors.Wrap(things.ErrCreateEntity, err)
 		}
 	}
 
 	if err = tx.Commit(); err != nil {
-		return []things.Channel{}, errors.Wrap(ErrSaveChannel, err)
+		return []things.Channel{}, errors.Wrap(things.ErrCreateEntity, err)
 	}
 
 	return channels, nil
@@ -106,12 +87,12 @@ func (cr channelRepository) Update(ctx context.Context, channel things.Channel)
 			}
 		}
 
-		return errors.Wrap(ErrUpdateChannel, err)
+		return errors.Wrap(things.ErrUpdateEntity, err)
 	}
 
 	cnt, err := res.RowsAffected()
 	if err != nil {
-		return errors.Wrap(ErrUpdateChannel, err)
+		return errors.Wrap(things.ErrUpdateEntity, err)
 	}
 
 	if cnt == 0 {
@@ -129,12 +110,11 @@ func (cr channelRepository) RetrieveByID(ctx context.Context, owner, id string)
 		Owner: owner,
 	}
 	if err := cr.db.QueryRowxContext(ctx, q, id, owner).StructScan(&dbch); err != nil {
-		empty := things.Channel{}
 		pqErr, ok := err.(*pq.Error)
 		if err == sql.ErrNoRows || ok && errInvalid == pqErr.Code.Name() {
-			return empty, things.ErrNotFound
+			return things.Channel{}, things.ErrNotFound
 		}
-		return empty, errors.Wrap(ErrSelectChannel, err)
+		return things.Channel{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	return toChannel(dbch), nil
@@ -144,7 +124,7 @@ func (cr channelRepository) RetrieveAll(ctx context.Context, owner string, offse
 	nq, name := getNameQuery(name)
 	m, mq, err := getMetadataQuery(metadata)
 	if err != nil {
-		return things.ChannelsPage{}, errors.Wrap(ErrSelectChannel, err)
+		return things.ChannelsPage{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	q := fmt.Sprintf(`SELECT id, name, metadata FROM channels
@@ -159,7 +139,7 @@ func (cr channelRepository) RetrieveAll(ctx context.Context, owner string, offse
 	}
 	rows, err := cr.db.NamedQueryContext(ctx, q, params)
 	if err != nil {
-		return things.ChannelsPage{}, errors.Wrap(ErrSelectChannel, err)
+		return things.ChannelsPage{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 	defer rows.Close()
 
@@ -167,7 +147,7 @@ func (cr channelRepository) RetrieveAll(ctx context.Context, owner string, offse
 	for rows.Next() {
 		dbch := dbChannel{Owner: owner}
 		if err := rows.StructScan(&dbch); err != nil {
-			return things.ChannelsPage{}, errors.Wrap(ErrSelectChannel, err)
+			return things.ChannelsPage{}, errors.Wrap(things.ErrSelectEntity, err)
 		}
 		ch := toChannel(dbch)
 
@@ -178,7 +158,7 @@ func (cr channelRepository) RetrieveAll(ctx context.Context, owner string, offse
 
 	total, err := total(ctx, cr.db, cq, params)
 	if err != nil {
-		return things.ChannelsPage{}, errors.Wrap(ErrSelectChannel, err)
+		return things.ChannelsPage{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	page := things.ChannelsPage{
@@ -245,7 +225,7 @@ func (cr channelRepository) RetrieveByThing(ctx context.Context, owner, thing st
 
 	rows, err := cr.db.NamedQueryContext(ctx, q, params)
 	if err != nil {
-		return things.ChannelsPage{}, errors.Wrap(ErrSelectChannel, err)
+		return things.ChannelsPage{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 	defer rows.Close()
 
@@ -253,7 +233,7 @@ func (cr channelRepository) RetrieveByThing(ctx context.Context, owner, thing st
 	for rows.Next() {
 		dbch := dbChannel{Owner: owner}
 		if err := rows.StructScan(&dbch); err != nil {
-			return things.ChannelsPage{}, errors.Wrap(ErrSelectChannel, err)
+			return things.ChannelsPage{}, errors.Wrap(things.ErrSelectEntity, err)
 		}
 
 		ch := toChannel(dbch)
@@ -262,7 +242,7 @@ func (cr channelRepository) RetrieveByThing(ctx context.Context, owner, thing st
 
 	var total uint64
 	if err := cr.db.GetContext(ctx, &total, qc, owner, thing); err != nil {
-		return things.ChannelsPage{}, errors.Wrap(ErrSelectChannel, err)
+		return things.ChannelsPage{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	return things.ChannelsPage{
@@ -288,7 +268,7 @@ func (cr channelRepository) Remove(ctx context.Context, owner, id string) error
 func (cr channelRepository) Connect(ctx context.Context, owner string, chIDs, thIDs []string) error {
 	tx, err := cr.db.BeginTxx(ctx, nil)
 	if err != nil {
-		return errors.Wrap(ErrDeleteChannel, err)
+		return errors.Wrap(things.ErrConnect, err)
 	}
 
 	q := `INSERT INTO connections (channel_id, channel_owner, thing_id, thing_owner)
@@ -315,13 +295,13 @@ func (cr channelRepository) Connect(ctx context.Context, owner string, chIDs, th
 					}
 				}
 
-				return errors.Wrap(ErrDeleteChannel, err)
+				return errors.Wrap(things.ErrConnect, err)
 			}
 		}
 	}
 
 	if err = tx.Commit(); err != nil {
-		return errors.Wrap(ErrDeleteChannel, err)
+		return errors.Wrap(things.ErrConnect, err)
 	}
 
 	return nil
@@ -340,12 +320,12 @@ func (cr channelRepository) Disconnect(ctx context.Context, owner, chanID, thing
 
 	res, err := cr.db.NamedExecContext(ctx, q, conn)
 	if err != nil {
-		return errors.Wrap(ErrDeleteConnection, err)
+		return errors.Wrap(things.ErrDisconnect, err)
 	}
 
 	cnt, err := res.RowsAffected()
 	if err != nil {
-		return errors.Wrap(ErrDeleteConnection, err)
+		return errors.Wrap(things.ErrDisconnect, err)
 	}
 
 	if cnt == 0 {
@@ -355,16 +335,15 @@ func (cr channelRepository) Disconnect(ctx context.Context, owner, chanID, thing
 	return nil
 }
 
-func (cr channelRepository) HasThing(ctx context.Context, chanID, key string) (string, error) {
+func (cr channelRepository) HasThing(ctx context.Context, chanID, thingKey string) (string, error) {
 	var thingID string
 	q := `SELECT id FROM things WHERE key = $1`
-	if err := cr.db.QueryRowxContext(ctx, q, key).Scan(&thingID); err != nil {
-		return "", errors.Wrap(ErrHasThing, err)
-
+	if err := cr.db.QueryRowxContext(ctx, q, thingKey).Scan(&thingID); err != nil {
+		return "", errors.Wrap(things.ErrEntityConnected, err)
 	}
 
 	if err := cr.hasThing(ctx, chanID, thingID); err != nil {
-		return "", errors.Wrap(ErrHasThing, err)
+		return "", err
 	}
 
 	return thingID, nil
@@ -378,11 +357,11 @@ func (cr channelRepository) hasThing(ctx context.Context, chanID, thingID string
 	q := `SELECT EXISTS (SELECT 1 FROM connections WHERE channel_id = $1 AND thing_id = $2);`
 	exists := false
 	if err := cr.db.QueryRowxContext(ctx, q, chanID, thingID).Scan(&exists); err != nil {
-		return errors.Wrap(ErrHasThing, err)
+		return errors.Wrap(things.ErrEntityConnected, err)
 	}
 
 	if !exists {
-		return things.ErrUnauthorizedAccess
+		return things.ErrNotFound
 	}
 
 	return nil
diff --git a/things/postgres/things.go b/things/postgres/things.go
index d0e76cf5..7507a922 100644
--- a/things/postgres/things.go
+++ b/things/postgres/things.go
@@ -15,21 +15,6 @@ import (
 	"github.com/mainflux/mainflux/things"
 )
 
-var (
-	// ErrSaveDb indicates error while saving to database
-	ErrSaveDb = errors.New("save thing to db error")
-	// ErrUpdateDb indicates error while updating database
-	ErrUpdateDb = errors.New("update thing in db error")
-	// ErrSelectDb indicates error while reading from database
-	ErrSelectDb = errors.New("select thing from db error")
-	// ErrDeleteDb indicates error while marshaling Thing to JSON
-	ErrDeleteDb = errors.New("delete thing from db error")
-	// ErrMarshalThing indicates error while marshaling Thing to JSON
-	ErrMarshalThing = errors.New("marshal to json error")
-	// ErrUnmarshalThing indicates error while unmarshaling JSON to Thing
-	ErrUnmarshalThing = errors.New("unmarshal json error")
-)
-
 const (
 	errDuplicate  = "unique_violation"
 	errFK         = "foreign_key_violation"
@@ -54,7 +39,7 @@ func NewThingRepository(db Database) things.ThingRepository {
 func (tr thingRepository) Save(ctx context.Context, ths ...things.Thing) ([]things.Thing, error) {
 	tx, err := tr.db.BeginTxx(ctx, nil)
 	if err != nil {
-		return nil, errors.Wrap(ErrSaveDb, err)
+		return []things.Thing{}, errors.Wrap(things.ErrCreateEntity, err)
 	}
 
 	q := `INSERT INTO things (id, owner, name, key, metadata)
@@ -63,7 +48,7 @@ func (tr thingRepository) Save(ctx context.Context, ths ...things.Thing) ([]thin
 	for _, thing := range ths {
 		dbth, err := toDBThing(thing)
 		if err != nil {
-			return []things.Thing{}, err
+			return []things.Thing{}, errors.Wrap(things.ErrCreateEntity, err)
 		}
 
 		if _, err := tx.NamedExecContext(ctx, q, dbth); err != nil {
@@ -78,12 +63,12 @@ func (tr thingRepository) Save(ctx context.Context, ths ...things.Thing) ([]thin
 				}
 			}
 
-			return []things.Thing{}, errors.Wrap(ErrSaveDb, err)
+			return []things.Thing{}, errors.Wrap(things.ErrCreateEntity, err)
 		}
 	}
 
 	if err = tx.Commit(); err != nil {
-		return []things.Thing{}, errors.Wrap(ErrSaveDb, err)
+		return []things.Thing{}, errors.Wrap(things.ErrCreateEntity, err)
 	}
 
 	return ths, nil
@@ -94,7 +79,7 @@ func (tr thingRepository) Update(ctx context.Context, t things.Thing) error {
 
 	dbth, err := toDBThing(t)
 	if err != nil {
-		return err
+		return errors.Wrap(things.ErrUpdateEntity, err)
 	}
 
 	res, errdb := tr.db.NamedExecContext(ctx, q, dbth)
@@ -107,12 +92,12 @@ func (tr thingRepository) Update(ctx context.Context, t things.Thing) error {
 			}
 		}
 
-		return errors.Wrap(ErrUpdateDb, errdb)
+		return errors.Wrap(things.ErrUpdateEntity, errdb)
 	}
 
 	cnt, errdb := res.RowsAffected()
 	if err != nil {
-		return errors.Wrap(ErrUpdateDb, errdb)
+		return errors.Wrap(things.ErrUpdateEntity, errdb)
 	}
 
 	if cnt == 0 {
@@ -143,12 +128,12 @@ func (tr thingRepository) UpdateKey(ctx context.Context, owner, id, key string)
 			}
 		}
 
-		return errors.Wrap(ErrUpdateDb, err)
+		return errors.Wrap(things.ErrUpdateEntity, err)
 	}
 
 	cnt, err := res.RowsAffected()
 	if err != nil {
-		return errors.Wrap(ErrUpdateDb, err)
+		return errors.Wrap(things.ErrUpdateEntity, err)
 	}
 
 	if cnt == 0 {
@@ -167,14 +152,11 @@ func (tr thingRepository) RetrieveByID(ctx context.Context, owner, id string) (t
 	}
 
 	if err := tr.db.QueryRowxContext(ctx, q, id, owner).StructScan(&dbth); err != nil {
-		var empty things.Thing
-
 		pqErr, ok := err.(*pq.Error)
 		if err == sql.ErrNoRows || ok && errInvalid == pqErr.Code.Name() {
-			return empty, errors.Wrap(things.ErrNotFound, err)
+			return things.Thing{}, errors.Wrap(things.ErrNotFound, err)
 		}
-
-		return empty, errors.Wrap(ErrSelectDb, err)
+		return things.Thing{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	return toThing(dbth)
@@ -188,7 +170,7 @@ func (tr thingRepository) RetrieveByKey(ctx context.Context, key string) (string
 		if err == sql.ErrNoRows {
 			return "", errors.Wrap(things.ErrNotFound, err)
 		}
-		return "", errors.Wrap(ErrSelectDb, err)
+		return "", errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	return id, nil
@@ -198,7 +180,7 @@ func (tr thingRepository) RetrieveAll(ctx context.Context, owner string, offset,
 	nq, name := getNameQuery(name)
 	m, mq, err := getMetadataQuery(tm)
 	if err != nil {
-		return things.Page{}, errors.Wrap(ErrSelectDb, err)
+		return things.Page{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	q := fmt.Sprintf(`SELECT id, name, key, metadata FROM things
@@ -214,7 +196,7 @@ func (tr thingRepository) RetrieveAll(ctx context.Context, owner string, offset,
 
 	rows, err := tr.db.NamedQueryContext(ctx, q, params)
 	if err != nil {
-		return things.Page{}, errors.Wrap(ErrSelectDb, err)
+		return things.Page{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 	defer rows.Close()
 
@@ -222,12 +204,12 @@ func (tr thingRepository) RetrieveAll(ctx context.Context, owner string, offset,
 	for rows.Next() {
 		dbth := dbThing{Owner: owner}
 		if err := rows.StructScan(&dbth); err != nil {
-			return things.Page{}, errors.Wrap(ErrSelectDb, err)
+			return things.Page{}, errors.Wrap(things.ErrSelectEntity, err)
 		}
 
 		th, err := toThing(dbth)
 		if err != nil {
-			return things.Page{}, err
+			return things.Page{}, errors.Wrap(things.ErrViewEntity, err)
 		}
 
 		items = append(items, th)
@@ -237,7 +219,7 @@ func (tr thingRepository) RetrieveAll(ctx context.Context, owner string, offset,
 
 	total, err := total(ctx, tr.db, cq, params)
 	if err != nil {
-		return things.Page{}, errors.Wrap(ErrSelectDb, err)
+		return things.Page{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	page := things.Page{
@@ -305,7 +287,7 @@ func (tr thingRepository) RetrieveByChannel(ctx context.Context, owner, channel
 
 	rows, err := tr.db.NamedQueryContext(ctx, q, params)
 	if err != nil {
-		return things.Page{}, errors.Wrap(ErrSelectDb, err)
+		return things.Page{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 	defer rows.Close()
 
@@ -313,12 +295,12 @@ func (tr thingRepository) RetrieveByChannel(ctx context.Context, owner, channel
 	for rows.Next() {
 		dbth := dbThing{Owner: owner}
 		if err := rows.StructScan(&dbth); err != nil {
-			return things.Page{}, errors.Wrap(ErrSelectDb, err)
+			return things.Page{}, errors.Wrap(things.ErrSelectEntity, err)
 		}
 
 		th, err := toThing(dbth)
 		if err != nil {
-			return things.Page{}, err
+			return things.Page{}, errors.Wrap(things.ErrViewEntity, err)
 		}
 
 		items = append(items, th)
@@ -326,7 +308,7 @@ func (tr thingRepository) RetrieveByChannel(ctx context.Context, owner, channel
 
 	var total uint64
 	if err := tr.db.GetContext(ctx, &total, qc, owner, channel); err != nil {
-		return things.Page{}, errors.Wrap(ErrSelectDb, err)
+		return things.Page{}, errors.Wrap(things.ErrSelectEntity, err)
 	}
 
 	return things.Page{
@@ -346,7 +328,7 @@ func (tr thingRepository) Remove(ctx context.Context, owner, id string) error {
 	}
 	q := `DELETE FROM things WHERE id = :id AND owner = :owner;`
 	if _, err := tr.db.NamedExecContext(ctx, q, dbth); err != nil {
-		return errors.Wrap(ErrDeleteDb, err)
+		return errors.Wrap(things.ErrRemoveEntity, err)
 	}
 	return nil
 }
@@ -364,7 +346,7 @@ func toDBThing(th things.Thing) (dbThing, error) {
 	if len(th.Metadata) > 0 {
 		b, err := json.Marshal(th.Metadata)
 		if err != nil {
-			return dbThing{}, errors.Wrap(ErrMarshalThing, err)
+			return dbThing{}, errors.Wrap(things.ErrMalformedEntity, err)
 		}
 		data = b
 	}
@@ -381,7 +363,7 @@ func toDBThing(th things.Thing) (dbThing, error) {
 func toThing(dbth dbThing) (things.Thing, error) {
 	var metadata map[string]interface{}
 	if err := json.Unmarshal([]byte(dbth.Metadata), &metadata); err != nil {
-		return things.Thing{}, errors.Wrap(ErrUnmarshalThing, err)
+		return things.Thing{}, errors.Wrap(things.ErrMalformedEntity, err)
 	}
 
 	return things.Thing{
diff --git a/things/redis/channels.go b/things/redis/channels.go
index 7bfb3a86..6d42750b 100644
--- a/things/redis/channels.go
+++ b/things/redis/channels.go
@@ -14,17 +14,6 @@ import (
 
 const chanPrefix = "channel"
 
-var (
-	// ErrRedisConnectChannel indicates error while adding connection in redis cache
-	ErrRedisConnectChannel = errors.New("failed to add connection to redis cache")
-
-	// ErrRedisDisconnectChannel indicates error while removing connection from redis cache
-	ErrRedisDisconnectChannel = errors.New("failed to remove connection from redis cache")
-
-	// ErrRedisRemoveChannel indicates error while removing channel from redis cache
-	ErrRedisRemoveChannel = errors.New("failed to remove channel from redis cache")
-)
-
 var _ things.ChannelCache = (*channelCache)(nil)
 
 type channelCache struct {
@@ -39,7 +28,7 @@ func NewChannelCache(client *redis.Client) things.ChannelCache {
 func (cc channelCache) Connect(_ context.Context, chanID, thingID string) error {
 	cid, tid := kv(chanID, thingID)
 	if err := cc.client.SAdd(cid, tid).Err(); err != nil {
-		return errors.Wrap(ErrRedisConnectChannel, err)
+		return errors.Wrap(things.ErrConnect, err)
 	}
 	return nil
 }
@@ -52,7 +41,7 @@ func (cc channelCache) HasThing(_ context.Context, chanID, thingID string) bool
 func (cc channelCache) Disconnect(_ context.Context, chanID, thingID string) error {
 	cid, tid := kv(chanID, thingID)
 	if err := cc.client.SRem(cid, tid).Err(); err != nil {
-		return errors.Wrap(ErrRedisDisconnectChannel, err)
+		return errors.Wrap(things.ErrDisconnect, err)
 	}
 	return nil
 }
@@ -60,7 +49,7 @@ func (cc channelCache) Disconnect(_ context.Context, chanID, thingID string) err
 func (cc channelCache) Remove(_ context.Context, chanID string) error {
 	cid, _ := kv(chanID, "0")
 	if err := cc.client.Del(cid).Err(); err != nil {
-		return errors.Wrap(ErrRedisRemoveChannel, err)
+		return errors.Wrap(things.ErrRemoveEntity, err)
 	}
 	return nil
 }
diff --git a/things/redis/things.go b/things/redis/things.go
index 565e95e8..1d8db5f0 100644
--- a/things/redis/things.go
+++ b/things/redis/things.go
@@ -17,17 +17,6 @@ const (
 	idPrefix  = "thing"
 )
 
-var (
-	// ErrRedisThingSave indicates error while saving Thing in redis cache
-	ErrRedisThingSave = errors.New("failed to save thing in redis cache")
-
-	// ErrRedisThingID indicates error while geting Thing ID from redis cache
-	ErrRedisThingID = errors.New("failed to get thing id from redis cache")
-
-	// ErrRedisThingRemove indicates error while removing Thing from redis cache
-	ErrRedisThingRemove = errors.New("failed to remove thing from redis cache")
-)
-
 var _ things.ThingCache = (*thingCache)(nil)
 
 type thingCache struct {
@@ -44,12 +33,12 @@ func NewThingCache(client *redis.Client) things.ThingCache {
 func (tc *thingCache) Save(_ context.Context, thingKey string, thingID string) error {
 	tkey := fmt.Sprintf("%s:%s", keyPrefix, thingKey)
 	if err := tc.client.Set(tkey, thingID, 0).Err(); err != nil {
-		return errors.Wrap(ErrRedisThingSave, err)
+		return errors.Wrap(things.ErrCreateEntity, err)
 	}
 
 	tid := fmt.Sprintf("%s:%s", idPrefix, thingID)
 	if err := tc.client.Set(tid, thingKey, 0).Err(); err != nil {
-		return errors.Wrap(ErrRedisThingSave, err)
+		return errors.Wrap(things.ErrCreateEntity, err)
 	}
 	return nil
 }
@@ -58,7 +47,7 @@ func (tc *thingCache) ID(_ context.Context, thingKey string) (string, error) {
 	tkey := fmt.Sprintf("%s:%s", keyPrefix, thingKey)
 	thingID, err := tc.client.Get(tkey).Result()
 	if err != nil {
-		return "", errors.Wrap(ErrRedisThingID, err)
+		return "", errors.Wrap(things.ErrNotFound, err)
 	}
 
 	return thingID, nil
@@ -72,12 +61,12 @@ func (tc *thingCache) Remove(_ context.Context, thingID string) error {
 		return nil
 	}
 	if err != nil {
-		return errors.Wrap(ErrRedisThingRemove, err)
+		return errors.Wrap(things.ErrRemoveEntity, err)
 	}
 
 	tkey := fmt.Sprintf("%s:%s", keyPrefix, key)
 	if err := tc.client.Del(tkey, tid).Err(); err != nil {
-		return errors.Wrap(ErrRedisThingRemove, err)
+		return errors.Wrap(things.ErrRemoveEntity, err)
 	}
 	return nil
 }
diff --git a/things/service.go b/things/service.go
index 2c09503c..c49d78f8 100644
--- a/things/service.go
+++ b/things/service.go
@@ -12,34 +12,27 @@ import (
 )
 
 var (
-	// ErrMalformedEntity indicates malformed entity specification (e.g.
-	// invalid username or password).
-	ErrMalformedEntity = errors.New("malformed entity specification")
-
 	// ErrUnauthorizedAccess indicates missing or invalid credentials provided
 	// when accessing a protected resource.
 	ErrUnauthorizedAccess = errors.New("missing or invalid credentials provided")
 
-	// ErrNotFound indicates a non-existent entity request.
-	ErrNotFound = errors.New("non-existent entity")
-
-	// ErrConflict indicates that entity already exists.
-	ErrConflict = errors.New("entity already exists")
+	// ErrCreateUUID indicates error in creating uuid for entity creation
+	ErrCreateUUID = errors.New("uuid creation failed")
 
-	// ErrScanMetadata indicates problem with metadata in db
-	ErrScanMetadata = errors.New("failed to scan metadata")
+	// ErrCreateEntity indicates error in creating entity or entities
+	ErrCreateEntity = errors.New("create entity failed")
 
-	// ErrCreateThings indicates error in creating Thing
-	ErrCreateThings = errors.New("create thing failed")
+	// ErrUpdateEntity indicates error in updating entity or entities
+	ErrUpdateEntity = errors.New("update entity failed")
 
-	// ErrCreateChannels indicates error in creating Channel
-	ErrCreateChannels = errors.New("create channel failed")
+	// ErrViewEntity indicates error in viewing entity or entities
+	ErrViewEntity = errors.New("view entity failed")
 
-	// ErrRemoveThing indicates error in removing Thing
-	ErrRemoveThing = errors.New("remove thing failed")
+	// ErrRemoveEntity indicates error in removing entity
+	ErrRemoveEntity = errors.New("remove entity failed")
 
-	// ErrRemoveChannel indicates error in removing Channel
-	ErrRemoveChannel = errors.New("remove channel failed")
+	// ErrConnect indicates error in adding connection
+	ErrConnect = errors.New("add connection failed")
 
 	// ErrDisconnect indicates error in removing connection
 	ErrDisconnect = errors.New("remove connection failed")
@@ -153,13 +146,13 @@ func New(auth mainflux.AuthNServiceClient, things ThingRepository, channels Chan
 func (ts *thingsService) CreateThings(ctx context.Context, token string, things ...Thing) ([]Thing, error) {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return []Thing{}, ErrUnauthorizedAccess
+		return []Thing{}, errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	for i := range things {
 		things[i].ID, err = ts.uuidProvider.ID()
 		if err != nil {
-			return []Thing{}, errors.Wrap(ErrCreateThings, err)
+			return []Thing{}, errors.Wrap(ErrCreateUUID, err)
 		}
 
 		things[i].Owner = res.GetValue()
@@ -167,7 +160,7 @@ func (ts *thingsService) CreateThings(ctx context.Context, token string, things
 		if things[i].Key == "" {
 			things[i].Key, err = ts.uuidProvider.ID()
 			if err != nil {
-				return []Thing{}, errors.Wrap(ErrCreateThings, err)
+				return []Thing{}, errors.Wrap(ErrCreateUUID, err)
 			}
 		}
 	}
@@ -178,7 +171,7 @@ func (ts *thingsService) CreateThings(ctx context.Context, token string, things
 func (ts *thingsService) UpdateThing(ctx context.Context, token string, thing Thing) error {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ErrUnauthorizedAccess
+		return errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	thing.Owner = res.GetValue()
@@ -189,19 +182,18 @@ func (ts *thingsService) UpdateThing(ctx context.Context, token string, thing Th
 func (ts *thingsService) UpdateKey(ctx context.Context, token, id, key string) error {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ErrUnauthorizedAccess
+		return errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	owner := res.GetValue()
 
 	return ts.things.UpdateKey(ctx, owner, id, key)
-
 }
 
 func (ts *thingsService) ViewThing(ctx context.Context, token, id string) (Thing, error) {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return Thing{}, ErrUnauthorizedAccess
+		return Thing{}, errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	return ts.things.RetrieveByID(ctx, res.GetValue(), id)
@@ -232,7 +224,7 @@ func (ts *thingsService) RemoveThing(ctx context.Context, token, id string) erro
 	}
 
 	if err := ts.thingCache.Remove(ctx, id); err != nil {
-		return errors.Wrap(ErrRemoveThing, err)
+		return err
 	}
 	return ts.things.Remove(ctx, res.GetValue(), id)
 }
@@ -240,13 +232,13 @@ func (ts *thingsService) RemoveThing(ctx context.Context, token, id string) erro
 func (ts *thingsService) CreateChannels(ctx context.Context, token string, channels ...Channel) ([]Channel, error) {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return []Channel{}, ErrUnauthorizedAccess
+		return []Channel{}, errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	for i := range channels {
 		channels[i].ID, err = ts.uuidProvider.ID()
 		if err != nil {
-			return []Channel{}, errors.Wrap(ErrCreateChannels, err)
+			return []Channel{}, errors.Wrap(ErrCreateUUID, err)
 		}
 
 		channels[i].Owner = res.GetValue()
@@ -258,7 +250,7 @@ func (ts *thingsService) CreateChannels(ctx context.Context, token string, chann
 func (ts *thingsService) UpdateChannel(ctx context.Context, token string, channel Channel) error {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ErrUnauthorizedAccess
+		return errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	channel.Owner = res.GetValue()
@@ -268,7 +260,7 @@ func (ts *thingsService) UpdateChannel(ctx context.Context, token string, channe
 func (ts *thingsService) ViewChannel(ctx context.Context, token, id string) (Channel, error) {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return Channel{}, ErrUnauthorizedAccess
+		return Channel{}, errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	return ts.channels.RetrieveByID(ctx, res.GetValue(), id)
@@ -277,7 +269,7 @@ func (ts *thingsService) ViewChannel(ctx context.Context, token, id string) (Cha
 func (ts *thingsService) ListChannels(ctx context.Context, token string, offset, limit uint64, name string, m Metadata) (ChannelsPage, error) {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ChannelsPage{}, ErrUnauthorizedAccess
+		return ChannelsPage{}, errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	return ts.channels.RetrieveAll(ctx, res.GetValue(), offset, limit, name, m)
@@ -286,7 +278,7 @@ func (ts *thingsService) ListChannels(ctx context.Context, token string, offset,
 func (ts *thingsService) ListChannelsByThing(ctx context.Context, token, thing string, offset, limit uint64, connected bool) (ChannelsPage, error) {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ChannelsPage{}, ErrUnauthorizedAccess
+		return ChannelsPage{}, errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	return ts.channels.RetrieveByThing(ctx, res.GetValue(), thing, offset, limit, connected)
@@ -295,19 +287,20 @@ func (ts *thingsService) ListChannelsByThing(ctx context.Context, token, thing s
 func (ts *thingsService) RemoveChannel(ctx context.Context, token, id string) error {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ErrUnauthorizedAccess
+		return errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	if err := ts.channelCache.Remove(ctx, id); err != nil {
-		return errors.Wrap(ErrRemoveChannel, err)
+		return err
 	}
+
 	return ts.channels.Remove(ctx, res.GetValue(), id)
 }
 
 func (ts *thingsService) Connect(ctx context.Context, token string, chIDs, thIDs []string) error {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ErrUnauthorizedAccess
+		return errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	return ts.channels.Connect(ctx, res.GetValue(), chIDs, thIDs)
@@ -316,28 +309,33 @@ func (ts *thingsService) Connect(ctx context.Context, token string, chIDs, thIDs
 func (ts *thingsService) Disconnect(ctx context.Context, token, chanID, thingID string) error {
 	res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token})
 	if err != nil {
-		return ErrUnauthorizedAccess
+		return errors.Wrap(ErrUnauthorizedAccess, err)
 	}
 
 	if err := ts.channelCache.Disconnect(ctx, chanID, thingID); err != nil {
-		return errors.Wrap(ErrDisconnect, err)
+		return err
 	}
+
 	return ts.channels.Disconnect(ctx, res.GetValue(), chanID, thingID)
 }
 
-func (ts *thingsService) CanAccessByKey(ctx context.Context, chanID, key string) (string, error) {
-	thingID, err := ts.hasThing(ctx, chanID, key)
+func (ts *thingsService) CanAccessByKey(ctx context.Context, chanID, thingKey string) (string, error) {
+	thingID, err := ts.hasThing(ctx, chanID, thingKey)
 	if err == nil {
 		return thingID, nil
 	}
 
-	thingID, err = ts.channels.HasThing(ctx, chanID, key)
+	thingID, err = ts.channels.HasThing(ctx, chanID, thingKey)
 	if err != nil {
-		return "", ErrUnauthorizedAccess
+		return "", err
 	}
 
-	ts.thingCache.Save(ctx, key, thingID)
-	ts.channelCache.Connect(ctx, chanID, thingID)
+	if err := ts.thingCache.Save(ctx, thingKey, thingID); err != nil {
+		return "", err
+	}
+	if err := ts.channelCache.Connect(ctx, chanID, thingID); err != nil {
+		return "", err
+	}
 	return thingID, nil
 }
 
@@ -347,10 +345,12 @@ func (ts *thingsService) CanAccessByID(ctx context.Context, chanID, thingID stri
 	}
 
 	if err := ts.channels.HasThingByID(ctx, chanID, thingID); err != nil {
-		return ErrUnauthorizedAccess
+		return err
 	}
 
-	ts.channelCache.Connect(ctx, chanID, thingID)
+	if err := ts.channelCache.Connect(ctx, chanID, thingID); err != nil {
+		return err
+	}
 	return nil
 }
 
@@ -362,22 +362,23 @@ func (ts *thingsService) Identify(ctx context.Context, key string) (string, erro
 
 	id, err = ts.things.RetrieveByKey(ctx, key)
 	if err != nil {
-		return "", ErrUnauthorizedAccess
+		return "", err
 	}
 
-	ts.thingCache.Save(ctx, key, id)
+	if err := ts.thingCache.Save(ctx, key, id); err != nil {
+		return "", err
+	}
 	return id, nil
 }
 
-func (ts *thingsService) hasThing(ctx context.Context, chanID, key string) (string, error) {
-	thingID, err := ts.thingCache.ID(ctx, key)
+func (ts *thingsService) hasThing(ctx context.Context, chanID, thingKey string) (string, error) {
+	thingID, err := ts.thingCache.ID(ctx, thingKey)
 	if err != nil {
 		return "", err
 	}
 
 	if connected := ts.channelCache.HasThing(ctx, chanID, thingID); !connected {
-		return "", ErrUnauthorizedAccess
+		return "", ErrEntityConnected
 	}
-
 	return thingID, nil
 }
diff --git a/things/swagger.yaml b/things/swagger.yaml
index bd27f0fe..c3160bb8 100644
--- a/things/swagger.yaml
+++ b/things/swagger.yaml
@@ -1,12 +1,9 @@
-swagger: "2.0"
+openapi: 3.0.1
 info:
   title: Mainflux things service
   description: HTTP API for managing platform things and channels.
   version: "1.0.0"
-consumes:
-  - "application/json"
-produces:
-  - "application/json"
+
 paths:
   /things:
     post:
@@ -17,28 +14,32 @@ paths:
       tags:
         - things
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - name: thing
-          description: JSON-formatted document describing the new thing.
-          in: body
-          schema:
-            $ref: "#/definitions/CreateThingReq"
-          required: true
+        - $ref: "#/components/parameters/Authorization"
+      requestBody: 
+        $ref: "#/components/requestBodies/CreateThingReq"
       responses:
         201:
           description: Thing registered.
           headers:
             Location:
-              type: string
-              description: Created thing's relative URL (i.e. /things/{thingId}).
+              content:
+                text/plain:
+                  schema:
+                    type: string
+                    description: Created thing's relative URL.
+                    example: /things/{thingId}
         400:
           description: Failed due to malformed JSON.
-        403:
+        401:
           description: Missing or invalid access token provided.
+        409:
+          description: Entity already exist.
         415:
           description: Missing or invalid content type.
+        422:
+          description: Database can't process request.            
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
     get:
       summary: Retrieves managed things
       description: |
@@ -49,22 +50,28 @@ paths:
       tags:
         - things
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/Limit"
-        - $ref: "#/parameters/Offset"
-        - $ref: "#/parameters/Name"
-        - $ref: "#/parameters/Metadata"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/Limit"
+        - $ref: "#/components/parameters/Offset"
+        - $ref: "#/components/parameters/Name"
+        - $ref: "#/components/parameters/Metadata"
       responses:
         200:
           description: Data retrieved.
-          schema:
-            $ref: "#/definitions/ThingsPage"
+          content: 
+            application/json:
+              schema:
+                $ref: "#/components/schemas/ThingsPage"
         400:
           description: Failed due to malformed query parameters.
-        403:
+        401:
           description: Missing or invalid access token provided.
+        404:
+          description: A non-existent entity request.            
+        422:
+          description: Database can't process request.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /things/bulk:
     post:
       summary: Bulk provisions new things
@@ -74,67 +81,39 @@ paths:
       tags:
         - things
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - name: things
-          description: JSON-formatted document describing the new things.
-          in: body
-          schema:
-            $ref: "#/definitions/CreateThingsReq"
-          required: true
+        - $ref: "#/components/parameters/Authorization"
+      requestBody: 
+        $ref: "#/components/requestBodies/CreateThingsReq"      
       responses:
         201:
           description: Things registered.
         400:
           description: Failed due to malformed JSON.
-        403:
+        401:
           description: Missing or invalid access token provided.
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
-  /channels/{chanId}/things:
-    get:
-      summary: Retrieves list of things connected or not connected to specified channel
-      description: |
-        Retrieves list of things connected to specified channel with pagination
-        metadata.
-      tags:
-        - things
-      parameters:
-        - $ref: "#/parameters/ChanId"
-        - $ref: "#/parameters/Offset"
-        - $ref: "#/parameters/Limit"
-        - $ref: "#/parameters/Connected"
-      responses:
-        200:
-          description: Data retrieved.
-          schema:
-            $ref: "#/definitions/ThingsPage"
-        400:
-          description: Failed due to malformed query parameters.
-        403:
-          description: Missing or invalid access token provided.
-        500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /things/{thingId}:
     get:
       summary: Retrieves thing info
       tags:
         - things
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ThingId"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ThingId"
       responses:
         200:
-          description: Data retrieved.
-          schema:
-            $ref: "#/definitions/ThingRes"
-        403:
+          $ref: "#/components/responses/ThingRes"
+        401:
           description: Missing or invalid access token provided.
         404:
           description: Thing does not exist.
+        422:
+          description: Database can't process request.            
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
     put:
       summary: Updates thing info
       description: |
@@ -144,27 +123,23 @@ paths:
       tags:
         - things
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ThingId"
-        - name: thing
-          description: JSON-formatted document describing the updated thing.
-          in: body
-          schema:
-            $ref: "#/definitions/UpdateThingReq"
-          required: true
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ThingId"
+      requestBody:
+        $ref: "#/components/requestBodies/UpdateThingReq"
       responses:
         200:
           description: Thing updated.
         400:
           description: Failed due to malformed JSON.
-        403:
+        401:
           description: Missing or invalid access token provided.
         404:
           description: Thing does not exist.
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
     delete:
       summary: Removes a thing
       description: |
@@ -173,17 +148,17 @@ paths:
       tags:
         - things
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ThingId"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ThingId"
       responses:
         204:
           description: Thing removed.
         400:
           description: Failed due to malformed thing's ID.
-        403:
+        401:
           description: Missing or invalid access token provided.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /things/{thingId}/key:
     patch:
       summary: Updates thing key
@@ -192,20 +167,16 @@ paths:
       tags:
         - things
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ThingId"
-        - name: key
-          description: JSON-formatted document describing updated key.
-          in: body
-          schema:
-            $ref: "#/definitions/UpdateKeyReq"
-          required: true
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ThingId"
+      requestBody: 
+        $ref: "#/components/requestBodies/UpdateKeyReq"  
       responses:
         200:
           description: Thing key updated.
         400:
           description: Failed due to malformed JSON.
-        403:
+        401:
           description: Missing or invalid access token provided.
         404:
           description: Thing does not exist.
@@ -214,7 +185,7 @@ paths:
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /channels:
     post:
       summary: Creates new channel
@@ -224,28 +195,29 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - name: channel
-          description: JSON-formatted document describing the new channel.
-          in: body
-          schema:
-            $ref: "#/definitions/CreateChannelReq"
-          required: true
+        - $ref: "#/components/parameters/Authorization"
+      requestBody: 
+        $ref: "#/components/requestBodies/CreateChannelReq"  
       responses:
         201:
           description: Channel created.
           headers:
             Location:
-              type: string
-              description: Created channel's relative URL (i.e. /channels/{chanId}).
+              content:
+                text/plain:
+                  schema:
+                    type: string
+                    description: Created channel's relative URL (i.e. /channels/{chanId}).
         400:
           description: Failed due to malformed JSON.
-        403:
+        401:
           description: Missing or invalid access token provided.
+        409:
+          description: Entity already exist.            
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
     get:
       summary: Retrieves managed channels
       description: |
@@ -256,21 +228,25 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/Limit"
-        - $ref: "#/parameters/Offset"
-        - $ref: "#/parameters/Name"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/Limit"
+        - $ref: "#/components/parameters/Offset"
+        - $ref: "#/components/parameters/Name"
       responses:
         200:
           description: Data retrieved.
-          schema:
-            $ref: "#/definitions/ChannelsPage"
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/ChannelsPage"
         400:
           description: Failed due to malformed query parameters.
-        403:
+        401:
           description: Missing or invalid access token provided.
+        422:
+          description: Database can't process request.            
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /channels/bulk:
     post:
       summary: Bulk provisions new channels
@@ -280,43 +256,43 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - name: channels
-          description: JSON-formatted document describing the new channels.
-          in: body
-          schema:
-            $ref: "#/definitions/CreateChannelsReq"
-          required: true
+        - $ref: "#/components/parameters/Authorization"
+      requestBody: 
+        $ref: "#/components/requestBodies/CreateChannelsReq"  
       responses:
         201:
           description: Channels registered.
         400:
           description: Failed due to malformed JSON.
-        403:
+        401:
           description: Missing or invalid access token provided.
+        409:
+          description: Entity already exist.            
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /channels/{chanId}:
     get:
       summary: Retrieves channel info
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ChanId"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ChanId"
       responses:
         200:
-          description: Data retrieved.
-          schema:
-            $ref: "#/definitions/ChannelRes"
-        403:
+          $ref: "#/components/responses/ChannelRes"
+        400:
+          description: Failed due to malformed channel's ID.
+        401:
           description: Missing or invalid access token provided.
         404:
           description: Channel does not exist.
+        422:
+          description: Database can't process request.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
     put:
       summary: Updates channel info
       description: |
@@ -326,27 +302,23 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ChanId"
-        - name: channel
-          description: JSON-formatted document describing the updated channel.
-          in: body
-          schema:
-            $ref: "#/definitions/CreateChannelReq"
-          required: true
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ChanId"
+      requestBody: 
+        $ref: "#/components/requestBodies/CreateChannelReq"
       responses:
         200:
           description: Channel updated.
         400:
           description: Failed due to malformed JSON.
-        403:
+        401:
           description: Missing or invalid access token provided.
         404:
           description: Channel does not exist.
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
     delete:
       summary: Removes a channel
       description: |
@@ -355,17 +327,52 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ChanId"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ChanId"
       responses:
         204:
           description: Channel removed.
         400:
           description: Failed due to malformed channel's ID.
-        403:
+        401:
           description: Missing or invalid access token provided.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
+  /connect:
+    post:
+      summary: Connects thing and channel.
+      description: |
+        Connect things specified by IDs to channels specified by IDs.
+        Channel and thing are owned by user identified using the provided access token.
+      tags:
+        - things
+      parameters:
+        - $ref: "#/components/parameters/Authorization"
+      requestBody: 
+        $ref: "#/components/requestBodies/CreateConnectionReq"
+      responses:
+        201:
+          description: Thing registered.
+          headers:
+            Location:
+              content:
+                text/plain:
+                  schema:
+                    type: string
+                    description: Created thing's relative URL.
+                    example: /things/{thingId}
+        400:
+          description: Failed due to malformed JSON.
+        401:
+          description: Missing or invalid access token provided.
+        404:
+          description: A non-existent entity request.
+        409:
+          description: Entity already exist.            
+        415:
+          description: Missing or invalid content type.
+        500:
+          $ref: "#/components/responses/ServiceError"          
   /things/{thingId}/channels:
     get:
       summary: Retrieves list of channels connected or not connected to specified thing
@@ -375,21 +382,57 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/ThingId"
-        - $ref: "#/parameters/Offset"
-        - $ref: "#/parameters/Limit"
-        - $ref: "#/parameters/Connected"
+        - $ref: "#/components/parameters/ThingId"
+        - $ref: "#/components/parameters/Offset"
+        - $ref: "#/components/parameters/Limit"
+        - $ref: "#/components/parameters/Connected"
       responses:
         200:
           description: Data retrieved.
-          schema:
-            $ref: "#/definitions/ChannelsPage"
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/ChannelsPage"
         400:
           description: Failed due to malformed query parameters.
-        403:
+        401:
           description: Missing or invalid access token provided.
+        404:
+          description: Thing does not exist.
+        422:
+          description: Database can't process request.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
+  /channels/{chanId}/things:
+    get:
+      summary: Retrieves list of things connected or not connected to specified channel
+      description: |
+        Retrieves list of things connected to specified channel with pagination
+        metadata.
+      tags:
+        - things
+      parameters:
+        - $ref: "#/components/parameters/ChanId"
+        - $ref: "#/components/parameters/Offset"
+        - $ref: "#/components/parameters/Limit"
+        - $ref: "#/components/parameters/Connected"
+      responses:
+        200:
+          description: Data retrieved.
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/ThingsPage"
+        400:
+          description: Failed due to malformed query parameters.
+        401:
+          description: Missing or invalid access token provided.
+        404:
+          description: A non-existent entity request.
+        422:
+          description: Database can't process request.            
+        500:
+          $ref: "#/components/responses/ServiceError"          
   /channels/{chanId}/things/{thingId}:
     put:
       summary: Connects the thing to the channel
@@ -399,18 +442,20 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ChanId"
-        - $ref: "#/parameters/ThingId"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ChanId"
+        - $ref: "#/components/parameters/ThingId"
       responses:
         200:
           description: Thing connected.
-        403:
+        400:
+          description: Failed due to malformed query parameters.            
+        401:
           description: Missing or invalid access token provided.
         404:
           description: Channel or thing does not exist.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
     delete:
       summary: Disconnects the thing from the channel
       description: |
@@ -419,18 +464,20 @@ paths:
       tags:
         - channels
       parameters:
-        - $ref: "#/parameters/Authorization"
-        - $ref: "#/parameters/ChanId"
-        - $ref: "#/parameters/ThingId"
+        - $ref: "#/components/parameters/Authorization"
+        - $ref: "#/components/parameters/ChanId"
+        - $ref: "#/components/parameters/ThingId"
       responses:
         204:
           description: Thing disconnected.
-        403:
+        400:
+          description: Failed due to malformed query parameters.            
+        401:
           description: Missing or invalid access token provided.
         404:
           description: Channel or thing does not exist.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /channels/{chanId}/access:
     post:
       summary: Checks if thing has access to a channel.
@@ -440,27 +487,25 @@ paths:
       tags:
         - access
       parameters:
-        - $ref: "#/parameters/ChanId"
-        - name: token
-          description: JSON-formatted document that contains thing key.
-          in: body
-          schema:
-            $ref: "#/definitions/IdentityReq"
-          required: true
+        - $ref: "#/components/parameters/ChanId"
+      requestBody: 
+        $ref: "#/components/requestBodies/IdentityReq"  
       responses:
         200:
           description: |
             Thing has access to the specified channel and the thing ID is returned.
-          schema:
-            $ref: "#/definitions/Identity"
-        403:
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Identity"
+        401:
           description: |
             Thing and channel are not connected, or thing with specified key doesn't
             exist.
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /channels/{chanId}/access-by-id:
     post:
       summary: Checks if thing has access to a channel.
@@ -470,24 +515,20 @@ paths:
       tags:
         - access
       parameters:
-        - $ref: "#/parameters/ChanId"
-        - name: token
-          description: JSON-formatted document that contains thing key.
-          in: body
-          schema:
-            $ref: "#/definitions/AccessByIDReq"
-          required: true
+        - $ref: "#/components/parameters/ChanId"
+      requestBody: 
+        $ref: "#/components/requestBodies/AccessByIDReq"
       responses:
         200:
           description: Thing has access to the specified channel.
-        403:
+        401:
           description: |
             Thing and channel are not connected, or thing with specified ID doesn't
             exist.
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
+          $ref: "#/components/responses/ServiceError"
   /identify:
     post:
       summary: Validates thing's key and returns it's ID if key is valid.
@@ -496,239 +537,330 @@ paths:
         and is valid.
       tags:
         - identity
-      parameters:
-        - name: token
-          description: JSON-formatted document that contains thing key.
-          in: body
-          schema:
-            $ref: "#/definitions/IdentityReq"
-          required: true
+      requestBody: 
+        $ref: "#/components/requestBodies/IdentityReq"
       responses:
         200:
           description: Thing ID returned.
-          schema:
-            $ref: "#/definitions/Identity"
-        403:
+          content:
+            application/json:
+              schema:
+                $ref: "#/components/schemas/Identity"
+        401:
           description: Thing with specified key doesn't exist.
         415:
           description: Missing or invalid content type.
         500:
-          $ref: "#/responses/ServiceError"
-
-parameters:
-  Authorization:
-    name: Authorization
-    description: User's access token.
-    in: header
-    type: string
-    required: true
-  ChanId:
-    name: chanId
-    description: Unique channel identifier.
-    in: path
-    type: integer
-    minimum: 1
-    required: true
-  ThingId:
-    name: thingId
-    description: Unique thing identifier.
-    in: path
-    type: integer
-    minimum: 1
-    required: true
-  Limit:
-    name: limit
-    description: Size of the subset to retrieve.
-    in: query
-    type: integer
-    default: 10
-    maximum: 100
-    minimum: 1
-    required: false
-  Offset:
-    name: offset
-    description: Number of items to skip during retrieval.
-    in: query
-    type: integer
-    default: 0
-    minimum: 0
-    required: false
-  Connected:
-    name: connected
-    description: Connection state of the subset to retrieve.
-    in: query
-    type: boolean
-    default: true
-    required: false
-  Name:
-    name: name
-    description: Name filter. Filtering is performed as a case-insensitive partial match.
-    in: query
-    type: string
-    minimum: 0
-    required: false
-  Metadata:
-    name: metadata
-    description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
-    in: query
-    type: string
-    minimum: 0
-    required: false
-
-responses:
-  ServiceError:
-    description: Unexpected server-side error occurred.
+          $ref: "#/components/responses/ServiceError"              
+        
+        
+components:
+  schemas:
+    Key:
+      type: string
+      description: |
+        Thing key that is used for thing auth. If there is
+        not one provided service will generate one in UUID
+        format.
+    Identity:
+      type: object
+      properties:
+        id:
+          type: string
+          description: Thing unique identifier.
+    ThingReqSchema:
+      type: object
+      properties:
+        key:
+          $ref: "#/components/schemas/Key"
+        name:
+          type: string
+          description: Free-form thing name.
+        metadata:
+          type: object
+          description: Arbitrary, object-encoded thing's data.
+    ThingResSchema:        
+      type: object
+      properties:
+        id:
+          type: string
+          description: Unique thing identifier generated by the service.
+        name:
+          type: string
+          description: Free-form thing name.
+        key:
+          type: string
+          description: Auto-generated access key.
+        metadata:
+          type: object
+          description: Arbitrary, object-encoded thing's data.
+      required:
+        - id
+        - type
+        - key
+    ThingsPage:
+      type: object
+      properties:
+        things:
+          type: array
+          minItems: 0
+          uniqueItems: true
+          items:
+            $ref: "#/components/schemas/ThingResSchema"
+        total:
+          type: integer
+          description: Total number of items.
+        offset:
+          type: integer
+          description: Number of items to skip during retrieval.
+        limit:
+          type: integer
+          description: Maximum number of items to return in one page.
+      required:
+        - things        
+    ChannelReqSchema:
+      type: object
+      properties:
+        name:
+          type: string
+          description: Free-form channel name.
+        metadata:
+          type: object
+          description: Arbitrary, object-encoded channel's data. 
+    ChannelResSchema:      
+      type: object
+      properties:
+        id:
+          type: string
+          description: Unique channel identifier generated by the service.
+        name:
+          type: string
+          description: Free-form channel name.
+        metadata:
+          type: object
+          description: Arbitrary, object-encoded channel's data.
+      required:
+        - id
+    ChannelsPage:
+      type: object
+      properties:
+        channels:
+          type: array
+          minItems: 0
+          uniqueItems: true
+          items:
+            $ref: "#/components/schemas/ChannelResSchema"
+        total:
+          type: integer
+          description: Total number of items.
+        offset:
+          type: integer
+          description: Number of items to skip during retrieval.
+        limit:
+          type: integer
+          description: Maximum number of items to return in one page.
+      required:
+        - channels
+    ConnectionReqSchema:
+      type: object
+      properties:
+        key:
+          $ref: "#/components/schemas/Key"
+        channel_ids:
+          type: array
+          description: Channel IDs.      
+          items:
+            type: string
+        thing_ids:
+          type: array
+          description: Thing IDs
+          items:
+            type: string
 
-definitions:
-  Key:
-    type: string
-    description: |
-      Thing key that is used for thing auth. If there is
-      not one provided service will generate one in UUID
-      format.
-  ChannelsPage:
-    type: object
-    properties:
-      channels:
-        type: array
-        minItems: 0
-        uniqueItems: true
-        items:
-          $ref: "#/definitions/ChannelRes"
-      total:
-        type: integer
-        description: Total number of items.
-      offset:
-        type: integer
-        description: Number of items to skip during retrieval.
-      limit:
-        type: integer
-        description: Maximum number of items to return in one page.
-    required:
-      - channels
-  ChannelRes:
-    type: object
-    properties:
-      id:
+  parameters:
+    Authorization:
+      name: Authorization
+      description: User's access token.
+      in: header
+      schema:
         type: string
-        description: Unique channel identifier generated by the service.
-      name:
-        type: string
-        description: Free-form channel name.
-      metadata:
-        type: object
-        description: Arbitrary, object-encoded channel's data.
-    required:
-      - id
-  CreateChannelReq:
-    type: object
-    properties:
-      name:
+      required: true
+    ChanId:
+      name: chanId
+      description: Unique channel identifier.
+      in: path
+      schema:      
         type: string
-        description: Free-form channel name.
-      metadata:
-        type: object
-        description: Arbitrary, object-encoded channel's data.
-  CreateChannelsReq:
-    type: object
-    properties:
-      key:
-        $ref: "#/definitions/Key"
-      things:
-        type: array
-        items: 
-          $ref: "#/definitions/CreateChannelReq"        
-  ThingsPage:
-    type: object
-    properties:
-      things:
-        type: array
-        minItems: 0
-        uniqueItems: true
-        items:
-          $ref: "#/definitions/ThingRes"
-      total:
+      required: true
+    ThingId:
+      name: thingId
+      description: Unique thing identifier.
+      in: path
+      schema:
         type: integer
-        description: Total number of items.
-      offset:
+        minimum: 1
+      required: true
+    Limit:
+      name: limit
+      description: Size of the subset to retrieve.
+      in: query
+      schema:      
         type: integer
-        description: Number of items to skip during retrieval.
-      limit:
+        default: 10
+        maximum: 100
+        minimum: 1
+      required: false
+    Offset:
+      name: offset
+      description: Number of items to skip during retrieval.
+      in: query
+      schema:      
         type: integer
-        description: Maximum number of items to return in one page.
-    required:
-      - things
-  ThingRes:
-    type: object
-    properties:
-      id:
-        type: string
-        description: Unique thing identifier generated by the service.
-      name:
+        default: 0
+        minimum: 0
+      required: false
+    Connected:
+      name: connected
+      description: Connection state of the subset to retrieve.
+      in: query
+      schema:      
+        type: boolean
+        default: true
+      required: false
+    Name:
+      name: name
+      description: Name filter. Filtering is performed as a case-insensitive partial match.
+      in: query
+      schema:      
         type: string
-        description: Free-form thing name.
-      key:
-        type: string
-        description: Auto-generated access key.
-      metadata:
+        format: byte
+      required: false
+    Metadata:
+      name: metadata
+      description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
+      in: query
+      required: false
+      schema:
         type: object
-        description: Arbitrary, object-encoded thing's data.
-    required:
-      - id
-      - type
-      - key
-  CreateThingReq:
-    type: object
-    properties:
-      key:
-        $ref: "#/definitions/Key"
-      name:
-        type: string
-        description: Free-form thing name.
-      metadata:
-        type: object
-        description: Arbitrary, object-encoded thing's data.
-  CreateThingsReq:
-    type: object
-    properties:
-      key:
-        $ref: "#/definitions/Key"
-      things:
-        type: array
-        items: 
-          $ref: "#/definitions/CreateThingReq"
-  UpdateThingReq:
-    type: object
-    properties:
-      name:
-        type: string
-        description: Free-form thing name.
-      metadata:
-        type: object
-        description: Arbitrary, object-encoded thing's data.
-  UpdateKeyReq:
-    type: object
-    properties:
-      key:
-        type: string
-        description: Thing key that is used for thing auth.
-  IdentityReq:
-    type: object
-    properties:
-      token:
-        type: string
-        description: Thing key that is used for thing auth.
-    required:
-      - token
-  AccessByIDReq:
-    type: object
-    properties:
-      thing_id:
-        type: string
-        description: Thing ID by which thing is uniquely identified.
-  Identity:
-    type: object
-    properties:
-      id:
-        type: string
-        description: Thing unique identifier.
+        additionalProperties: {}
+
+  requestBodies:
+    CreateThingReq:
+      description: JSON-formatted document describing the new thing.
+      required: true
+      content:
+        application/json:
+          schema:
+           $ref: "#/components/schemas/ThingReqSchema"
+    CreateThingsReq:
+      description: JSON-formatted document describing the new things.
+      required: true
+      content:
+        application/json:
+          schema:
+            type: object
+            properties:
+              key:
+                $ref: "#/components/schemas/Key"            
+              things:
+                type: array
+                items: 
+                  $ref: "#/components/schemas/ThingReqSchema"
+    UpdateThingReq:
+      description: Arbitrary, object-encoded thing's data.
+      required: true
+      content:
+        application/json:
+          schema:
+            type: object
+            properties:
+              name:
+                type: string
+                description: Free-form thing name.
+              metadata:
+                type: object
+    UpdateKeyReq:
+      required: true
+      description: JSON containing thing.
+      content:
+        application/json:
+          schema:
+            type: object
+            properties:
+              key:
+                type: string
+                description: Thing key that is used for thing auth.
+    CreateChannelReq:
+      description: JSON-formatted document describing the updated channel.
+      required: true
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ChannelReqSchema"
+    CreateChannelsReq:
+      description: JSON-formatted document describing the new channels.
+      required: true
+      content:
+        application/json:
+          schema:
+            type: object
+            properties:    
+              key:
+                $ref: "#/components/schemas/Key"
+              things:
+                type: array
+                items: 
+                  $ref: "#/components/schemas/ChannelReqSchema"
+    CreateConnectionReq:
+      description: JSON-formatted document describing the new connection.
+      required: true
+      content:
+        application/json:
+          schema:
+           $ref: "#/components/schemas/ConnectionReqSchema"
+    IdentityReq:
+      description: JSON-formatted document that contains thing key.
+      required: true
+      content:
+        application/json:
+          schema:
+            type: object
+            properties:
+              token:
+                type: string
+                description: Thing key that is used for thing auth.
+            required:
+              - token
+    AccessByIDReq:
+      description: JSON-formatted document that contains thing key.
+      required: true
+      content:
+        application/json:
+          schema:      
+            type: object
+            properties:
+              thing_id:
+                type: string
+                description: Thing ID by which thing is uniquely identified.
+
+  responses:
+    ServiceError:
+      description: Unexpected server-side error occurred.
+      content:
+        application/json:
+          schema:
+            type: string
+            format: byte
+
+    ThingRes:
+      description: Data retrieved.
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ThingResSchema"
+    ChannelRes:
+      description: Data retrieved.
+      content:
+        application/json:
+          schema:
+            $ref: "#/components/schemas/ChannelResSchema"
diff --git a/things/things.go b/things/things.go
index fe5e4ae4..2678c544 100644
--- a/things/things.go
+++ b/things/things.go
@@ -5,6 +5,29 @@ package things
 
 import (
 	"context"
+
+	"github.com/mainflux/mainflux/pkg/errors"
+)
+
+var (
+	// ErrMalformedEntity indicates malformed entity specification (e.g.
+	// invalid username or password).
+	ErrMalformedEntity = errors.New("malformed entity specification")
+
+	// ErrNotFound indicates a non-existent entity request.
+	ErrNotFound = errors.New("non-existent entity")
+
+	// ErrConflict indicates that entity already exists.
+	ErrConflict = errors.New("entity already exists")
+
+	// ErrScanMetadata indicates problem with metadata in db
+	ErrScanMetadata = errors.New("failed to scan metadata in db")
+
+	// ErrSelectEntity indicates error while reading entity from database
+	ErrSelectEntity = errors.New("select entity from db error")
+
+	// ErrEntityConnected indicates error while checking connection in database
+	ErrEntityConnected = errors.New("check thing-channel connection in database error")
 )
 
 // Metadata to be used for mainflux thing or channel for customized
diff --git a/twins/api/http/transport.go b/twins/api/http/transport.go
index 57f8e4c2..6da6f8c3 100644
--- a/twins/api/http/transport.go
+++ b/twins/api/http/transport.go
@@ -6,12 +6,13 @@ package http
 import (
 	"context"
 	"encoding/json"
-	"errors"
 	"io"
 	"net/http"
 	"strconv"
 	"strings"
 
+	"github.com/mainflux/mainflux/pkg/errors"
+
 	kitot "github.com/go-kit/kit/tracing/opentracing"
 	kithttp "github.com/go-kit/kit/transport/http"
 	"github.com/go-zoo/bone"
@@ -280,7 +281,7 @@ func readMetadataQuery(r *http.Request, key string) (map[string]interface{}, err
 	m := make(map[string]interface{})
 	err := json.Unmarshal([]byte(vals[0]), &m)
 	if err != nil {
-		return nil, err
+		return nil, errInvalidQueryParams
 	}
 
 	return m, nil


Test patch:
diff --git a/pkg/sdk/go/channels_test.go b/pkg/sdk/go/channels_test.go
index aa91cd41..95287f70 100644
--- a/pkg/sdk/go/channels_test.go
+++ b/pkg/sdk/go/channels_test.go
@@ -54,14 +54,14 @@ func TestCreateChannel(t *testing.T) {
 			desc:    "create new channel with empty token",
 			channel: channel,
 			token:   "",
-			err:     createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			empty:   true,
 		},
 		{
 			desc:    "create new channel with invalid token",
 			channel: channel,
 			token:   wrongValue,
-			err:     createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			empty:   true,
 		},
 		{
@@ -126,14 +126,14 @@ func TestCreateChannels(t *testing.T) {
 			desc:     "create new channels with empty token",
 			channels: channels,
 			token:    "",
-			err:      createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			res:      []sdk.Channel{},
 		},
 		{
 			desc:     "create new channels with invalid token",
 			channels: channels,
 			token:    wrongValue,
-			err:      createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			res:      []sdk.Channel{},
 		},
 	}
@@ -189,7 +189,7 @@ func TestChannel(t *testing.T) {
 			desc:     "get channel with invalid token",
 			chanID:   id,
 			token:    "",
-			err:      createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response: sdk.Channel{},
 		},
 	}
@@ -244,7 +244,7 @@ func TestChannels(t *testing.T) {
 			token:    wrongValue,
 			offset:   0,
 			limit:    5,
-			err:      createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response: nil,
 		},
 		{
@@ -252,7 +252,7 @@ func TestChannels(t *testing.T) {
 			token:    "",
 			offset:   0,
 			limit:    5,
-			err:      createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response: nil,
 		},
 		{
@@ -366,7 +366,7 @@ func TestChannelsByThing(t *testing.T) {
 			offset:    0,
 			limit:     5,
 			connected: true,
-			err:       createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:       createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response:  nil,
 		},
 		{
@@ -376,7 +376,7 @@ func TestChannelsByThing(t *testing.T) {
 			offset:    0,
 			limit:     5,
 			connected: true,
-			err:       createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:       createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response:  nil,
 		},
 		{
@@ -483,13 +483,13 @@ func TestUpdateChannel(t *testing.T) {
 			desc:    "update channel with invalid token",
 			channel: sdk.Channel{ID: id, Name: "test2"},
 			token:   wrongValue,
-			err:     createError(sdk.ErrFailedUpdate, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedUpdate, http.StatusUnauthorized),
 		},
 		{
 			desc:    "update channel with empty token",
 			channel: sdk.Channel{ID: id, Name: "test2"},
 			token:   "",
-			err:     createError(sdk.ErrFailedUpdate, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedUpdate, http.StatusUnauthorized),
 		},
 	}
 
@@ -526,7 +526,7 @@ func TestDeleteChannel(t *testing.T) {
 			desc:   "delete channel with invalid token",
 			chanID: id,
 			token:  wrongValue,
-			err:    createError(sdk.ErrFailedRemoval, http.StatusForbidden),
+			err:    createError(sdk.ErrFailedRemoval, http.StatusUnauthorized),
 		},
 		{
 			desc:   "delete non-existing channel",
@@ -544,7 +544,7 @@ func TestDeleteChannel(t *testing.T) {
 			desc:   "delete channel with empty token",
 			chanID: id,
 			token:  "",
-			err:    createError(sdk.ErrFailedRemoval, http.StatusForbidden),
+			err:    createError(sdk.ErrFailedRemoval, http.StatusUnauthorized),
 		},
 		{
 			desc:   "delete existing channel",
diff --git a/pkg/sdk/go/things_test.go b/pkg/sdk/go/things_test.go
index 3abebe89..244e5a77 100644
--- a/pkg/sdk/go/things_test.go
+++ b/pkg/sdk/go/things_test.go
@@ -98,14 +98,14 @@ func TestCreateThing(t *testing.T) {
 			desc:     "create new thing with empty token",
 			thing:    thing,
 			token:    "",
-			err:      createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			location: "",
 		},
 		{
 			desc:     "create new thing with invalid token",
 			thing:    thing,
 			token:    wrongValue,
-			err:      createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			location: "",
 		},
 	}
@@ -163,14 +163,14 @@ func TestCreateThings(t *testing.T) {
 			desc:   "create new thing with empty token",
 			things: things,
 			token:  "",
-			err:    createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:    createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			res:    []sdk.Thing{},
 		},
 		{
 			desc:   "create new thing with invalid token",
 			things: things,
 			token:  wrongValue,
-			err:    createError(sdk.ErrFailedCreation, http.StatusForbidden),
+			err:    createError(sdk.ErrFailedCreation, http.StatusUnauthorized),
 			res:    []sdk.Thing{},
 		},
 	}
@@ -228,7 +228,7 @@ func TestThing(t *testing.T) {
 			desc:     "get thing with invalid token",
 			thID:     id,
 			token:    wrongValue,
-			err:      createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response: sdk.Thing{},
 		},
 	}
@@ -286,7 +286,7 @@ func TestThings(t *testing.T) {
 			token:    wrongValue,
 			offset:   0,
 			limit:    5,
-			err:      createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response: nil,
 		},
 		{
@@ -294,7 +294,7 @@ func TestThings(t *testing.T) {
 			token:    "",
 			offset:   0,
 			limit:    5,
-			err:      createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:      createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response: nil,
 		},
 		{
@@ -412,7 +412,7 @@ func TestThingsByChannel(t *testing.T) {
 			offset:    0,
 			limit:     5,
 			connected: true,
-			err:       createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:       createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response:  nil,
 		},
 		{
@@ -422,7 +422,7 @@ func TestThingsByChannel(t *testing.T) {
 			offset:    0,
 			limit:     5,
 			connected: true,
-			err:       createError(sdk.ErrFailedFetch, http.StatusForbidden),
+			err:       createError(sdk.ErrFailedFetch, http.StatusUnauthorized),
 			response:  nil,
 		},
 		{
@@ -545,7 +545,7 @@ func TestUpdateThing(t *testing.T) {
 				Metadata: metadata2,
 			},
 			token: wrongValue,
-			err:   createError(sdk.ErrFailedUpdate, http.StatusForbidden),
+			err:   createError(sdk.ErrFailedUpdate, http.StatusUnauthorized),
 		},
 		{
 			desc: "update channel with empty token",
@@ -555,7 +555,7 @@ func TestUpdateThing(t *testing.T) {
 				Metadata: metadata2,
 			},
 			token: "",
-			err:   createError(sdk.ErrFailedUpdate, http.StatusForbidden),
+			err:   createError(sdk.ErrFailedUpdate, http.StatusUnauthorized),
 		},
 	}
 
@@ -592,7 +592,7 @@ func TestDeleteThing(t *testing.T) {
 			desc:    "delete thing with invalid token",
 			thingID: id,
 			token:   wrongValue,
-			err:     createError(sdk.ErrFailedRemoval, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedRemoval, http.StatusUnauthorized),
 		},
 		{
 			desc:    "delete non-existing thing",
@@ -610,7 +610,7 @@ func TestDeleteThing(t *testing.T) {
 			desc:    "delete thing with empty token",
 			thingID: id,
 			token:   "",
-			err:     createError(sdk.ErrFailedRemoval, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedRemoval, http.StatusUnauthorized),
 		},
 		{
 			desc:    "delete existing thing",
@@ -708,14 +708,14 @@ func TestConnectThing(t *testing.T) {
 			thingID: thingID,
 			chanID:  chanID1,
 			token:   wrongValue,
-			err:     createError(sdk.ErrFailedConnect, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedConnect, http.StatusUnauthorized),
 		},
 		{
 			desc:    "connect existing thing to existing channel with empty token",
 			thingID: thingID,
 			chanID:  chanID1,
 			token:   "",
-			err:     createError(sdk.ErrFailedConnect, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedConnect, http.StatusUnauthorized),
 		},
 		{
 			desc:    "connect thing from owner to channel of other user",
@@ -812,14 +812,14 @@ func TestConnect(t *testing.T) {
 			thingID: thingID,
 			chanID:  chanID1,
 			token:   wrongValue,
-			err:     createError(sdk.ErrFailedConnect, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedConnect, http.StatusUnauthorized),
 		},
 		{
 			desc:    "connect existing things to existing channels with empty token",
 			thingID: thingID,
 			chanID:  chanID1,
 			token:   emptyValue,
-			err:     createError(sdk.ErrFailedConnect, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedConnect, http.StatusUnauthorized),
 		},
 		{
 			desc:    "connect things from owner to channels of other user",
@@ -923,14 +923,14 @@ func TestDisconnectThing(t *testing.T) {
 			thingID: thingID,
 			chanID:  chanID1,
 			token:   wrongValue,
-			err:     createError(sdk.ErrFailedDisconnect, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedDisconnect, http.StatusUnauthorized),
 		},
 		{
 			desc:    "disconnect existing thing from existing channel with empty token",
 			thingID: thingID,
 			chanID:  chanID1,
 			token:   "",
-			err:     createError(sdk.ErrFailedDisconnect, http.StatusForbidden),
+			err:     createError(sdk.ErrFailedDisconnect, http.StatusUnauthorized),
 		},
 		{
 			desc:    "disconnect owner's thing from someone elses channel",
diff --git a/things/api/auth/grpc/endpoint_test.go b/things/api/auth/grpc/endpoint_test.go
index f27bfc07..d2a209c2 100644
--- a/things/api/auth/grpc/endpoint_test.go
+++ b/things/api/auth/grpc/endpoint_test.go
@@ -15,6 +15,7 @@ import (
 	"github.com/mainflux/mainflux/things"
 	grpcapi "github.com/mainflux/mainflux/things/api/auth/grpc"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -28,16 +29,20 @@ var (
 )
 
 func TestCanAccessByKey(t *testing.T) {
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	oth := sths[0]
-	sths, _ = svc.CreateThings(context.Background(), token, thing)
-	cth := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
-	svc.Connect(context.Background(), token, []string{sch.ID}, []string{cth.ID})
+	ths, err := svc.CreateThings(context.Background(), token, thing, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th1 := ths[0]
+	th2 := ths[1]
+
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
+	err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th1.ID})
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 
 	usersAddr := fmt.Sprintf("localhost:%d", port)
-	conn, _ := grpc.Dial(usersAddr, grpc.WithInsecure())
+	conn, err := grpc.Dial(usersAddr, grpc.WithInsecure())
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 	cli := grpcapi.NewClient(conn, mocktracer.New(), time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	defer cancel()
@@ -49,25 +54,25 @@ func TestCanAccessByKey(t *testing.T) {
 		code    codes.Code
 	}{
 		"check if connected thing can access existing channel": {
-			key:     cth.Key,
-			chanID:  sch.ID,
-			thingID: cth.ID,
+			key:     th1.Key,
+			chanID:  ch.ID,
+			thingID: th1.ID,
 			code:    codes.OK,
 		},
 		"check if unconnected thing can access existing channel": {
-			key:     oth.Key,
-			chanID:  sch.ID,
+			key:     th2.Key,
+			chanID:  ch.ID,
 			thingID: wrongID,
 			code:    codes.PermissionDenied,
 		},
 		"check if thing with wrong access key can access existing channel": {
 			key:     wrong,
-			chanID:  sch.ID,
+			chanID:  ch.ID,
 			thingID: wrongID,
-			code:    codes.PermissionDenied,
+			code:    codes.NotFound,
 		},
 		"check if connected thing can access non-existent channel": {
-			key:     cth.Key,
+			key:     th1.Key,
 			chanID:  wrongID,
 			thingID: wrongID,
 			code:    codes.InvalidArgument,
@@ -84,16 +89,21 @@ func TestCanAccessByKey(t *testing.T) {
 }
 
 func TestCanAccessByID(t *testing.T) {
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	oth := sths[0]
-	sths, _ = svc.CreateThings(context.Background(), token, thing)
-	cth := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
-	svc.Connect(context.Background(), token, []string{sch.ID}, []string{cth.ID})
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th1 := ths[0]
+	ths, err = svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th2 := ths[0]
+
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
+	svc.Connect(context.Background(), token, []string{ch.ID}, []string{th2.ID})
 
 	usersAddr := fmt.Sprintf("localhost:%d", port)
-	conn, _ := grpc.Dial(usersAddr, grpc.WithInsecure())
+	conn, err := grpc.Dial(usersAddr, grpc.WithInsecure())
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 	cli := grpcapi.NewClient(conn, mocktracer.New(), time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	defer cancel()
@@ -104,28 +114,28 @@ func TestCanAccessByID(t *testing.T) {
 		code    codes.Code
 	}{
 		"check if connected thing can access existing channel": {
-			chanID:  sch.ID,
-			thingID: cth.ID,
+			chanID:  ch.ID,
+			thingID: th2.ID,
 			code:    codes.OK,
 		},
 		"check if unconnected thing can access existing channel": {
-			chanID:  sch.ID,
-			thingID: oth.ID,
+			chanID:  ch.ID,
+			thingID: th1.ID,
 			code:    codes.PermissionDenied,
 		},
 		"check if connected thing can access non-existent channel": {
 			chanID:  wrongID,
-			thingID: cth.ID,
+			thingID: th2.ID,
 			code:    codes.InvalidArgument,
 		},
 		"check if thing with empty ID can access existing channel": {
-			chanID:  sch.ID,
+			chanID:  ch.ID,
 			thingID: "",
 			code:    codes.InvalidArgument,
 		},
 		"check if connected thing can access channel with empty ID": {
 			chanID:  "",
-			thingID: cth.ID,
+			thingID: th2.ID,
 			code:    codes.InvalidArgument,
 		},
 	}
@@ -139,11 +149,13 @@ func TestCanAccessByID(t *testing.T) {
 }
 
 func TestIdentify(t *testing.T) {
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	sth := ths[0]
 
 	usersAddr := fmt.Sprintf("localhost:%d", port)
-	conn, _ := grpc.Dial(usersAddr, grpc.WithInsecure())
+	conn, err := grpc.Dial(usersAddr, grpc.WithInsecure())
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 	cli := grpcapi.NewClient(conn, mocktracer.New(), time.Second)
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	defer cancel()
@@ -161,7 +173,7 @@ func TestIdentify(t *testing.T) {
 		"identify non-existent thing": {
 			key:  wrong,
 			id:   wrongID,
-			code: codes.PermissionDenied,
+			code: codes.NotFound,
 		},
 	}
 
diff --git a/things/api/auth/http/endpoint_test.go b/things/api/auth/http/endpoint_test.go
index 8926d6d9..babba7e5 100644
--- a/things/api/auth/http/endpoint_test.go
+++ b/things/api/auth/http/endpoint_test.go
@@ -88,11 +88,11 @@ func TestIdentify(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, err := svc.CreateThings(context.Background(), token, thing)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
 	require.Nil(t, err, fmt.Sprintf("failed to create thing: %s", err))
-	sth := sths[0]
+	th := ths[0]
 
-	ir := identifyReq{Token: sth.Key}
+	ir := identifyReq{Token: th.Key}
 	data := toJSON(ir)
 
 	nonexistentData := toJSON(identifyReq{Token: wrong})
@@ -110,7 +110,7 @@ func TestIdentify(t *testing.T) {
 		"identify non-existent thing": {
 			contentType: contentType,
 			req:         nonexistentData,
-			status:      http.StatusForbidden,
+			status:      http.StatusNotFound,
 		},
 		"identify with missing content type": {
 			contentType: wrong,
@@ -120,7 +120,7 @@ func TestIdentify(t *testing.T) {
 		"identify with empty JSON request": {
 			contentType: contentType,
 			req:         "{}",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		"identify with invalid JSON request": {
 			contentType: contentType,
@@ -148,21 +148,20 @@ func TestCanAccessByKey(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, err := svc.CreateThings(context.Background(), token, thing)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
 	require.Nil(t, err, fmt.Sprintf("failed to create thing: %s", err))
-	sth := sths[0]
+	th := ths[0]
 
-	schs, err := svc.CreateChannels(context.Background(), token, channel)
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
 	require.Nil(t, err, fmt.Sprintf("failed to create channel: %s", err))
-	sch := schs[0]
+	ch := chs[0]
 
-	err = svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+	err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
 	require.Nil(t, err, fmt.Sprintf("failed to connect thing and channel: %s", err))
 
-	car := canAccessByKeyReq{
-		Token: sth.Key,
-	}
-	data := toJSON(car)
+	data := toJSON(canAccessByKeyReq{
+		Token: th.Key,
+	})
 
 	cases := map[string]struct {
 		contentType string
@@ -172,7 +171,7 @@ func TestCanAccessByKey(t *testing.T) {
 	}{
 		"check access for connected thing and channel": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         data,
 			status:      http.StatusOK,
 		},
@@ -184,25 +183,25 @@ func TestCanAccessByKey(t *testing.T) {
 		},
 		"check access with invalid content type": {
 			contentType: wrong,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         data,
 			status:      http.StatusUnsupportedMediaType,
 		},
 		"check access with empty JSON request": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         "{}",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		"check access with invalid JSON request": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         "}",
 			status:      http.StatusBadRequest,
 		},
 		"check access with empty request": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         "",
 			status:      http.StatusBadRequest,
 		},
@@ -227,21 +226,20 @@ func TestCanAccessByID(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, err := svc.CreateThings(context.Background(), token, thing)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
 	require.Nil(t, err, fmt.Sprintf("failed to create thing: %s", err))
-	sth := sths[0]
+	th := ths[0]
 
-	schs, err := svc.CreateChannels(context.Background(), token, channel)
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
 	require.Nil(t, err, fmt.Sprintf("failed to create channel: %s", err))
-	sch := schs[0]
+	ch := chs[0]
 
-	err = svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+	err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
 	require.Nil(t, err, fmt.Sprintf("failed to connect thing and channel: %s", err))
 
-	car := canAccessByIDReq{
-		ThingID: sth.ID,
-	}
-	data := toJSON(car)
+	data := toJSON(canAccessByIDReq{
+		ThingID: th.ID,
+	})
 
 	cases := map[string]struct {
 		contentType string
@@ -251,7 +249,7 @@ func TestCanAccessByID(t *testing.T) {
 	}{
 		"check access for connected thing and channel": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         data,
 			status:      http.StatusOK,
 		},
@@ -263,25 +261,25 @@ func TestCanAccessByID(t *testing.T) {
 		},
 		"check access with invalid content type": {
 			contentType: wrong,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         data,
 			status:      http.StatusUnsupportedMediaType,
 		},
 		"check access with empty JSON request": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         "{}",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		"check access with invalid JSON request": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         "}",
 			status:      http.StatusBadRequest,
 		},
 		"check access with empty request": {
 			contentType: contentType,
-			chanID:      sch.ID,
+			chanID:      ch.ID,
 			req:         "",
 			status:      http.StatusBadRequest,
 		},
diff --git a/things/api/things/http/endpoint_test.go b/things/api/things/http/endpoint_test.go
index cef153fc..7593f359 100644
--- a/things/api/things/http/endpoint_test.go
+++ b/things/api/things/http/endpoint_test.go
@@ -126,7 +126,7 @@ func TestCreateThing(t *testing.T) {
 			req:         data,
 			contentType: contentType,
 			auth:        token,
-			status:      http.StatusUnprocessableEntity,
+			status:      http.StatusConflict,
 			location:    "",
 		},
 		{
@@ -142,7 +142,7 @@ func TestCreateThing(t *testing.T) {
 			req:         data,
 			contentType: contentType,
 			auth:        wrongValue,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			location:    "",
 		},
 		{
@@ -150,7 +150,7 @@ func TestCreateThing(t *testing.T) {
 			req:         data,
 			contentType: contentType,
 			auth:        "",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			location:    "",
 		},
 		{
@@ -266,7 +266,7 @@ func TestCreateThings(t *testing.T) {
 			data:        data,
 			contentType: contentType,
 			auth:        token,
-			status:      http.StatusUnprocessableEntity,
+			status:      http.StatusConflict,
 			response:    "",
 		},
 		{
@@ -274,7 +274,7 @@ func TestCreateThings(t *testing.T) {
 			data:        data,
 			contentType: contentType,
 			auth:        wrongValue,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			response:    "",
 		},
 		{
@@ -282,7 +282,7 @@ func TestCreateThings(t *testing.T) {
 			data:        data,
 			contentType: contentType,
 			auth:        "",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			response:    "",
 		},
 		{
@@ -319,12 +319,13 @@ func TestUpdateThing(t *testing.T) {
 	defer ts.Close()
 
 	data := toJSON(thing)
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th1 := ths[0]
 
-	th := thing
-	th.Name = invalidName
-	invalidData := toJSON(th)
+	th2 := thing
+	th2.Name = invalidName
+	invalidData := toJSON(th2)
 
 	cases := []struct {
 		desc        string
@@ -337,7 +338,7 @@ func TestUpdateThing(t *testing.T) {
 		{
 			desc:        "update existing thing",
 			req:         data,
-			id:          sth.ID,
+			id:          th1.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusOK,
@@ -345,7 +346,7 @@ func TestUpdateThing(t *testing.T) {
 		{
 			desc:        "update thing with empty JSON request",
 			req:         "{}",
-			id:          sth.ID,
+			id:          th1.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusOK,
@@ -369,23 +370,23 @@ func TestUpdateThing(t *testing.T) {
 		{
 			desc:        "update thing with invalid user token",
 			req:         data,
-			id:          sth.ID,
+			id:          th1.ID,
 			contentType: contentType,
 			auth:        wrongValue,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "update thing with empty user token",
 			req:         data,
-			id:          sth.ID,
+			id:          th1.ID,
 			contentType: contentType,
 			auth:        "",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "update thing with invalid data format",
 			req:         "{",
-			id:          sth.ID,
+			id:          th1.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusBadRequest,
@@ -393,7 +394,7 @@ func TestUpdateThing(t *testing.T) {
 		{
 			desc:        "update thing with empty request",
 			req:         "",
-			id:          sth.ID,
+			id:          th1.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusBadRequest,
@@ -401,7 +402,7 @@ func TestUpdateThing(t *testing.T) {
 		{
 			desc:        "update thing without content type",
 			req:         data,
-			id:          sth.ID,
+			id:          th1.ID,
 			contentType: "",
 			auth:        token,
 			status:      http.StatusUnsupportedMediaType,
@@ -437,14 +438,15 @@ func TestUpdateKey(t *testing.T) {
 
 	th := thing
 	th.Key = "key"
-	sths, _ := svc.CreateThings(context.Background(), token, th)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, th)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th = ths[0]
 
-	sth.Key = "new-key"
-	data := toJSON(sth)
+	th.Key = "new-key"
+	data := toJSON(th)
 
-	sth.Key = "key"
-	dummyData := toJSON(sth)
+	th.Key = "key"
+	dummyData := toJSON(th)
 
 	cases := []struct {
 		desc        string
@@ -457,7 +459,7 @@ func TestUpdateKey(t *testing.T) {
 		{
 			desc:        "update key for an existing thing",
 			req:         data,
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusOK,
@@ -465,15 +467,15 @@ func TestUpdateKey(t *testing.T) {
 		{
 			desc:        "update thing with conflicting key",
 			req:         data,
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: contentType,
 			auth:        token,
-			status:      http.StatusUnprocessableEntity,
+			status:      http.StatusConflict,
 		},
 		{
 			desc:        "update key with empty JSON request",
 			req:         "{}",
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusBadRequest,
@@ -497,23 +499,23 @@ func TestUpdateKey(t *testing.T) {
 		{
 			desc:        "update thing with invalid user token",
 			req:         data,
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: contentType,
 			auth:        wrongValue,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "update thing with empty user token",
 			req:         data,
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: contentType,
 			auth:        "",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "update thing with invalid data format",
 			req:         "{",
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusBadRequest,
@@ -521,7 +523,7 @@ func TestUpdateKey(t *testing.T) {
 		{
 			desc:        "update thing with empty request",
 			req:         "",
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusBadRequest,
@@ -529,7 +531,7 @@ func TestUpdateKey(t *testing.T) {
 		{
 			desc:        "update thing without content type",
 			req:         data,
-			id:          sth.ID,
+			id:          th.ID,
 			contentType: "",
 			auth:        token,
 			status:      http.StatusUnsupportedMediaType,
@@ -556,17 +558,16 @@ func TestViewThing(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, err := svc.CreateThings(context.Background(), token, thing)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-	sth := sths[0]
+	th := ths[0]
 
-	thres := thingRes{
-		ID:       sth.ID,
-		Name:     sth.Name,
-		Key:      sth.Key,
-		Metadata: sth.Metadata,
-	}
-	data := toJSON(thres)
+	data := toJSON(thingRes{
+		ID:       th.ID,
+		Name:     th.Name,
+		Key:      th.Key,
+		Metadata: th.Metadata,
+	})
 
 	cases := []struct {
 		desc   string
@@ -577,7 +578,7 @@ func TestViewThing(t *testing.T) {
 	}{
 		{
 			desc:   "view existing thing",
-			id:     sth.ID,
+			id:     th.ID,
 			auth:   token,
 			status: http.StatusOK,
 			res:    data,
@@ -591,16 +592,16 @@ func TestViewThing(t *testing.T) {
 		},
 		{
 			desc:   "view thing by passing invalid token",
-			id:     sth.ID,
+			id:     th.ID,
 			auth:   wrongValue,
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			res:    unauthRes,
 		},
 		{
 			desc:   "view thing by passing empty token",
-			id:     sth.ID,
+			id:     th.ID,
 			auth:   "",
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			res:    unauthRes,
 		},
 		{
@@ -636,16 +637,15 @@ func TestListThings(t *testing.T) {
 
 	data := []thingRes{}
 	for i := 0; i < 100; i++ {
-		sths, err := svc.CreateThings(context.Background(), token, thing)
+		ths, err := svc.CreateThings(context.Background(), token, thing)
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-		sth := sths[0]
-		thres := thingRes{
-			ID:       sth.ID,
-			Name:     sth.Name,
-			Key:      sth.Key,
-			Metadata: sth.Metadata,
-		}
-		data = append(data, thres)
+		th := ths[0]
+		data = append(data, thingRes{
+			ID:       th.ID,
+			Name:     th.Name,
+			Key:      th.Key,
+			Metadata: th.Metadata,
+		})
 	}
 
 	thingURL := fmt.Sprintf("%s/things", ts.URL)
@@ -666,14 +666,14 @@ func TestListThings(t *testing.T) {
 		{
 			desc:   "get a list of things with invalid token",
 			auth:   wrongValue,
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			url:    fmt.Sprintf("%s?offset=%d&limit=%d", thingURL, 0, 1),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things with empty token",
 			auth:   "",
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			url:    fmt.Sprintf("%s?offset=%d&limit=%d", thingURL, 0, 1),
 			res:    nil,
 		},
@@ -784,25 +784,24 @@ func TestListThingsByChannel(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	schs, err := svc.CreateChannels(context.Background(), token, channel)
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-	sch := schs[0]
+	ch := chs[0]
 
 	data := []thingRes{}
 	for i := 0; i < 101; i++ {
-		sths, err := svc.CreateThings(context.Background(), token, thing)
+		ths, err := svc.CreateThings(context.Background(), token, thing)
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-		sth := sths[0]
-		err = svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+		th := ths[0]
+		err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
 
-		thres := thingRes{
-			ID:       sth.ID,
-			Name:     sth.Name,
-			Key:      sth.Key,
-			Metadata: sth.Metadata,
-		}
-		data = append(data, thres)
+		data = append(data, thingRes{
+			ID:       th.ID,
+			Name:     th.Name,
+			Key:      th.Key,
+			Metadata: th.Metadata,
+		})
 	}
 	thingURL := fmt.Sprintf("%s/channels", ts.URL)
 
@@ -820,98 +819,98 @@ func TestListThingsByChannel(t *testing.T) {
 			desc:   "get a list of things by channel",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, sch.ID, 0, 5),
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, ch.ID, 0, 5),
 			res:    data[0:5],
 		},
 		{
 			desc:   "get a list of things by channel with invalid token",
 			auth:   wrongValue,
-			status: http.StatusForbidden,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, sch.ID, 0, 1),
+			status: http.StatusUnauthorized,
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, ch.ID, 0, 1),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel with empty token",
 			auth:   "",
-			status: http.StatusForbidden,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, sch.ID, 0, 1),
+			status: http.StatusUnauthorized,
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, ch.ID, 0, 1),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel with negative offset",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, sch.ID, -1, 5),
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, ch.ID, -1, 5),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel with negative limit",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, sch.ID, 1, -5),
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, ch.ID, 1, -5),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel with zero limit",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, sch.ID, 1, 0),
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, ch.ID, 1, 0),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel without offset",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/things?limit=%d", thingURL, sch.ID, 5),
+			url:    fmt.Sprintf("%s/%s/things?limit=%d", thingURL, ch.ID, 5),
 			res:    data[0:5],
 		},
 		{
 			desc:   "get a list of things by channel without limit",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d", thingURL, sch.ID, 1),
+			url:    fmt.Sprintf("%s/%s/things?offset=%d", thingURL, ch.ID, 1),
 			res:    data[1:11],
 		},
 		{
 			desc:   "get a list of things by channel with redundant query params",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d&value=something", thingURL, sch.ID, 0, 5),
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d&value=something", thingURL, ch.ID, 0, 5),
 			res:    data[0:5],
 		},
 		{
 			desc:   "get a list of things by channel with limit greater than max",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, sch.ID, 0, 110),
+			url:    fmt.Sprintf("%s/%s/things?offset=%d&limit=%d", thingURL, ch.ID, 0, 110),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel with default URL",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/things", thingURL, sch.ID),
+			url:    fmt.Sprintf("%s/%s/things", thingURL, ch.ID),
 			res:    data[0:10],
 		},
 		{
 			desc:   "get a list of things by channel with invalid number of params",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/things%s", thingURL, sch.ID, "?offset=4&limit=4&limit=5&offset=5"),
+			url:    fmt.Sprintf("%s/%s/things%s", thingURL, ch.ID, "?offset=4&limit=4&limit=5&offset=5"),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel with invalid offset",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/things%s", thingURL, sch.ID, "?offset=e&limit=5"),
+			url:    fmt.Sprintf("%s/%s/things%s", thingURL, ch.ID, "?offset=e&limit=5"),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of things by channel with invalid limit",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/things%s", thingURL, sch.ID, "?offset=5&limit=e"),
+			url:    fmt.Sprintf("%s/%s/things%s", thingURL, ch.ID, "?offset=5&limit=e"),
 			res:    nil,
 		},
 	}
@@ -937,8 +936,9 @@ func TestRemoveThing(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
 
 	cases := []struct {
 		desc   string
@@ -948,7 +948,7 @@ func TestRemoveThing(t *testing.T) {
 	}{
 		{
 			desc:   "delete existing thing",
-			id:     sth.ID,
+			id:     th.ID,
 			auth:   token,
 			status: http.StatusNoContent,
 		},
@@ -960,15 +960,15 @@ func TestRemoveThing(t *testing.T) {
 		},
 		{
 			desc:   "delete thing with invalid token",
-			id:     sth.ID,
+			id:     th.ID,
 			auth:   wrongValue,
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 		},
 		{
 			desc:   "delete thing with empty token",
-			id:     sth.ID,
+			id:     th.ID,
 			auth:   "",
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 		},
 	}
 
@@ -1017,7 +1017,7 @@ func TestCreateChannel(t *testing.T) {
 			req:         data,
 			contentType: contentType,
 			auth:        wrongValue,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			location:    "",
 		},
 		{
@@ -1025,7 +1025,7 @@ func TestCreateChannel(t *testing.T) {
 			req:         data,
 			contentType: contentType,
 			auth:        "",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			location:    "",
 		},
 		{
@@ -1133,7 +1133,7 @@ func TestCreateChannels(t *testing.T) {
 			data:        data,
 			contentType: contentType,
 			auth:        wrongValue,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			response:    "",
 		},
 		{
@@ -1141,7 +1141,7 @@ func TestCreateChannels(t *testing.T) {
 			data:        data,
 			contentType: contentType,
 			auth:        "",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 			response:    "",
 		},
 		{
@@ -1192,15 +1192,16 @@ func TestUpdateChannel(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
 
-	ch := channel
-	ch.Name = "updated_channel"
-	updateData := toJSON(ch)
+	c := channel
+	c.Name = "updated_channel"
+	updateData := toJSON(c)
 
-	ch.Name = invalidName
-	invalidData := toJSON(ch)
+	c.Name = invalidName
+	invalidData := toJSON(c)
 
 	cases := []struct {
 		desc        string
@@ -1213,7 +1214,7 @@ func TestUpdateChannel(t *testing.T) {
 		{
 			desc:        "update existing channel",
 			req:         updateData,
-			id:          sch.ID,
+			id:          ch.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusOK,
@@ -1237,23 +1238,23 @@ func TestUpdateChannel(t *testing.T) {
 		{
 			desc:        "update channel with invalid token",
 			req:         updateData,
-			id:          sch.ID,
+			id:          ch.ID,
 			contentType: contentType,
 			auth:        wrongValue,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "update channel with empty token",
 			req:         updateData,
-			id:          sch.ID,
+			id:          ch.ID,
 			contentType: contentType,
 			auth:        "",
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "update channel with invalid data format",
 			req:         "}",
-			id:          sch.ID,
+			id:          ch.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusBadRequest,
@@ -1261,7 +1262,7 @@ func TestUpdateChannel(t *testing.T) {
 		{
 			desc:        "update channel with empty JSON object",
 			req:         "{}",
-			id:          sch.ID,
+			id:          ch.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusOK,
@@ -1269,7 +1270,7 @@ func TestUpdateChannel(t *testing.T) {
 		{
 			desc:        "update channel with empty request",
 			req:         "",
-			id:          sch.ID,
+			id:          ch.ID,
 			contentType: contentType,
 			auth:        token,
 			status:      http.StatusBadRequest,
@@ -1277,7 +1278,7 @@ func TestUpdateChannel(t *testing.T) {
 		{
 			desc:        "update channel with missing content type",
 			req:         updateData,
-			id:          sch.ID,
+			id:          ch.ID,
 			contentType: "",
 			auth:        token,
 			status:      http.StatusUnsupportedMediaType,
@@ -1311,19 +1312,20 @@ func TestViewChannel(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	sch := chs[0]
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
-	svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
+	svc.Connect(context.Background(), token, []string{sch.ID}, []string{th.ID})
 
-	chres := channelRes{
+	data := toJSON(channelRes{
 		ID:       sch.ID,
 		Name:     sch.Name,
 		Metadata: sch.Metadata,
-	}
-	data := toJSON(chres)
+	})
 
 	cases := []struct {
 		desc   string
@@ -1350,14 +1352,14 @@ func TestViewChannel(t *testing.T) {
 			desc:   "view channel with invalid token",
 			id:     sch.ID,
 			auth:   wrongValue,
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			res:    unauthRes,
 		},
 		{
 			desc:   "view channel with empty token",
 			id:     sch.ID,
 			auth:   "",
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			res:    unauthRes,
 		},
 		{
@@ -1393,20 +1395,19 @@ func TestListChannels(t *testing.T) {
 
 	channels := []channelRes{}
 	for i := 0; i < 101; i++ {
-		schs, err := svc.CreateChannels(context.Background(), token, channel)
+		chs, err := svc.CreateChannels(context.Background(), token, channel)
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-		sch := schs[0]
-		sths, err := svc.CreateThings(context.Background(), token, thing)
+		ch := chs[0]
+		ths, err := svc.CreateThings(context.Background(), token, thing)
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-		sth := sths[0]
-		svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
-
-		chres := channelRes{
-			ID:       sch.ID,
-			Name:     sch.Name,
-			Metadata: sch.Metadata,
-		}
-		channels = append(channels, chres)
+		th := ths[0]
+		svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
+
+		channels = append(channels, channelRes{
+			ID:       ch.ID,
+			Name:     ch.Name,
+			Metadata: ch.Metadata,
+		})
 	}
 	channelURL := fmt.Sprintf("%s/channels", ts.URL)
 
@@ -1427,14 +1428,14 @@ func TestListChannels(t *testing.T) {
 		{
 			desc:   "get a list of channels with invalid token",
 			auth:   wrongValue,
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			url:    fmt.Sprintf("%s?offset=%d&limit=%d", channelURL, 0, 1),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels with empty token",
 			auth:   "",
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 			url:    fmt.Sprintf("%s?offset=%d&limit=%d", channelURL, 0, 1),
 			res:    nil,
 		},
@@ -1545,24 +1546,23 @@ func TestListChannelsByThing(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, err := svc.CreateThings(context.Background(), token, thing)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-	sth := sths[0]
+	th := ths[0]
 
 	channels := []channelRes{}
 	for i := 0; i < 101; i++ {
-		schs, err := svc.CreateChannels(context.Background(), token, channel)
+		chs, err := svc.CreateChannels(context.Background(), token, channel)
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-		sch := schs[0]
-		err = svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+		ch := chs[0]
+		err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
 
-		chres := channelRes{
-			ID:       sch.ID,
-			Name:     sch.Name,
-			Metadata: sch.Metadata,
-		}
-		channels = append(channels, chres)
+		channels = append(channels, channelRes{
+			ID:       ch.ID,
+			Name:     ch.Name,
+			Metadata: ch.Metadata,
+		})
 	}
 	channelURL := fmt.Sprintf("%s/things", ts.URL)
 
@@ -1577,98 +1577,98 @@ func TestListChannelsByThing(t *testing.T) {
 			desc:   "get a list of channels by thing",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, sth.ID, 0, 6),
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, th.ID, 0, 6),
 			res:    channels[0:6],
 		},
 		{
 			desc:   "get a list of channels by thing with invalid token",
 			auth:   wrongValue,
-			status: http.StatusForbidden,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, sth.ID, 0, 1),
+			status: http.StatusUnauthorized,
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, th.ID, 0, 1),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with empty token",
 			auth:   "",
-			status: http.StatusForbidden,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, sth.ID, 0, 1),
+			status: http.StatusUnauthorized,
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, th.ID, 0, 1),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with negative offset",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, sth.ID, -1, 5),
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, th.ID, -1, 5),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with negative limit",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, sth.ID, -1, 5),
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, th.ID, -1, 5),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with zero limit",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, sth.ID, 1, 0),
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, th.ID, 1, 0),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with no offset provided",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/channels?limit=%d", channelURL, sth.ID, 5),
+			url:    fmt.Sprintf("%s/%s/channels?limit=%d", channelURL, th.ID, 5),
 			res:    channels[0:5],
 		},
 		{
 			desc:   "get a list of channels by thing with no limit provided",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d", channelURL, sth.ID, 1),
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d", channelURL, th.ID, 1),
 			res:    channels[1:11],
 		},
 		{
 			desc:   "get a list of channels by thing with redundant query params",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d&value=something", channelURL, sth.ID, 0, 5),
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d&value=something", channelURL, th.ID, 0, 5),
 			res:    channels[0:5],
 		},
 		{
 			desc:   "get a list of channels by thing with limit greater than max",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, sth.ID, 0, 110),
+			url:    fmt.Sprintf("%s/%s/channels?offset=%d&limit=%d", channelURL, th.ID, 0, 110),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with default URL",
 			auth:   token,
 			status: http.StatusOK,
-			url:    fmt.Sprintf("%s/%s/channels", channelURL, sth.ID),
+			url:    fmt.Sprintf("%s/%s/channels", channelURL, th.ID),
 			res:    channels[0:10],
 		},
 		{
 			desc:   "get a list of channels by thing with invalid number of params",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/channels%s", channelURL, sth.ID, "?offset=4&limit=4&limit=5&offset=5"),
+			url:    fmt.Sprintf("%s/%s/channels%s", channelURL, th.ID, "?offset=4&limit=4&limit=5&offset=5"),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with invalid offset",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/channels%s", channelURL, sth.ID, "?offset=e&limit=5"),
+			url:    fmt.Sprintf("%s/%s/channels%s", channelURL, th.ID, "?offset=e&limit=5"),
 			res:    nil,
 		},
 		{
 			desc:   "get a list of channels by thing with invalid limit",
 			auth:   token,
 			status: http.StatusBadRequest,
-			url:    fmt.Sprintf("%s/%s/channels%s", channelURL, sth.ID, "?offset=5&limit=e"),
+			url:    fmt.Sprintf("%s/%s/channels%s", channelURL, th.ID, "?offset=5&limit=e"),
 			res:    nil,
 		},
 	}
@@ -1694,8 +1694,8 @@ func TestRemoveChannel(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
+	chs, _ := svc.CreateChannels(context.Background(), token, channel)
+	ch := chs[0]
 
 	cases := []struct {
 		desc   string
@@ -1705,33 +1705,33 @@ func TestRemoveChannel(t *testing.T) {
 	}{
 		{
 			desc:   "remove channel with invalid token",
-			id:     sch.ID,
+			id:     ch.ID,
 			auth:   wrongValue,
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 		},
 		{
 			desc:   "remove existing channel",
-			id:     sch.ID,
+			id:     ch.ID,
 			auth:   token,
 			status: http.StatusNoContent,
 		},
 		{
 			desc:   "remove removed channel",
-			id:     sch.ID,
+			id:     ch.ID,
 			auth:   token,
 			status: http.StatusNoContent,
 		},
 		{
 			desc:   "remove channel with invalid token",
-			id:     sch.ID,
+			id:     ch.ID,
 			auth:   wrongValue,
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 		},
 		{
 			desc:   "remove channel with empty token",
-			id:     sch.ID,
+			id:     ch.ID,
 			auth:   "",
-			status: http.StatusForbidden,
+			status: http.StatusUnauthorized,
 		},
 	}
 
@@ -1758,12 +1758,12 @@ func TestConnect(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	ath := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	ach := schs[0]
-	schs, _ = svc.CreateChannels(context.Background(), otherToken, channel)
-	bch := schs[0]
+	ths, _ := svc.CreateThings(context.Background(), token, thing)
+	th1 := ths[0]
+	chs, _ := svc.CreateChannels(context.Background(), token, channel)
+	ch1 := chs[0]
+	chs, _ = svc.CreateChannels(context.Background(), otherToken, channel)
+	ch2 := chs[0]
 
 	cases := []struct {
 		desc    string
@@ -1774,21 +1774,21 @@ func TestConnect(t *testing.T) {
 	}{
 		{
 			desc:    "connect existing thing to existing channel",
-			chanID:  ach.ID,
-			thingID: ath.ID,
+			chanID:  ch1.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusOK,
 		},
 		{
 			desc:    "connect existing thing to non-existent channel",
 			chanID:  strconv.FormatUint(wrongID, 10),
-			thingID: ath.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
 		{
 			desc:    "connect non-existing thing to existing channel",
-			chanID:  ach.ID,
+			chanID:  ch1.ID,
 			thingID: strconv.FormatUint(wrongID, 10),
 			auth:    token,
 			status:  http.StatusNotFound,
@@ -1796,35 +1796,35 @@ func TestConnect(t *testing.T) {
 		{
 			desc:    "connect existing thing to channel with invalid id",
 			chanID:  "invalid",
-			thingID: ath.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
 		{
 			desc:    "connect thing with invalid id to existing channel",
-			chanID:  ach.ID,
+			chanID:  ch1.ID,
 			thingID: "invalid",
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
 		{
 			desc:    "connect existing thing to existing channel with invalid token",
-			chanID:  ach.ID,
-			thingID: ath.ID,
+			chanID:  ch1.ID,
+			thingID: th1.ID,
 			auth:    wrongValue,
-			status:  http.StatusForbidden,
+			status:  http.StatusUnauthorized,
 		},
 		{
 			desc:    "connect existing thing to existing channel with empty token",
-			chanID:  ach.ID,
-			thingID: ath.ID,
+			chanID:  ch1.ID,
+			thingID: th1.ID,
 			auth:    "",
-			status:  http.StatusForbidden,
+			status:  http.StatusUnauthorized,
 		},
 		{
 			desc:    "connect thing from owner to channel of other user",
-			chanID:  bch.ID,
-			thingID: ath.ID,
+			chanID:  ch2.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
@@ -1853,21 +1853,24 @@ func TestCreateConnections(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	ths := []string{}
-	for _, th := range sths {
-		ths = append(ths, th.ID)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	thIDs := []string{}
+	for _, th := range ths {
+		thIDs = append(thIDs, th.ID)
 	}
 
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	achs := []string{}
-	for _, ch := range schs {
-		achs = append(achs, ch.ID)
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chIDs1 := []string{}
+	for _, ch := range chs {
+		chIDs1 = append(chIDs1, ch.ID)
 	}
-	schs, _ = svc.CreateChannels(context.Background(), otherToken, channel)
-	bchs := []string{}
-	for _, ch := range schs {
-		bchs = append(bchs, ch.ID)
+	chs, err = svc.CreateChannels(context.Background(), otherToken, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chIDs2 := []string{}
+	for _, ch := range chs {
+		chIDs2 = append(chIDs2, ch.ID)
 	}
 
 	cases := []struct {
@@ -1881,8 +1884,8 @@ func TestCreateConnections(t *testing.T) {
 	}{
 		{
 			desc:        "connect existing things to existing channels",
-			channelIDs:  achs,
-			thingIDs:    ths,
+			channelIDs:  chIDs1,
+			thingIDs:    thIDs,
 			auth:        token,
 			contentType: contentType,
 			status:      http.StatusOK,
@@ -1890,14 +1893,14 @@ func TestCreateConnections(t *testing.T) {
 		{
 			desc:        "connect existing things to non-existent channels",
 			channelIDs:  []string{strconv.FormatUint(wrongID, 10)},
-			thingIDs:    ths,
+			thingIDs:    thIDs,
 			auth:        token,
 			contentType: contentType,
 			status:      http.StatusNotFound,
 		},
 		{
 			desc:        "connect non-existing things to existing channels",
-			channelIDs:  achs,
+			channelIDs:  chIDs1,
 			thingIDs:    []string{strconv.FormatUint(wrongID, 10)},
 			auth:        token,
 			contentType: contentType,
@@ -1906,14 +1909,14 @@ func TestCreateConnections(t *testing.T) {
 		{
 			desc:        "connect existing things to channel with invalid id",
 			channelIDs:  []string{"invalid"},
-			thingIDs:    ths,
+			thingIDs:    thIDs,
 			auth:        token,
 			contentType: contentType,
 			status:      http.StatusNotFound,
 		},
 		{
 			desc:        "connect things with invalid id to existing channels",
-			channelIDs:  achs,
+			channelIDs:  chIDs1,
 			thingIDs:    []string{"invalid"},
 			auth:        token,
 			contentType: contentType,
@@ -1922,14 +1925,14 @@ func TestCreateConnections(t *testing.T) {
 		{
 			desc:        "connect existing things to empty channel ids",
 			channelIDs:  []string{""},
-			thingIDs:    ths,
+			thingIDs:    thIDs,
 			auth:        token,
 			contentType: contentType,
 			status:      http.StatusBadRequest,
 		},
 		{
 			desc:        "connect empty things id to existing channels",
-			channelIDs:  achs,
+			channelIDs:  chIDs1,
 			thingIDs:    []string{""},
 			auth:        token,
 			contentType: contentType,
@@ -1937,32 +1940,32 @@ func TestCreateConnections(t *testing.T) {
 		},
 		{
 			desc:        "connect existing things to existing channels with invalid token",
-			channelIDs:  achs,
-			thingIDs:    ths,
+			channelIDs:  chIDs1,
+			thingIDs:    thIDs,
 			auth:        wrongValue,
 			contentType: contentType,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "connect existing things to existing channels with empty token",
-			channelIDs:  achs,
-			thingIDs:    ths,
+			channelIDs:  chIDs1,
+			thingIDs:    thIDs,
 			auth:        "",
 			contentType: contentType,
-			status:      http.StatusForbidden,
+			status:      http.StatusUnauthorized,
 		},
 		{
 			desc:        "connect things from owner to channels of other user",
-			channelIDs:  bchs,
-			thingIDs:    ths,
+			channelIDs:  chIDs2,
+			thingIDs:    thIDs,
 			auth:        token,
 			contentType: contentType,
 			status:      http.StatusNotFound,
 		},
 		{
 			desc:        "connect with invalid content type",
-			channelIDs:  bchs,
-			thingIDs:    ths,
+			channelIDs:  chIDs2,
+			thingIDs:    thIDs,
 			auth:        token,
 			contentType: "invalid",
 			status:      http.StatusUnsupportedMediaType,
@@ -1977,14 +1980,14 @@ func TestCreateConnections(t *testing.T) {
 		{
 			desc:        "connect valid thing ids with empty channel ids",
 			channelIDs:  []string{},
-			thingIDs:    ths,
+			thingIDs:    thIDs,
 			auth:        token,
 			contentType: contentType,
 			status:      http.StatusBadRequest,
 		},
 		{
 			desc:        "connect valid channel ids with empty thing ids",
-			channelIDs:  achs,
+			channelIDs:  chIDs1,
 			thingIDs:    []string{},
 			auth:        token,
 			contentType: contentType,
@@ -2039,13 +2042,13 @@ func TestDisconnnect(t *testing.T) {
 	ts := newServer(svc)
 	defer ts.Close()
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	ath := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	ach := schs[0]
-	svc.Connect(context.Background(), token, []string{ach.ID}, []string{ath.ID})
-	schs, _ = svc.CreateChannels(context.Background(), otherToken, channel)
-	bch := schs[0]
+	ths, _ := svc.CreateThings(context.Background(), token, thing)
+	th1 := ths[0]
+	chs, _ := svc.CreateChannels(context.Background(), token, channel)
+	ch1 := chs[0]
+	svc.Connect(context.Background(), token, []string{ch1.ID}, []string{th1.ID})
+	chs, _ = svc.CreateChannels(context.Background(), otherToken, channel)
+	ch2 := chs[0]
 
 	cases := []struct {
 		desc    string
@@ -2056,21 +2059,21 @@ func TestDisconnnect(t *testing.T) {
 	}{
 		{
 			desc:    "disconnect connected thing from channel",
-			chanID:  ach.ID,
-			thingID: ath.ID,
+			chanID:  ch1.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNoContent,
 		},
 		{
 			desc:    "disconnect non-connected thing from channel",
-			chanID:  ach.ID,
-			thingID: ath.ID,
+			chanID:  ch1.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
 		{
 			desc:    "disconnect non-existent thing from channel",
-			chanID:  ach.ID,
+			chanID:  ch1.ID,
 			thingID: strconv.FormatUint(wrongID, 10),
 			auth:    token,
 			status:  http.StatusNotFound,
@@ -2078,34 +2081,34 @@ func TestDisconnnect(t *testing.T) {
 		{
 			desc:    "disconnect thing from non-existent channel",
 			chanID:  strconv.FormatUint(wrongID, 10),
-			thingID: ath.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
 		{
 			desc:    "disconnect thing from channel with invalid token",
-			chanID:  ach.ID,
-			thingID: ath.ID,
+			chanID:  ch1.ID,
+			thingID: th1.ID,
 			auth:    wrongValue,
-			status:  http.StatusForbidden,
+			status:  http.StatusUnauthorized,
 		},
 		{
 			desc:    "disconnect thing from channel with empty token",
-			chanID:  ach.ID,
-			thingID: ath.ID,
+			chanID:  ch1.ID,
+			thingID: th1.ID,
 			auth:    "",
-			status:  http.StatusForbidden,
+			status:  http.StatusUnauthorized,
 		},
 		{
 			desc:    "disconnect owner's thing from someone elses channel",
-			chanID:  bch.ID,
-			thingID: ath.ID,
+			chanID:  ch2.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
 		{
 			desc:    "disconnect thing with invalid id from channel",
-			chanID:  ach.ID,
+			chanID:  ch1.ID,
 			thingID: "invalid",
 			auth:    token,
 			status:  http.StatusNotFound,
@@ -2113,7 +2116,7 @@ func TestDisconnnect(t *testing.T) {
 		{
 			desc:    "disconnect thing from channel with invalid id",
 			chanID:  "invalid",
-			thingID: ath.ID,
+			thingID: th1.ID,
 			auth:    token,
 			status:  http.StatusNotFound,
 		},
diff --git a/things/postgres/channels_test.go b/things/postgres/channels_test.go
index 011da924..559e1c0d 100644
--- a/things/postgres/channels_test.go
+++ b/things/postgres/channels_test.go
@@ -10,6 +10,7 @@ import (
 
 	"github.com/stretchr/testify/require"
 
+	"github.com/mainflux/mainflux/pkg/errors"
 	uuidProvider "github.com/mainflux/mainflux/pkg/uuid"
 	"github.com/mainflux/mainflux/things"
 	"github.com/mainflux/mainflux/things/postgres"
@@ -22,18 +23,18 @@ func TestChannelsSave(t *testing.T) {
 
 	email := "channel-save@example.com"
 
-	var chid string
 	chs := []things.Channel{}
 	for i := 1; i <= 5; i++ {
-		chid, err := uuidProvider.New().ID()
+		id, err := uuidProvider.New().ID()
 		require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
 		ch := things.Channel{
-			ID:    chid,
+			ID:    id,
 			Owner: email,
 		}
 		chs = append(chs, ch)
 	}
+	id := chs[0].ID
 
 	cases := []struct {
 		desc     string
@@ -53,32 +54,21 @@ func TestChannelsSave(t *testing.T) {
 		{
 			desc: "create channel with invalid ID",
 			channels: []things.Channel{
-				things.Channel{
-					ID:    "invalid",
-					Owner: email,
-				},
+				{ID: "invalid", Owner: email},
 			},
 			err: things.ErrMalformedEntity,
 		},
 		{
 			desc: "create channel with invalid name",
 			channels: []things.Channel{
-				things.Channel{
-					ID:    chid,
-					Owner: email,
-					Name:  invalidName,
-				},
+				{ID: id, Owner: email, Name: invalidName},
 			},
 			err: things.ErrMalformedEntity,
 		},
 		{
 			desc: "create channel with invalid name",
 			channels: []things.Channel{
-				things.Channel{
-					ID:    chid,
-					Owner: email,
-					Name:  invalidName,
-				},
+				{ID: id, Owner: email, Name: invalidName},
 			},
 			err: things.ErrMalformedEntity,
 		},
@@ -86,7 +76,7 @@ func TestChannelsSave(t *testing.T) {
 
 	for _, cc := range cases {
 		_, err := channelRepo.Save(context.Background(), cc.channels...)
-		assert.Equal(t, cc.err, err, fmt.Sprintf("%s: expected %s got %s\n", cc.desc, cc.err, err))
+		assert.True(t, errors.Contains(err, cc.err), fmt.Sprintf("%s: expected %s got %s\n", cc.desc, cc.err, err))
 	}
 }
 
@@ -95,15 +85,16 @@ func TestChannelUpdate(t *testing.T) {
 	dbMiddleware := postgres.NewDatabase(db)
 	chanRepo := postgres.NewChannelRepository(dbMiddleware)
 
-	cid, err := uuidProvider.New().ID()
+	id, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 	ch := things.Channel{
-		ID:    cid,
+		ID:    id,
 		Owner: email,
 	}
 
-	schs, _ := chanRepo.Save(context.Background(), ch)
-	ch.ID = schs[0].ID
+	chs, err := chanRepo.Save(context.Background(), ch)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch.ID = chs[0].ID
 
 	nonexistentChanID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -146,7 +137,7 @@ func TestChannelUpdate(t *testing.T) {
 
 	for _, tc := range cases {
 		err := chanRepo.Update(context.Background(), tc.channel)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 	}
 }
 
@@ -158,17 +149,15 @@ func TestSingleChannelRetrieval(t *testing.T) {
 
 	thid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
 	thkey, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
 	th := things.Thing{
 		ID:    thid,
 		Owner: email,
 		Key:   thkey,
 	}
-	sths, _ := thingRepo.Save(context.Background(), th)
-	th.ID = sths[0].ID
+	ths, _ := thingRepo.Save(context.Background(), th)
+	th.ID = ths[0].ID
 
 	chid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -176,9 +165,8 @@ func TestSingleChannelRetrieval(t *testing.T) {
 		ID:    chid,
 		Owner: email,
 	}
-
-	schs, _ := chanRepo.Save(context.Background(), ch)
-	ch.ID = schs[0].ID
+	chs, _ := chanRepo.Save(context.Background(), ch)
+	ch.ID = chs[0].ID
 	chanRepo.Connect(context.Background(), email, []string{ch.ID}, []string{th.ID})
 
 	nonexistentChanID, err := uuidProvider.New().ID()
@@ -213,7 +201,7 @@ func TestSingleChannelRetrieval(t *testing.T) {
 
 	for desc, tc := range cases {
 		_, err := chanRepo.RetrieveByID(context.Background(), tc.owner, tc.ID)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
 	}
 }
 
@@ -231,9 +219,9 @@ func TestMultiChannelRetrieval(t *testing.T) {
 	}
 
 	offset := uint64(1)
-	chNameNum := uint64(3)
-	chMetaNum := uint64(3)
-	chNameMetaNum := uint64(2)
+	nameNum := uint64(3)
+	metaNum := uint64(3)
+	nameMetaNum := uint64(2)
 
 	n := uint64(10)
 	for i := uint64(0); i < n; i++ {
@@ -246,15 +234,15 @@ func TestMultiChannelRetrieval(t *testing.T) {
 		}
 
 		// Create Channels with name.
-		if i < chNameNum {
+		if i < nameNum {
 			ch.Name = name
 		}
 		// Create Channels with metadata.
-		if i >= chNameNum && i < chNameNum+chMetaNum {
+		if i >= nameNum && i < nameNum+metaNum {
 			ch.Metadata = metadata
 		}
 		// Create Channels with name and metadata.
-		if i >= n-chNameMetaNum {
+		if i >= n-nameMetaNum {
 			ch.Metadata = metadata
 			ch.Name = name
 		}
@@ -297,8 +285,8 @@ func TestMultiChannelRetrieval(t *testing.T) {
 			offset: offset,
 			limit:  n,
 			name:   name,
-			size:   chNameNum + chNameMetaNum - offset,
-			total:  chNameNum + chNameMetaNum,
+			size:   nameNum + nameMetaNum - offset,
+			total:  nameNum + nameMetaNum,
 		},
 		"retrieve all channels with non-existing name": {
 			owner:  email,
@@ -312,8 +300,8 @@ func TestMultiChannelRetrieval(t *testing.T) {
 			owner:    email,
 			offset:   0,
 			limit:    n,
-			size:     chMetaNum + chNameMetaNum,
-			total:    chMetaNum + chNameMetaNum,
+			size:     metaNum + nameMetaNum,
+			total:    metaNum + nameMetaNum,
 			metadata: metadata,
 		},
 		"retrieve all channels with non-existing metadata": {
@@ -327,8 +315,8 @@ func TestMultiChannelRetrieval(t *testing.T) {
 			owner:    email,
 			offset:   0,
 			limit:    n,
-			size:     chNameMetaNum,
-			total:    chNameMetaNum,
+			size:     nameMetaNum,
+			total:    nameMetaNum,
 			name:     name,
 			metadata: metadata,
 		},
@@ -351,13 +339,12 @@ func TestRetrieveByThing(t *testing.T) {
 
 	thid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
-	sths, err := thingRepo.Save(context.Background(), things.Thing{
+	ths, err := thingRepo.Save(context.Background(), things.Thing{
 		ID:    thid,
 		Owner: email,
 	})
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-	tid := sths[0].ID
+	thid = ths[0].ID
 
 	n := uint64(10)
 	chsDisconNum := uint64(1)
@@ -378,7 +365,7 @@ func TestRetrieveByThing(t *testing.T) {
 			break
 		}
 
-		err = chanRepo.Connect(context.Background(), email, []string{cid}, []string{tid})
+		err = chanRepo.Connect(context.Background(), email, []string{cid}, []string{thid})
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
 	}
 
@@ -396,7 +383,7 @@ func TestRetrieveByThing(t *testing.T) {
 	}{
 		"retrieve all channels by thing with existing owner": {
 			owner:     email,
-			thing:     tid,
+			thing:     thid,
 			offset:    0,
 			limit:     n,
 			connected: true,
@@ -404,7 +391,7 @@ func TestRetrieveByThing(t *testing.T) {
 		},
 		"retrieve subset of channels by thing with existing owner": {
 			owner:     email,
-			thing:     tid,
+			thing:     thid,
 			offset:    n / 2,
 			limit:     n,
 			connected: true,
@@ -412,7 +399,7 @@ func TestRetrieveByThing(t *testing.T) {
 		},
 		"retrieve channels by thing with non-existing owner": {
 			owner:     wrongValue,
-			thing:     tid,
+			thing:     thid,
 			offset:    n / 2,
 			limit:     n,
 			connected: true,
@@ -437,7 +424,7 @@ func TestRetrieveByThing(t *testing.T) {
 		},
 		"retrieve all non connected channels by thing with existing owner": {
 			owner:     email,
-			thing:     tid,
+			thing:     thid,
 			offset:    0,
 			limit:     n,
 			connected: false,
@@ -449,7 +436,7 @@ func TestRetrieveByThing(t *testing.T) {
 		page, err := chanRepo.RetrieveByThing(context.Background(), tc.owner, tc.thing, tc.offset, tc.limit, tc.connected)
 		size := uint64(len(page.Channels))
 		assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected size %d got %d\n", desc, tc.size, size))
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected no error got %d\n", desc, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected no error got %d\n", desc, err))
 	}
 }
 
@@ -460,20 +447,21 @@ func TestChannelRemoval(t *testing.T) {
 
 	chid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	schs, _ := chanRepo.Save(context.Background(), things.Channel{
+	chs, err := chanRepo.Save(context.Background(), things.Channel{
 		ID:    chid,
 		Owner: email,
 	})
-	chanID := schs[0].ID
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chid = chs[0].ID
 
 	// show that the removal works the same for both existing and non-existing
 	// (removed) channel
 	for i := 0; i < 2; i++ {
-		err := chanRepo.Remove(context.Background(), email, chanID)
+		err := chanRepo.Remove(context.Background(), email, chid)
 		require.Nil(t, err, fmt.Sprintf("#%d: failed to remove channel due to: %s", i, err))
 
-		_, err = chanRepo.RetrieveByID(context.Background(), email, chanID)
-		require.Equal(t, things.ErrNotFound, err, fmt.Sprintf("#%d: expected %s got %s", i, things.ErrNotFound, err))
+		_, err = chanRepo.RetrieveByID(context.Background(), email, chid)
+		assert.True(t, errors.Contains(err, things.ErrNotFound), fmt.Sprintf("#%d: expected %s got %s", i, things.ErrNotFound, err))
 	}
 }
 
@@ -487,24 +475,26 @@ func TestConnect(t *testing.T) {
 	thkey, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
-	thing := things.Thing{
+	th := things.Thing{
 		ID:       thid,
 		Owner:    email,
 		Key:      thkey,
 		Metadata: things.Metadata{},
 	}
-	sths, _ := thingRepo.Save(context.Background(), thing)
-	thingID := sths[0].ID
+	ths, err := thingRepo.Save(context.Background(), th)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	thid = ths[0].ID
 
 	chanRepo := postgres.NewChannelRepository(dbMiddleware)
 
 	chid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	schs, _ := chanRepo.Save(context.Background(), things.Channel{
+	chs, err := chanRepo.Save(context.Background(), things.Channel{
 		ID:    chid,
 		Owner: email,
 	})
-	chanID := schs[0].ID
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chid = chs[0].ID
 
 	nonexistentThingID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -513,52 +503,52 @@ func TestConnect(t *testing.T) {
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
 	cases := []struct {
-		desc    string
-		owner   string
-		chanID  string
-		thingID string
-		err     error
+		desc  string
+		owner string
+		chid  string
+		thid  string
+		err   error
 	}{
 		{
-			desc:    "connect existing user, channel and thing",
-			owner:   email,
-			chanID:  chanID,
-			thingID: thingID,
-			err:     nil,
+			desc:  "connect existing user, channel and thing",
+			owner: email,
+			chid:  chid,
+			thid:  thid,
+			err:   nil,
 		},
 		{
-			desc:    "connect connected channel and thing",
-			owner:   email,
-			chanID:  chanID,
-			thingID: thingID,
-			err:     things.ErrConflict,
+			desc:  "connect connected channel and thing",
+			owner: email,
+			chid:  chid,
+			thid:  thid,
+			err:   things.ErrConflict,
 		},
 		{
-			desc:    "connect with non-existing user",
-			owner:   wrongValue,
-			chanID:  chanID,
-			thingID: thingID,
-			err:     things.ErrNotFound,
+			desc:  "connect with non-existing user",
+			owner: wrongValue,
+			chid:  chid,
+			thid:  thid,
+			err:   things.ErrNotFound,
 		},
 		{
-			desc:    "connect non-existing channel",
-			owner:   email,
-			chanID:  nonexistentChanID,
-			thingID: thingID,
-			err:     things.ErrNotFound,
+			desc:  "connect non-existing channel",
+			owner: email,
+			chid:  nonexistentChanID,
+			thid:  thid,
+			err:   things.ErrNotFound,
 		},
 		{
-			desc:    "connect non-existing thing",
-			owner:   email,
-			chanID:  chanID,
-			thingID: nonexistentThingID,
-			err:     things.ErrNotFound,
+			desc:  "connect non-existing thing",
+			owner: email,
+			chid:  chid,
+			thid:  nonexistentThingID,
+			err:   things.ErrNotFound,
 		},
 	}
 
 	for _, tc := range cases {
-		err := chanRepo.Connect(context.Background(), tc.owner, []string{tc.chanID}, []string{tc.thingID})
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
+		err := chanRepo.Connect(context.Background(), tc.owner, []string{tc.chid}, []string{tc.thid})
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 	}
 }
 
@@ -571,25 +561,26 @@ func TestDisconnect(t *testing.T) {
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 	thkey, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
-	thing := things.Thing{
+	th := things.Thing{
 		ID:       thid,
 		Owner:    email,
 		Key:      thkey,
 		Metadata: map[string]interface{}{},
 	}
-	sths, _ := thingRepo.Save(context.Background(), thing)
-	thingID := sths[0].ID
+	ths, err := thingRepo.Save(context.Background(), th)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	thid = ths[0].ID
 
 	chanRepo := postgres.NewChannelRepository(dbMiddleware)
 	chid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	schs, _ := chanRepo.Save(context.Background(), things.Channel{
+	chs, err := chanRepo.Save(context.Background(), things.Channel{
 		ID:    chid,
 		Owner: email,
 	})
-	chanID := schs[0].ID
-	chanRepo.Connect(context.Background(), email, []string{chanID}, []string{thingID})
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chid = chs[0].ID
+	chanRepo.Connect(context.Background(), email, []string{chid}, []string{thid})
 
 	nonexistentThingID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -598,52 +589,52 @@ func TestDisconnect(t *testing.T) {
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
 	cases := []struct {
-		desc    string
-		owner   string
-		chanID  string
-		thingID string
-		err     error
+		desc  string
+		owner string
+		chid  string
+		thid  string
+		err   error
 	}{
 		{
-			desc:    "disconnect connected thing",
-			owner:   email,
-			chanID:  chanID,
-			thingID: thingID,
-			err:     nil,
+			desc:  "disconnect connected thing",
+			owner: email,
+			chid:  chid,
+			thid:  thid,
+			err:   nil,
 		},
 		{
-			desc:    "disconnect non-connected thing",
-			owner:   email,
-			chanID:  chanID,
-			thingID: thingID,
-			err:     things.ErrNotFound,
+			desc:  "disconnect non-connected thing",
+			owner: email,
+			chid:  chid,
+			thid:  thid,
+			err:   things.ErrNotFound,
 		},
 		{
-			desc:    "disconnect non-existing user",
-			owner:   wrongValue,
-			chanID:  chanID,
-			thingID: thingID,
-			err:     things.ErrNotFound,
+			desc:  "disconnect non-existing user",
+			owner: wrongValue,
+			chid:  chid,
+			thid:  thid,
+			err:   things.ErrNotFound,
 		},
 		{
-			desc:    "disconnect non-existing channel",
-			owner:   email,
-			chanID:  nonexistentChanID,
-			thingID: thingID,
-			err:     things.ErrNotFound,
+			desc:  "disconnect non-existing channel",
+			owner: email,
+			chid:  nonexistentChanID,
+			thid:  thid,
+			err:   things.ErrNotFound,
 		},
 		{
-			desc:    "disconnect non-existing thing",
-			owner:   email,
-			chanID:  chanID,
-			thingID: nonexistentThingID,
-			err:     things.ErrNotFound,
+			desc:  "disconnect non-existing thing",
+			owner: email,
+			chid:  chid,
+			thid:  nonexistentThingID,
+			err:   things.ErrNotFound,
 		},
 	}
 
 	for _, tc := range cases {
-		err := chanRepo.Disconnect(context.Background(), tc.owner, tc.chanID, tc.thingID)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
+		err := chanRepo.Disconnect(context.Background(), tc.owner, tc.chid, tc.thid)
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 	}
 }
 
@@ -657,51 +648,53 @@ func TestHasThing(t *testing.T) {
 	thkey, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
-	thing := things.Thing{
+	th := things.Thing{
 		ID:    thid,
 		Owner: email,
 		Key:   thkey,
 	}
-	sths, _ := thingRepo.Save(context.Background(), thing)
-	thingID := sths[0].ID
+	ths, err := thingRepo.Save(context.Background(), th)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	thid = ths[0].ID
 
 	chanRepo := postgres.NewChannelRepository(dbMiddleware)
 	chid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	schs, _ := chanRepo.Save(context.Background(), things.Channel{
+	chs, err := chanRepo.Save(context.Background(), things.Channel{
 		ID:    chid,
 		Owner: email,
 	})
-	chanID := schs[0].ID
-	chanRepo.Connect(context.Background(), email, []string{chanID}, []string{thingID})
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chid = chs[0].ID
+	chanRepo.Connect(context.Background(), email, []string{chid}, []string{thid})
 
 	nonexistentChanID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
 	cases := map[string]struct {
-		chanID    string
+		chid      string
 		key       string
 		hasAccess bool
 	}{
 		"access check for thing that has access": {
-			chanID:    chanID,
-			key:       thing.Key,
+			chid:      chid,
+			key:       th.Key,
 			hasAccess: true,
 		},
 		"access check for thing without access": {
-			chanID:    chanID,
+			chid:      chid,
 			key:       wrongValue,
 			hasAccess: false,
 		},
 		"access check for non-existing channel": {
-			chanID:    nonexistentChanID,
-			key:       thing.Key,
+			chid:      nonexistentChanID,
+			key:       th.Key,
 			hasAccess: false,
 		},
 	}
 
 	for desc, tc := range cases {
-		_, err := chanRepo.HasThing(context.Background(), tc.chanID, tc.key)
+		_, err := chanRepo.HasThing(context.Background(), tc.chid, tc.key)
 		hasAccess := err == nil
 		assert.Equal(t, tc.hasAccess, hasAccess, fmt.Sprintf("%s: expected %t got %t\n", desc, tc.hasAccess, hasAccess))
 	}
@@ -716,14 +709,14 @@ func TestHasThingByID(t *testing.T) {
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 	thkey, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
-	thing := things.Thing{
+	th := things.Thing{
 		ID:    thid,
 		Owner: email,
 		Key:   thkey,
 	}
-	sths, _ := thingRepo.Save(context.Background(), thing)
-	thingID := sths[0].ID
+	ths, err := thingRepo.Save(context.Background(), th)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	thid = ths[0].ID
 
 	disconnectedThID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -735,51 +728,53 @@ func TestHasThingByID(t *testing.T) {
 		Owner: email,
 		Key:   disconnectedThKey,
 	}
-	sths, _ = thingRepo.Save(context.Background(), disconnectedThing)
-	disconnectedThingID := sths[0].ID
+	ths, err = thingRepo.Save(context.Background(), disconnectedThing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	disconnectedThingID := ths[0].ID
 
 	chanRepo := postgres.NewChannelRepository(dbMiddleware)
 	chid, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	schs, _ := chanRepo.Save(context.Background(), things.Channel{
+	chs, err := chanRepo.Save(context.Background(), things.Channel{
 		ID:    chid,
 		Owner: email,
 	})
-	chanID := schs[0].ID
-	chanRepo.Connect(context.Background(), email, []string{chanID}, []string{thingID})
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chid = chs[0].ID
+	chanRepo.Connect(context.Background(), email, []string{chid}, []string{thid})
 
 	nonexistentChanID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
 	cases := map[string]struct {
-		chanID    string
-		thingID   string
+		chid      string
+		thid      string
 		hasAccess bool
 	}{
 		"access check for thing that has access": {
-			chanID:    chanID,
-			thingID:   thingID,
+			chid:      chid,
+			thid:      thid,
 			hasAccess: true,
 		},
 		"access check for thing without access": {
-			chanID:    chanID,
-			thingID:   disconnectedThingID,
+			chid:      chid,
+			thid:      disconnectedThingID,
 			hasAccess: false,
 		},
 		"access check for non-existing channel": {
-			chanID:    nonexistentChanID,
-			thingID:   thingID,
+			chid:      nonexistentChanID,
+			thid:      thid,
 			hasAccess: false,
 		},
 		"access check for non-existing thing": {
-			chanID:    chanID,
-			thingID:   wrongValue,
+			chid:      chid,
+			thid:      wrongValue,
 			hasAccess: false,
 		},
 	}
 
 	for desc, tc := range cases {
-		err := chanRepo.HasThingByID(context.Background(), tc.chanID, tc.thingID)
+		err := chanRepo.HasThingByID(context.Background(), tc.chid, tc.thid)
 		hasAccess := err == nil
 		assert.Equal(t, tc.hasAccess, hasAccess, fmt.Sprintf("%s: expected %t got %t\n", desc, tc.hasAccess, hasAccess))
 	}
diff --git a/things/postgres/things_test.go b/things/postgres/things_test.go
index c388f125..dc2297fc 100644
--- a/things/postgres/things_test.go
+++ b/things/postgres/things_test.go
@@ -30,13 +30,11 @@ func TestThingsSave(t *testing.T) {
 	nonexistentThingKey, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
-	var thid string
-	var thkey string
 	ths := []things.Thing{}
 	for i := 1; i <= 5; i++ {
-		thid, err = uuidProvider.New().ID()
+		thid, err := uuidProvider.New().ID()
 		require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-		thkey, err = uuidProvider.New().ID()
+		thkey, err := uuidProvider.New().ID()
 		require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
 		thing := things.Thing{
@@ -46,6 +44,8 @@ func TestThingsSave(t *testing.T) {
 		}
 		ths = append(ths, thing)
 	}
+	thkey := ths[0].Key
+	thid := ths[0].ID
 
 	cases := []struct {
 		desc   string
@@ -65,34 +65,21 @@ func TestThingsSave(t *testing.T) {
 		{
 			desc: "create thing with invalid ID",
 			things: []things.Thing{
-				things.Thing{
-					ID:    "invalid",
-					Owner: email,
-					Key:   thkey,
-				},
+				{ID: "invalid", Owner: email, Key: thkey},
 			},
 			err: things.ErrMalformedEntity,
 		},
 		{
 			desc: "create thing with invalid name",
 			things: []things.Thing{
-				things.Thing{
-					ID:    thid,
-					Owner: email,
-					Key:   thkey,
-					Name:  invalidName,
-				},
+				{ID: thid, Owner: email, Key: thkey, Name: invalidName},
 			},
 			err: things.ErrMalformedEntity,
 		},
 		{
 			desc: "create thing with invalid Key",
 			things: []things.Thing{
-				things.Thing{
-					ID:    thid,
-					Owner: email,
-					Key:   nonexistentThingKey,
-				},
+				{ID: thid, Owner: email, Key: nonexistentThingKey},
 			},
 			err: things.ErrConflict,
 		},
@@ -203,32 +190,31 @@ func TestUpdateKey(t *testing.T) {
 	dbMiddleware := postgres.NewDatabase(db)
 	thingRepo := postgres.NewThingRepository(dbMiddleware)
 
-	ethid, err := uuidProvider.New().ID()
+	id, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	ethkey, err := uuidProvider.New().ID()
+	key, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
-	existingThing := things.Thing{
-		ID:    ethid,
+	th1 := things.Thing{
+		ID:    id,
 		Owner: email,
-		Key:   ethkey,
+		Key:   key,
 	}
-	sths, _ := thingRepo.Save(context.Background(), existingThing)
-	existingThing.ID = sths[0].ID
+	ths, err := thingRepo.Save(context.Background(), th1)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th1.ID = ths[0].ID
 
-	thid, err := uuidProvider.New().ID()
+	id, err = uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	thkey, err := uuidProvider.New().ID()
+	key, err = uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
-	thing := things.Thing{
-		ID:    thid,
+	th2 := things.Thing{
+		ID:    id,
 		Owner: email,
-		Key:   thkey,
+		Key:   key,
 	}
-
-	sths, _ = thingRepo.Save(context.Background(), thing)
-	thing.ID = sths[0].ID
+	ths, err = thingRepo.Save(context.Background(), th2)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th2.ID = ths[0].ID
 
 	nonexistentThingID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -242,14 +228,14 @@ func TestUpdateKey(t *testing.T) {
 	}{
 		{
 			desc:  "update key of an existing thing",
-			owner: thing.Owner,
-			id:    thing.ID,
+			owner: th2.Owner,
+			id:    th2.ID,
 			key:   newKey,
 			err:   nil,
 		},
 		{
 			desc:  "update key of a non-existing thing with existing user",
-			owner: thing.Owner,
+			owner: th2.Owner,
 			id:    nonexistentThingID,
 			key:   newKey,
 			err:   things.ErrNotFound,
@@ -257,7 +243,7 @@ func TestUpdateKey(t *testing.T) {
 		{
 			desc:  "update key of an existing thing with non-existing user",
 			owner: wrongValue,
-			id:    thing.ID,
+			id:    th2.ID,
 			key:   newKey,
 			err:   things.ErrNotFound,
 		},
@@ -270,9 +256,9 @@ func TestUpdateKey(t *testing.T) {
 		},
 		{
 			desc:  "update key with existing key value",
-			owner: thing.Owner,
-			id:    thing.ID,
-			key:   existingThing.Key,
+			owner: th2.Owner,
+			id:    th2.ID,
+			key:   th1.Key,
 			err:   things.ErrConflict,
 		},
 	}
@@ -288,19 +274,19 @@ func TestSingleThingRetrieval(t *testing.T) {
 	dbMiddleware := postgres.NewDatabase(db)
 	thingRepo := postgres.NewThingRepository(dbMiddleware)
 
-	thid, err := uuidProvider.New().ID()
+	id, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	thkey, err := uuidProvider.New().ID()
+	key, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
-	thing := things.Thing{
-		ID:    thid,
+	th := things.Thing{
+		ID:    id,
 		Owner: email,
-		Key:   thkey,
+		Key:   key,
 	}
 
-	sths, _ := thingRepo.Save(context.Background(), thing)
-	thing.ID = sths[0].ID
+	ths, err := thingRepo.Save(context.Background(), th)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th.ID = ths[0].ID
 
 	nonexistentThingID, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -311,22 +297,22 @@ func TestSingleThingRetrieval(t *testing.T) {
 		err   error
 	}{
 		"retrieve thing with existing user": {
-			owner: thing.Owner,
-			ID:    thing.ID,
+			owner: th.Owner,
+			ID:    th.ID,
 			err:   nil,
 		},
 		"retrieve non-existing thing with existing user": {
-			owner: thing.Owner,
+			owner: th.Owner,
 			ID:    nonexistentThingID,
 			err:   things.ErrNotFound,
 		},
 		"retrieve thing with non-existing owner": {
 			owner: wrongValue,
-			ID:    thing.ID,
+			ID:    th.ID,
 			err:   things.ErrNotFound,
 		},
 		"retrieve thing with malformed ID": {
-			owner: thing.Owner,
+			owner: th.Owner,
 			ID:    wrongValue,
 			err:   things.ErrNotFound,
 		},
@@ -343,19 +329,20 @@ func TestThingRetrieveByKey(t *testing.T) {
 	dbMiddleware := postgres.NewDatabase(db)
 	thingRepo := postgres.NewThingRepository(dbMiddleware)
 
-	thid, err := uuidProvider.New().ID()
+	id, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	thkey, err := uuidProvider.New().ID()
+	key, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
-	thing := things.Thing{
-		ID:    thid,
+	th := things.Thing{
+		ID:    id,
 		Owner: email,
-		Key:   thkey,
+		Key:   key,
 	}
 
-	sths, _ := thingRepo.Save(context.Background(), thing)
-	thing.ID = sths[0].ID
+	ths, err := thingRepo.Save(context.Background(), th)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th.ID = ths[0].ID
 
 	cases := map[string]struct {
 		key string
@@ -363,8 +350,8 @@ func TestThingRetrieveByKey(t *testing.T) {
 		err error
 	}{
 		"retrieve existing thing by key": {
-			key: thing.Key,
-			ID:  thing.ID,
+			key: th.Key,
+			ID:  th.ID,
 			err: nil,
 		},
 		"retrieve non-existent thing by key": {
@@ -396,38 +383,38 @@ func TestMultiThingRetrieval(t *testing.T) {
 
 	up := uuidProvider.New()
 	offset := uint64(1)
-	thNameNum := uint64(3)
-	thMetaNum := uint64(3)
-	thNameMetaNum := uint64(2)
+	nameNum := uint64(3)
+	metaNum := uint64(3)
+	nameMetaNum := uint64(2)
 
 	n := uint64(10)
 	for i := uint64(0); i < n; i++ {
-		thid, err := up.ID()
+		id, err := up.ID()
 		require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-		thkey, err := up.ID()
+		key, err := up.ID()
 		require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
 		th := things.Thing{
 			Owner: email,
-			ID:    thid,
-			Key:   thkey,
+			ID:    id,
+			Key:   key,
 		}
 
 		// Create Things with name.
-		if i < thNameNum {
+		if i < nameNum {
 			th.Name = name
 		}
 		// Create Things with metadata.
-		if i >= thNameNum && i < thNameNum+thMetaNum {
+		if i >= nameNum && i < nameNum+metaNum {
 			th.Metadata = metadata
 		}
 		// Create Things with name and metadata.
-		if i >= n-thNameMetaNum {
+		if i >= n-nameMetaNum {
 			th.Metadata = metadata
 			th.Name = name
 		}
 
-		thingRepo.Save(context.Background(), th)
+		_, err = thingRepo.Save(context.Background(), th)
+		require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 	}
 
 	cases := map[string]struct {
@@ -465,8 +452,8 @@ func TestMultiThingRetrieval(t *testing.T) {
 			offset: 1,
 			limit:  n,
 			name:   name,
-			size:   thNameNum + thNameMetaNum - offset,
-			total:  thNameNum + thNameMetaNum,
+			size:   nameNum + nameMetaNum - offset,
+			total:  nameNum + nameMetaNum,
 		},
 		"retrieve things with non-existing name": {
 			owner:  email,
@@ -480,8 +467,8 @@ func TestMultiThingRetrieval(t *testing.T) {
 			owner:    email,
 			offset:   0,
 			limit:    n,
-			size:     thMetaNum + thNameMetaNum,
-			total:    thMetaNum + thNameMetaNum,
+			size:     metaNum + nameMetaNum,
+			total:    metaNum + nameMetaNum,
 			metadata: metadata,
 		},
 		"retrieve things with non-existing metadata": {
@@ -496,8 +483,8 @@ func TestMultiThingRetrieval(t *testing.T) {
 			owner:    email,
 			offset:   0,
 			limit:    n,
-			size:     thNameMetaNum,
-			total:    thNameMetaNum,
+			size:     nameMetaNum,
+			total:    nameMetaNum,
 			name:     name,
 			metadata: metadata,
 		},
@@ -525,12 +512,12 @@ func TestMultiThingRetrievalByChannel(t *testing.T) {
 	chid, err := up.ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
 
-	schs, err := channelRepo.Save(context.Background(), things.Channel{
+	chs, err := channelRepo.Save(context.Background(), things.Channel{
 		ID:    chid,
 		Owner: email,
 	})
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-	cid := schs[0].ID
+	cid := chs[0].ID
 	for i := uint64(0); i < n; i++ {
 		thid, err := up.ID()
 		require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
@@ -542,16 +529,16 @@ func TestMultiThingRetrievalByChannel(t *testing.T) {
 			Key:   thkey,
 		}
 
-		sths, err := thingRepo.Save(context.Background(), th)
+		ths, err := thingRepo.Save(context.Background(), th)
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-		tid := sths[0].ID
+		thid = ths[0].ID
 
 		// Don't connnect last Thing
 		if i == n-thsDisconNum {
 			break
 		}
 
-		err = channelRepo.Connect(context.Background(), email, []string{cid}, []string{tid})
+		err = channelRepo.Connect(context.Background(), email, []string{cid}, []string{thid})
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
 	}
 
@@ -631,19 +618,18 @@ func TestThingRemoval(t *testing.T) {
 	dbMiddleware := postgres.NewDatabase(db)
 	thingRepo := postgres.NewThingRepository(dbMiddleware)
 
-	thid, err := uuidProvider.New().ID()
+	id, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-	thkey, err := uuidProvider.New().ID()
+	key, err := uuidProvider.New().ID()
 	require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
-
 	thing := things.Thing{
-		ID:    thid,
+		ID:    id,
 		Owner: email,
-		Key:   thkey,
+		Key:   key,
 	}
 
-	sths, _ := thingRepo.Save(context.Background(), thing)
-	thing.ID = sths[0].ID
+	ths, _ := thingRepo.Save(context.Background(), thing)
+	thing.ID = ths[0].ID
 
 	// show that the removal works the same for both existing and non-existing
 	// (removed) thing
@@ -652,7 +638,6 @@ func TestThingRemoval(t *testing.T) {
 		require.Nil(t, err, fmt.Sprintf("#%d: failed to remove thing due to: %s", i, err))
 
 		_, err = thingRepo.RetrieveByID(context.Background(), email, thing.ID)
-		// require.Equal(t, things.ErrNotFound, err, fmt.Sprintf("#%d: expected %s got %s", i, things.ErrNotFound, err))
 		require.True(t, errors.Contains(err, things.ErrNotFound), fmt.Sprintf("#%d: expected %s got %s", i, things.ErrNotFound, err))
 	}
 }
diff --git a/things/redis/streams_test.go b/things/redis/streams_test.go
index ca4beb9d..92672c72 100644
--- a/things/redis/streams_test.go
+++ b/things/redis/streams_test.go
@@ -91,7 +91,7 @@ func TestCreateThings(t *testing.T) {
 	lastID := "0"
 	for _, tc := range cases {
 		_, err := svc.CreateThings(context.Background(), tc.key, tc.ths...)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 
 		streams := redisClient.XRead(&r.XReadArgs{
 			Streams: []string{streamID, lastID},
@@ -150,8 +150,7 @@ func TestUpdateThing(t *testing.T) {
 	lastID := "0"
 	for _, tc := range cases {
 		err := svc.UpdateThing(context.Background(), tc.key, tc.thing)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
-
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 		streams := redisClient.XRead(&r.XReadArgs{
 			Streams: []string{streamID, lastID},
 			Count:   1,
@@ -318,7 +317,7 @@ func TestCreateChannels(t *testing.T) {
 	lastID := "0"
 	for _, tc := range cases {
 		_, err := svc.CreateChannels(context.Background(), tc.key, tc.chs...)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 
 		streams := redisClient.XRead(&r.XReadArgs{
 			Streams: []string{streamID, lastID},
@@ -386,7 +385,7 @@ func TestUpdateChannel(t *testing.T) {
 	lastID := "0"
 	for _, tc := range cases {
 		err := svc.UpdateChannel(context.Background(), tc.key, tc.channel)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 
 		streams := redisClient.XRead(&r.XReadArgs{
 			Streams: []string{streamID, lastID},
@@ -497,7 +496,7 @@ func TestRemoveChannel(t *testing.T) {
 	lastID := "0"
 	for _, tc := range cases {
 		err := svc.RemoveChannel(context.Background(), tc.key, tc.id)
-		assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
 
 		streams := redisClient.XRead(&r.XReadArgs{
 			Streams: []string{streamID, lastID},
diff --git a/things/service_test.go b/things/service_test.go
index 67bf46bc..296d427a 100644
--- a/things/service_test.go
+++ b/things/service_test.go
@@ -51,23 +51,16 @@ func TestCreateThings(t *testing.T) {
 		err    error
 	}{
 		{
-			desc: "create new things",
-			things: []things.Thing{
-				things.Thing{Name: "a"},
-				things.Thing{Name: "b"},
-				things.Thing{Name: "c"},
-				things.Thing{Name: "d"},
-			},
-			token: token,
-			err:   nil,
+			desc:   "create new things",
+			things: []things.Thing{{Name: "a"}, {Name: "b"}, {Name: "c"}, {Name: "d"}},
+			token:  token,
+			err:    nil,
 		},
 		{
-			desc: "create thing with wrong credentials",
-			things: []things.Thing{
-				things.Thing{Name: "e"},
-			},
-			token: wrongValue,
-			err:   things.ErrUnauthorizedAccess,
+			desc:   "create thing with wrong credentials",
+			things: []things.Thing{{Name: "e"}},
+			token:  wrongValue,
+			err:    things.ErrUnauthorizedAccess,
 		},
 	}
 
@@ -79,8 +72,9 @@ func TestCreateThings(t *testing.T) {
 
 func TestUpdateThing(t *testing.T) {
 	svc := newService(map[string]string{token: email})
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
 	other := things.Thing{ID: wrongID, Key: "x"}
 
 	cases := []struct {
@@ -91,13 +85,13 @@ func TestUpdateThing(t *testing.T) {
 	}{
 		{
 			desc:  "update existing thing",
-			thing: sth,
+			thing: th,
 			token: token,
 			err:   nil,
 		},
 		{
 			desc:  "update thing with wrong credentials",
-			thing: sth,
+			thing: th,
 			token: wrongValue,
 			err:   things.ErrUnauthorizedAccess,
 		},
@@ -118,9 +112,9 @@ func TestUpdateThing(t *testing.T) {
 func TestUpdateKey(t *testing.T) {
 	key := "new-key"
 	svc := newService(map[string]string{token: email})
-	sths, err := svc.CreateThings(context.Background(), token, thing)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
-	sth := sths[0]
+	th := ths[0]
 
 	cases := []struct {
 		desc  string
@@ -132,14 +126,14 @@ func TestUpdateKey(t *testing.T) {
 		{
 			desc:  "update key of an existing thing",
 			token: token,
-			id:    sth.ID,
+			id:    th.ID,
 			key:   key,
 			err:   nil,
 		},
 		{
 			desc:  "update key with invalid credentials",
 			token: wrongValue,
-			id:    sth.ID,
+			id:    th.ID,
 			key:   key,
 			err:   things.ErrUnauthorizedAccess,
 		},
@@ -160,8 +154,9 @@ func TestUpdateKey(t *testing.T) {
 
 func TestViewThing(t *testing.T) {
 	svc := newService(map[string]string{token: email})
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
 
 	cases := map[string]struct {
 		id    string
@@ -169,12 +164,12 @@ func TestViewThing(t *testing.T) {
 		err   error
 	}{
 		"view existing thing": {
-			id:    sth.ID,
+			id:    th.ID,
 			token: token,
 			err:   nil,
 		},
 		"view thing with wrong credentials": {
-			id:    sth.ID,
+			id:    th.ID,
 			token: wrongValue,
 			err:   things.ErrUnauthorizedAccess,
 		},
@@ -200,7 +195,8 @@ func TestListThings(t *testing.T) {
 
 	n := uint64(10)
 	for i := uint64(0); i < n; i++ {
-		svc.CreateThings(context.Background(), token, thing)
+		_, err := svc.CreateThings(context.Background(), token, thing)
+		require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 	}
 
 	cases := map[string]struct {
@@ -275,24 +271,25 @@ func TestListThings(t *testing.T) {
 func TestListThingsByChannel(t *testing.T) {
 	svc := newService(map[string]string{token: email})
 
-	schs, err := svc.CreateChannels(context.Background(), token, channel)
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-	sch := schs[0]
+	ch := chs[0]
 
 	n := uint64(10)
 	thsDisconNum := uint64(1)
 
 	for i := uint64(0); i < n; i++ {
-		sths, err := svc.CreateThings(context.Background(), token, thing)
+		ths, err := svc.CreateThings(context.Background(), token, thing)
 		require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-		sth := sths[0]
+		th := ths[0]
 
 		// Don't connect last Channel
 		if i == n-thsDisconNum {
 			break
 		}
 
-		svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+		err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
+		require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 	}
 
 	// Wait for things and channels to connect
@@ -309,7 +306,7 @@ func TestListThingsByChannel(t *testing.T) {
 	}{
 		"list all things by existing channel": {
 			token:     token,
-			channel:   sch.ID,
+			channel:   ch.ID,
 			offset:    0,
 			limit:     n,
 			connected: true,
@@ -318,7 +315,7 @@ func TestListThingsByChannel(t *testing.T) {
 		},
 		"list half of things by existing channel": {
 			token:     token,
-			channel:   sch.ID,
+			channel:   ch.ID,
 			offset:    n / 2,
 			limit:     n,
 			connected: true,
@@ -327,7 +324,7 @@ func TestListThingsByChannel(t *testing.T) {
 		},
 		"list last thing by existing channel": {
 			token:     token,
-			channel:   sch.ID,
+			channel:   ch.ID,
 			offset:    n - 1 - thsDisconNum,
 			limit:     n,
 			connected: true,
@@ -336,7 +333,7 @@ func TestListThingsByChannel(t *testing.T) {
 		},
 		"list empty set of things by existing channel": {
 			token:     token,
-			channel:   sch.ID,
+			channel:   ch.ID,
 			offset:    n + 1,
 			limit:     n,
 			connected: true,
@@ -345,7 +342,7 @@ func TestListThingsByChannel(t *testing.T) {
 		},
 		"list things by existing channel with zero limit": {
 			token:     token,
-			channel:   sch.ID,
+			channel:   ch.ID,
 			offset:    1,
 			limit:     0,
 			connected: true,
@@ -354,7 +351,7 @@ func TestListThingsByChannel(t *testing.T) {
 		},
 		"list things by existing channel with wrong credentials": {
 			token:     wrongValue,
-			channel:   sch.ID,
+			channel:   ch.ID,
 			offset:    0,
 			limit:     0,
 			connected: true,
@@ -372,7 +369,7 @@ func TestListThingsByChannel(t *testing.T) {
 		},
 		"list all non connected things by existing channel": {
 			token:     token,
-			channel:   sch.ID,
+			channel:   ch.ID,
 			offset:    0,
 			limit:     n,
 			connected: false,
@@ -391,8 +388,9 @@ func TestListThingsByChannel(t *testing.T) {
 
 func TestRemoveThing(t *testing.T) {
 	svc := newService(map[string]string{token: email})
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	sth := ths[0]
 
 	cases := []struct {
 		desc  string
@@ -442,36 +440,30 @@ func TestCreateChannels(t *testing.T) {
 		err      error
 	}{
 		{
-			desc: "create new channels",
-			channels: []things.Channel{
-				things.Channel{Name: "a"},
-				things.Channel{Name: "b"},
-				things.Channel{Name: "c"},
-				things.Channel{Name: "d"},
-			},
-			token: token,
-			err:   nil,
+			desc:     "create new channels",
+			channels: []things.Channel{{Name: "a"}, {Name: "b"}, {Name: "c"}, {Name: "d"}},
+			token:    token,
+			err:      nil,
 		},
 		{
-			desc: "create channel with wrong credentials",
-			channels: []things.Channel{
-				things.Channel{Name: "e"},
-			},
-			token: wrongValue,
-			err:   things.ErrUnauthorizedAccess,
+			desc:     "create channel with wrong credentials",
+			channels: []things.Channel{{Name: "e"}},
+			token:    wrongValue,
+			err:      things.ErrUnauthorizedAccess,
 		},
 	}
 
 	for _, cc := range cases {
 		_, err := svc.CreateChannels(context.Background(), cc.token, cc.channels...)
-		assert.Equal(t, cc.err, err, fmt.Sprintf("%s: expected %s got %s\n", cc.desc, cc.err, err))
+		assert.True(t, errors.Contains(err, cc.err), fmt.Sprintf("%s: expected %s got %s\n", cc.desc, cc.err, err))
 	}
 }
 
 func TestUpdateChannel(t *testing.T) {
 	svc := newService(map[string]string{token: email})
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
 	other := things.Channel{ID: wrongID}
 
 	cases := []struct {
@@ -482,13 +474,13 @@ func TestUpdateChannel(t *testing.T) {
 	}{
 		{
 			desc:    "update existing channel",
-			channel: sch,
+			channel: ch,
 			token:   token,
 			err:     nil,
 		},
 		{
 			desc:    "update channel with wrong credentials",
-			channel: sch,
+			channel: ch,
 			token:   wrongValue,
 			err:     things.ErrUnauthorizedAccess,
 		},
@@ -508,8 +500,9 @@ func TestUpdateChannel(t *testing.T) {
 
 func TestViewChannel(t *testing.T) {
 	svc := newService(map[string]string{token: email})
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
 
 	cases := map[string]struct {
 		id       string
@@ -518,12 +511,12 @@ func TestViewChannel(t *testing.T) {
 		metadata things.Metadata
 	}{
 		"view existing channel": {
-			id:    sch.ID,
+			id:    ch.ID,
 			token: token,
 			err:   nil,
 		},
 		"view channel with wrong credentials": {
-			id:    sch.ID,
+			id:    ch.ID,
 			token: wrongValue,
 			err:   things.ErrUnauthorizedAccess,
 		},
@@ -642,9 +635,9 @@ func TestListChannels(t *testing.T) {
 func TestListChannelsByThing(t *testing.T) {
 	svc := newService(map[string]string{token: email})
 
-	sths, err := svc.CreateThings(context.Background(), token, thing)
+	ths, err := svc.CreateThings(context.Background(), token, thing)
 	require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
-	sth := sths[0]
+	th := ths[0]
 
 	n := uint64(10)
 	chsDisconNum := uint64(1)
@@ -659,7 +652,8 @@ func TestListChannelsByThing(t *testing.T) {
 			break
 		}
 
-		svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+		err = svc.Connect(context.Background(), token, []string{sch.ID}, []string{th.ID})
+		require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 	}
 
 	// Wait for things and channels to connect.
@@ -676,7 +670,7 @@ func TestListChannelsByThing(t *testing.T) {
 	}{
 		"list all channels by existing thing": {
 			token:     token,
-			thing:     sth.ID,
+			thing:     th.ID,
 			offset:    0,
 			limit:     n,
 			connected: true,
@@ -685,7 +679,7 @@ func TestListChannelsByThing(t *testing.T) {
 		},
 		"list half of channels by existing thing": {
 			token:     token,
-			thing:     sth.ID,
+			thing:     th.ID,
 			offset:    n / 2,
 			limit:     n,
 			connected: true,
@@ -694,7 +688,7 @@ func TestListChannelsByThing(t *testing.T) {
 		},
 		"list last channel by existing thing": {
 			token:     token,
-			thing:     sth.ID,
+			thing:     th.ID,
 			offset:    n - 1 - chsDisconNum,
 			limit:     n,
 			connected: true,
@@ -703,7 +697,7 @@ func TestListChannelsByThing(t *testing.T) {
 		},
 		"list empty set of channels by existing thing": {
 			token:     token,
-			thing:     sth.ID,
+			thing:     th.ID,
 			offset:    n + 1,
 			limit:     n,
 			connected: true,
@@ -712,7 +706,7 @@ func TestListChannelsByThing(t *testing.T) {
 		},
 		"list channels by existing thing with zero limit": {
 			token:     token,
-			thing:     sth.ID,
+			thing:     th.ID,
 			offset:    1,
 			limit:     0,
 			connected: true,
@@ -721,7 +715,7 @@ func TestListChannelsByThing(t *testing.T) {
 		},
 		"list channels by existing thing with wrong credentials": {
 			token:     wrongValue,
-			thing:     sth.ID,
+			thing:     th.ID,
 			offset:    0,
 			limit:     0,
 			connected: true,
@@ -739,7 +733,7 @@ func TestListChannelsByThing(t *testing.T) {
 		},
 		"list all non connected channels by existing thing": {
 			token:     token,
-			thing:     sth.ID,
+			thing:     th.ID,
 			offset:    0,
 			limit:     n,
 			connected: false,
@@ -758,8 +752,9 @@ func TestListChannelsByThing(t *testing.T) {
 
 func TestRemoveChannel(t *testing.T) {
 	svc := newService(map[string]string{token: email})
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
 
 	cases := []struct {
 		desc  string
@@ -769,25 +764,25 @@ func TestRemoveChannel(t *testing.T) {
 	}{
 		{
 			desc:  "remove channel with wrong credentials",
-			id:    sch.ID,
+			id:    ch.ID,
 			token: wrongValue,
 			err:   things.ErrUnauthorizedAccess,
 		},
 		{
 			desc:  "remove existing channel",
-			id:    sch.ID,
+			id:    ch.ID,
 			token: token,
 			err:   nil,
 		},
 		{
 			desc:  "remove removed channel",
-			id:    sch.ID,
+			id:    ch.ID,
 			token: token,
 			err:   nil,
 		},
 		{
 			desc:  "remove non-existing channel",
-			id:    sch.ID,
+			id:    ch.ID,
 			token: token,
 			err:   nil,
 		},
@@ -802,10 +797,12 @@ func TestRemoveChannel(t *testing.T) {
 func TestConnect(t *testing.T) {
 	svc := newService(map[string]string{token: email})
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
 
 	cases := []struct {
 		desc    string
@@ -817,28 +814,28 @@ func TestConnect(t *testing.T) {
 		{
 			desc:    "connect thing",
 			token:   token,
-			chanID:  sch.ID,
-			thingID: sth.ID,
+			chanID:  ch.ID,
+			thingID: th.ID,
 			err:     nil,
 		},
 		{
 			desc:    "connect thing with wrong credentials",
 			token:   wrongValue,
-			chanID:  sch.ID,
-			thingID: sth.ID,
+			chanID:  ch.ID,
+			thingID: th.ID,
 			err:     things.ErrUnauthorizedAccess,
 		},
 		{
 			desc:    "connect thing to non-existing channel",
 			token:   token,
 			chanID:  wrongID,
-			thingID: sth.ID,
+			thingID: th.ID,
 			err:     things.ErrNotFound,
 		},
 		{
 			desc:    "connect non-existing thing to channel",
 			token:   token,
-			chanID:  sch.ID,
+			chanID:  ch.ID,
 			thingID: wrongID,
 			err:     things.ErrNotFound,
 		},
@@ -853,11 +850,14 @@ func TestConnect(t *testing.T) {
 func TestDisconnect(t *testing.T) {
 	svc := newService(map[string]string{token: email})
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
-	svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
+	err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 
 	cases := []struct {
 		desc    string
@@ -869,35 +869,35 @@ func TestDisconnect(t *testing.T) {
 		{
 			desc:    "disconnect connected thing",
 			token:   token,
-			chanID:  sch.ID,
-			thingID: sth.ID,
+			chanID:  ch.ID,
+			thingID: th.ID,
 			err:     nil,
 		},
 		{
 			desc:    "disconnect disconnected thing",
 			token:   token,
-			chanID:  sch.ID,
-			thingID: sth.ID,
+			chanID:  ch.ID,
+			thingID: th.ID,
 			err:     things.ErrNotFound,
 		},
 		{
 			desc:    "disconnect with wrong credentials",
 			token:   wrongValue,
-			chanID:  sch.ID,
-			thingID: sth.ID,
+			chanID:  ch.ID,
+			thingID: th.ID,
 			err:     things.ErrUnauthorizedAccess,
 		},
 		{
 			desc:    "disconnect from non-existing channel",
 			token:   token,
 			chanID:  wrongID,
-			thingID: sth.ID,
+			thingID: th.ID,
 			err:     things.ErrNotFound,
 		},
 		{
 			desc:    "disconnect non-existing thing",
 			token:   token,
-			chanID:  sch.ID,
+			chanID:  ch.ID,
 			thingID: wrongID,
 			err:     things.ErrNotFound,
 		},
@@ -913,11 +913,12 @@ func TestDisconnect(t *testing.T) {
 func TestCanAccessByKey(t *testing.T) {
 	svc := newService(map[string]string{token: email})
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
-	svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	chs, err := svc.CreateChannels(context.Background(), token, channel, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	err = svc.Connect(context.Background(), token, []string{chs[0].ID}, []string{ths[0].ID})
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 
 	cases := map[string]struct {
 		token   string
@@ -925,36 +926,44 @@ func TestCanAccessByKey(t *testing.T) {
 		err     error
 	}{
 		"allowed access": {
-			token:   sth.Key,
-			channel: sch.ID,
+			token:   ths[0].Key,
+			channel: chs[0].ID,
 			err:     nil,
 		},
-		"not-connected cannot access": {
+		"non-existing thing": {
 			token:   wrongValue,
-			channel: sch.ID,
-			err:     things.ErrUnauthorizedAccess,
+			channel: chs[0].ID,
+			err:     things.ErrNotFound,
 		},
-		"access to non-existing channel": {
-			token:   sth.Key,
-			channel: wrongID,
-			err:     things.ErrUnauthorizedAccess,
+		"non-existing chan": {
+			token:   ths[0].Key,
+			channel: wrongValue,
+			err:     things.ErrEntityConnected,
+		},
+		"non-connected channel": {
+			token:   ths[0].Key,
+			channel: chs[1].ID,
+			err:     things.ErrEntityConnected,
 		},
 	}
 
 	for desc, tc := range cases {
 		_, err := svc.CanAccessByKey(context.Background(), tc.channel, tc.token)
-		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", desc, tc.err, err))
+		assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected '%s' got '%s'\n", desc, tc.err, err))
 	}
 }
 
 func TestCanAccessByID(t *testing.T) {
 	svc := newService(map[string]string{token: email})
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
-	schs, _ := svc.CreateChannels(context.Background(), token, channel)
-	sch := schs[0]
-	svc.Connect(context.Background(), token, []string{sch.ID}, []string{sth.ID})
+	ths, err := svc.CreateThings(context.Background(), token, thing, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
+	chs, err := svc.CreateChannels(context.Background(), token, channel)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	ch := chs[0]
+	err = svc.Connect(context.Background(), token, []string{ch.ID}, []string{th.ID})
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
 
 	cases := map[string]struct {
 		thingID string
@@ -962,19 +971,24 @@ func TestCanAccessByID(t *testing.T) {
 		err     error
 	}{
 		"allowed access": {
-			thingID: sth.ID,
-			channel: sch.ID,
+			thingID: th.ID,
+			channel: ch.ID,
 			err:     nil,
 		},
-		"not-connected cannot access": {
+		"access to non-existing thing": {
 			thingID: wrongValue,
-			channel: sch.ID,
-			err:     things.ErrUnauthorizedAccess,
+			channel: ch.ID,
+			err:     things.ErrEntityConnected,
 		},
 		"access to non-existing channel": {
-			thingID: sth.ID,
+			thingID: th.ID,
 			channel: wrongID,
-			err:     things.ErrUnauthorizedAccess,
+			err:     things.ErrEntityConnected,
+		},
+		"access to not-connected thing": {
+			thingID: ths[1].ID,
+			channel: ch.ID,
+			err:     things.ErrEntityConnected,
 		},
 	}
 
@@ -987,8 +1001,9 @@ func TestCanAccessByID(t *testing.T) {
 func TestIdentify(t *testing.T) {
 	svc := newService(map[string]string{token: email})
 
-	sths, _ := svc.CreateThings(context.Background(), token, thing)
-	sth := sths[0]
+	ths, err := svc.CreateThings(context.Background(), token, thing)
+	require.Nil(t, err, fmt.Sprintf("unexpected error: %s\n", err))
+	th := ths[0]
 
 	cases := map[string]struct {
 		token string
@@ -996,14 +1011,14 @@ func TestIdentify(t *testing.T) {
 		err   error
 	}{
 		"identify existing thing": {
-			token: sth.Key,
-			id:    sth.ID,
+			token: th.Key,
+			id:    th.ID,
 			err:   nil,
 		},
 		"identify non-existing thing": {
 			token: wrongValue,
 			id:    wrongID,
-			err:   things.ErrUnauthorizedAccess,
+			err:   things.ErrNotFound,
 		},
 	}