Repository: TBD54566975/ssi-service
Pull request #126 (2022-10-11 20:38:03)

Support schema usage in the credential service
- allow referencing schemas from the cred service
- streamlined service status / init code

codecov-commenter: # [Codecov](https://codecov.io/gh/TBD54566975/ssi-service/pull/126?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) Report
> Merging [#126](https://codecov.io/gh/TBD54566975/ssi-service/pull/126?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (57218a1) into [main](https://codecov.io/gh/TBD54566975/ssi-service/commit/cbc49af9caec60585274b105b2224914fb4031e4?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (cbc49af) will **increase** coverage by `0.11%`.
> The diff coverage is `36.36%`.

```diff
@@            Coverage Diff             @@
##             main     #126      +/-   ##
==========================================
+ Coverage   27.88%   28.00%   +0.11%     
==========================================
  Files          20       20              
  Lines        1467     1475       +8     
==========================================
+ Hits          409      413       +4     
- Misses        994      995       +1     
- Partials       64       67       +3     
```


| [Impacted Files](https://codecov.io/gh/TBD54566975/ssi-service/pull/126?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) | Coverage Δ | |
|---|---|---|
| [pkg/service/keystore/keystore.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/126/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZpY2Uva2V5c3RvcmUva2V5c3RvcmUuZ28=) | `43.47% <36.36%> (+0.40%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975)

decentralgabe: the manifest test will fail until this is resolved and uptaken in the ssi-sdk, which needs to be uptaken here https://github.com/decentralized-identity/credential-manifest/pull/122
decentralgabe: Relies on uptake in https://github.com/TBD54566975/ssi-sdk/pull/224

Patch:
diff --git a/README.md b/README.md
index 01cd244..b8a55b4 100644
--- a/README.md
+++ b/README.md
@@ -128,10 +128,10 @@ project.
 
 - [x] [DID Management](https://www.w3.org/TR/did-core/) - Using [did:key](https://w3c-ccg.github.io/did-method-key/)
 - [x] [Verifiable Credential Schema](https://w3c-ccg.github.io/vc-json-schemas/v2/index.html) Management
-- [ ] [Verifiable Credential](https://www.w3.org/TR/vc-data-model) Issuance & Verification
+- [x] [Verifiable Credential](https://www.w3.org/TR/vc-data-model) Issuance & Verification
+- [x] Applying for Verifiable Credentials using [Credential Manifest](https://identity.foundation/credential-manifest/)
 - [ ] Requesting, Receiving, and the Validation of Verifiable Claims
   using [Presentation Exchange](https://identity.foundation/presentation-exchange/)
-- [ ] Applying for Verifiable Credentials using [Credential Manifest](https://identity.foundation/credential-manifest/)
 - [ ] Revocations of Verifiable Credentials using the [Status List 2021](https://w3c-ccg.github.io/vc-status-list-2021/)
 - [ ] [Decentralized Web Node](https://identity.foundation/decentralized-web-node/spec/) Messaging
 
@@ -139,9 +139,9 @@ project.
 
 | Resource                                                                                   | Description                                                                   |
 |--------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
-| [VISION](https://github.com/TBD54566975/ssi-service/blob/main/doc/VISION.md)                   | Outlines the project vision                                                   |
+| [VISION](https://github.com/TBD54566975/ssi-service/blob/main/doc/VISION.md)               | Outlines the project vision                                                   |
 | [SIPs](sip/README.md)                                                                      | Proposals for improving the SSI Service                                       |
-| [VERSIONING](https://github.com/TBD54566975/ssi-service/blob/main/doc/VERSIONING.md)           | Project versioning strategy                                                   |
+| [VERSIONING](https://github.com/TBD54566975/ssi-service/blob/main/doc/VERSIONING.md)       | Project versioning strategy                                                   |
 | [CODEOWNERS](https://github.com/TBD54566975/ssi-service/blob/main/CODEOWNERS)              | Outlines the project lead(s)                                                  |
 | [CODE_OF_CONDUCT](https://github.com/TBD54566975/ssi-service/blob/main/CODE_OF_CONDUCT.md) | Expected behavior for project contributors, promoting a welcoming environment |
 | [CONTRIBUTING](https://github.com/TBD54566975/ssi-service/blob/main/CONTRIBUTING.md)       | Developer guide to build, test, run, access CI, chat, discuss, file issues    |
diff --git a/go.mod b/go.mod
index 497ce0f..b75aaeb 100644
--- a/go.mod
+++ b/go.mod
@@ -4,15 +4,18 @@ go 1.19
 
 require (
 	github.com/BurntSushi/toml v1.2.0
-	github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221007180051-d48966db0f15
+	github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221012163631-99a9a918234b
 	github.com/ardanlabs/conf v1.5.0
 	github.com/dimfeld/httptreemux/v5 v5.4.0
 	github.com/go-playground/locales v0.14.0
 	github.com/go-playground/universal-translator v0.18.0
 	github.com/goccy/go-json v0.9.11
 	github.com/google/uuid v1.3.0
+	github.com/lestrrat-go/jwx v1.2.25
 	github.com/magefile/mage v1.14.0
 	github.com/mr-tron/base58 v1.2.0
+	github.com/multiformats/go-multibase v0.1.1
+	github.com/multiformats/go-varint v0.0.6
 	github.com/pkg/errors v0.9.1
 	github.com/sirupsen/logrus v1.9.0
 	github.com/stretchr/testify v1.8.0
@@ -36,15 +39,12 @@ require (
 	github.com/lestrrat-go/blackmagic v1.0.0 // indirect
 	github.com/lestrrat-go/httpcc v1.0.1 // indirect
 	github.com/lestrrat-go/iter v1.0.1 // indirect
-	github.com/lestrrat-go/jwx v1.2.25 // indirect
 	github.com/lestrrat-go/option v1.0.0 // indirect
 	github.com/multiformats/go-base32 v0.0.3 // indirect
 	github.com/multiformats/go-base36 v0.1.0 // indirect
-	github.com/multiformats/go-multibase v0.1.1 // indirect
 	github.com/multiformats/go-multicodec v0.6.0 // indirect
-	github.com/multiformats/go-varint v0.0.6 // indirect
 	github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect
-	github.com/piprate/json-gold v0.4.1 // indirect
+	github.com/piprate/json-gold v0.4.2 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/pquerna/cachecontrol v0.1.0 // indirect
 	github.com/rogpeppe/go-internal v1.8.1 // indirect
diff --git a/go.sum b/go.sum
index 9cf6e77..9b63c88 100644
--- a/go.sum
+++ b/go.sum
@@ -1,19 +1,7 @@
 github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
 github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20220919021815-57be087eca80 h1:1HBBtzkjsgjCYjMVWi6+785SO+Q7kSOOrA0Njw3JON0=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20220919021815-57be087eca80/go.mod h1:ZUcjj/CHvtmz48c9GapcbavlTRsN9JZ9pKdT+co/EvY=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20220920154030-cbf6b4665a6d h1:NW/9Qg2Z+Yhh6PtzgV/cFwgNz7Sgng3E25IYQiUV34c=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20220920154030-cbf6b4665a6d/go.mod h1:jkbaZT2qU+g6weOHpjPdxuHdmfOApdT8CQg41GEyZhA=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20220921215642-f749c4d89b8b h1:0IJJPN8qBGEINcNheyMN/VztIj/Wu9OLzoaEdwfKMWM=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20220921215642-f749c4d89b8b/go.mod h1:jkbaZT2qU+g6weOHpjPdxuHdmfOApdT8CQg41GEyZhA=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221001002612-ec8641015c21 h1:tsvfXXVW2rqdPIYJ5uLSUhTXG4C6niB9FmjpgQE/f9w=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221001002612-ec8641015c21/go.mod h1:jkbaZT2qU+g6weOHpjPdxuHdmfOApdT8CQg41GEyZhA=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221006024829-0be992d222cd h1:TfikEZGgOY0nSlJ3GlIBLisMu9zkV0cIXg+dbXX4poI=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221006024829-0be992d222cd/go.mod h1:jkbaZT2qU+g6weOHpjPdxuHdmfOApdT8CQg41GEyZhA=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221007010336-560f7ccb3b93 h1:paLRTB3VnfKfcJgx43faOgVM2ypKFJDrvovq5/BykL0=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221007010336-560f7ccb3b93/go.mod h1:oi28ndJG+ksI/NvGI+x7t6xHiDXYGOYxORTjuVynklQ=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221007180051-d48966db0f15 h1:tg8HA0K2/a7X6K/K5ayToC7Yrout5+v2CZH5sGpX2mc=
-github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221007180051-d48966db0f15/go.mod h1:oi28ndJG+ksI/NvGI+x7t6xHiDXYGOYxORTjuVynklQ=
+github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221012163631-99a9a918234b h1:7JhNPNNGDdIB7Q6kTaHd3cirG1xcDsmEX2ryK+a5iKM=
+github.com/TBD54566975/ssi-sdk v0.0.1-alpha.0.20221012163631-99a9a918234b/go.mod h1:zmrYK0NCOKbD6lOOXzZBN51RN6Ai78HuZ3Jt0tqbkm0=
 github.com/ardanlabs/conf v1.5.0 h1:5TwP6Wu9Xi07eLFEpiCUF3oQXh9UzHMDVnD3u/I5d5c=
 github.com/ardanlabs/conf v1.5.0/go.mod h1:ILsMo9dMqYzCxDjDXTiwMI0IgxOJd0MOiucbQY2wlJw=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@@ -37,8 +25,6 @@ github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
-github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
-github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
 github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
 github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
 github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
@@ -87,8 +73,8 @@ github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2
 github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
 github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjGmesFh1D0rDy+q1Twx6FyU7VWHi8wZbI=
 github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4=
-github.com/piprate/json-gold v0.4.1 h1:JYbYN36n6YcAYipKy3ttv3X2HDQPeqWqmwta35NPj04=
-github.com/piprate/json-gold v0.4.1/go.mod h1:OK1z7UgtBZk06n2cDE2OSq1kffmjFFp5/2yhLLCz9UM=
+github.com/piprate/json-gold v0.4.2 h1:Rq8V+637HOFcj20KdTqW/g/llCwX2qtau0g5d1pD79o=
+github.com/piprate/json-gold v0.4.2/go.mod h1:OK1z7UgtBZk06n2cDE2OSq1kffmjFFp5/2yhLLCz9UM=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -132,10 +118,6 @@ go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zA
 go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
-golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 h1:a5Yg6ylndHHYJqIPrdq0AhvR6KTvDTAvgBtaidhEevY=
-golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b h1:huxqepDufQpLLIRXiVkTvnxrzJlpwmIWAObmcCcUFr0=
 golang.org/x/crypto v0.0.0-20221005025214-4161e89ecf1b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -145,15 +127,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
-golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc=
-golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 h1:AzgQNqF+FKwyQ5LbVrVqOcuuFB67N47F9+htZYH0wFM=
 golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
-golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.0.0-20220919170432-7a66f970e087 h1:tPwmk4vmvVCMdr98VgL4JH+qZxPL8fqlUOHnyOM8N3w=
 golang.org/x/term v0.0.0-20220919170432-7a66f970e087/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
diff --git a/pkg/service/credential/credential.go b/pkg/service/credential/credential.go
index 297c5c8..01f3075 100644
--- a/pkg/service/credential/credential.go
+++ b/pkg/service/credential/credential.go
@@ -5,7 +5,9 @@ import (
 	"time"
 
 	"github.com/TBD54566975/ssi-sdk/credential"
+	schemalib "github.com/TBD54566975/ssi-sdk/credential/schema"
 	didint "github.com/TBD54566975/ssi-sdk/did"
+	sdkutil "github.com/TBD54566975/ssi-sdk/util"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
@@ -16,6 +18,7 @@ import (
 	credstorage "github.com/tbd54566975/ssi-service/pkg/service/credential/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
+	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
@@ -26,6 +29,7 @@ type Service struct {
 
 	// external dependencies
 	keyStore *keystore.Service
+	schema   *schema.Service
 }
 
 func (s Service) Type() framework.Type {
@@ -33,10 +37,23 @@ func (s Service) Type() framework.Type {
 }
 
 func (s Service) Status() framework.Status {
+	ae := sdkutil.NewAppendError()
 	if s.storage == nil {
+		ae.AppendString("no storage configured")
+	}
+	if s.verifier == nil {
+		ae.AppendString("no credential verifier configured")
+	}
+	if s.keyStore == nil {
+		ae.AppendString("no key store service configured")
+	}
+	if s.schema == nil {
+		ae.AppendString("no schema service configured")
+	}
+	if !ae.IsEmpty() {
 		return framework.Status{
 			Status:  framework.StatusNotReady,
-			Message: "no storage",
+			Message: fmt.Sprintf("credential service is not ready: %s", ae.Error().Error()),
 		}
 	}
 	return framework.Status{Status: framework.StatusReady}
@@ -46,7 +63,7 @@ func (s Service) Config() config.CredentialServiceConfig {
 	return s.config
 }
 
-func NewCredentialService(config config.CredentialServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, resolver *didint.Resolver) (*Service, error) {
+func NewCredentialService(config config.CredentialServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, resolver *didint.Resolver, schema *schema.Service) (*Service, error) {
 	credentialStorage, err := credstorage.NewCredentialStorage(s)
 	if err != nil {
 		errMsg := "could not instantiate storage for the credential service"
@@ -56,12 +73,17 @@ func NewCredentialService(config config.CredentialServiceConfig, s storage.Servi
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate verifier for the credential service")
 	}
-	return &Service{
+	service := Service{
 		storage:  credentialStorage,
 		config:   config,
 		verifier: verifier,
 		keyStore: keyStore,
-	}, nil
+		schema:   schema,
+	}
+	if !service.Status().IsReady() {
+		return nil, errors.New(service.Status().Message)
+	}
+	return &service, nil
 }
 
 func (s Service) CreateCredential(request CreateCredentialRequest) (*CreateCredentialResponse, error) {
@@ -99,12 +121,21 @@ func (s Service) CreateCredential(request CreateCredentialRequest) (*CreateCrede
 	}
 
 	// if a schema value exists, verify we can access it, validate the data against it, then set it
+	var credSchema *schemalib.VCJSONSchema
 	if request.JSONSchema != "" {
-		schema := credential.CredentialSchema{
+		// resolve schema and save it for validation later
+		gotSchema, err := s.schema.GetSchema(schema.GetSchemaRequest{ID: request.JSONSchema})
+		if err != nil {
+			errMsg := fmt.Sprintf("failed to create credential; could not get schema: %s", request.JSONSchema)
+			return nil, util.LoggingErrorMsg(err, errMsg)
+		}
+		credSchema = &gotSchema.Schema
+
+		credSchema := credential.CredentialSchema{
 			ID:   request.JSONSchema,
 			Type: SchemaType,
 		}
-		if err := builder.SetCredentialSchema(schema); err != nil {
+		if err = builder.SetCredentialSchema(credSchema); err != nil {
 			errMsg := fmt.Sprintf("could not set JSON Schema for credential: %s", request.JSONSchema)
 			return nil, util.LoggingErrorMsg(err, errMsg)
 		}
@@ -129,6 +160,14 @@ func (s Service) CreateCredential(request CreateCredentialRequest) (*CreateCrede
 		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 
+	// verify the built schema complies with the schema we've set
+	if credSchema != nil {
+		if err = schemalib.IsCredentialValidForVCJSONSchema(*cred, *credSchema); err != nil {
+			errMsg := fmt.Sprintf("credential data does not comply with the provided schema: %s", request.JSONSchema)
+			return nil, util.LoggingErrorMsg(err, errMsg)
+		}
+	}
+
 	// TODO(gabe) support Data Integrity creds too https://github.com/TBD54566975/ssi-service/issues/105
 	// sign the credential
 	credJWT, err := s.signCredentialJWT(request.Issuer, *cred)
diff --git a/pkg/service/did/did.go b/pkg/service/did/did.go
index 11daeb9..88d5863 100644
--- a/pkg/service/did/did.go
+++ b/pkg/service/did/did.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
+	sdkutil "github.com/TBD54566975/ssi-sdk/util"
 	"github.com/pkg/errors"
 
 	"github.com/tbd54566975/ssi-service/config"
@@ -27,11 +28,40 @@ type Service struct {
 	keyStore *keystore.Service
 }
 
-// MethodHandler describes the functionality of *all* possible DID service, regardless of method
-type MethodHandler interface {
-	CreateDID(request CreateDIDRequest) (*CreateDIDResponse, error)
-	GetDID(request GetDIDRequest) (*GetDIDResponse, error)
-	GetDIDs(method didsdk.Method) (*GetDIDsResponse, error)
+func (s *Service) Type() framework.Type {
+	return framework.DID
+}
+
+// Status is a self-reporting status for the DID service.
+func (s *Service) Status() framework.Status {
+	ae := sdkutil.NewAppendError()
+	if s.storage == nil {
+		ae.AppendString("no storage configured")
+	}
+	if len(s.handlers) == 0 {
+		ae.AppendString("no did handlers configured")
+	}
+	if s.keyStore == nil {
+		ae.AppendString("no key store service configured")
+	}
+	if s.resolver == nil {
+		ae.AppendString("no resolver configured")
+	}
+	if !ae.IsEmpty() {
+		return framework.Status{
+			Status:  framework.StatusNotReady,
+			Message: fmt.Sprintf("did service is not ready: %s", ae.Error().Error()),
+		}
+	}
+	return framework.Status{Status: framework.StatusReady}
+}
+
+func (s *Service) Config() config.DIDServiceConfig {
+	return s.config
+}
+
+func (s *Service) GetResolver() *didsdk.Resolver {
+	return s.resolver
 }
 
 func NewDIDService(config config.DIDServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service) (*Service, error) {
@@ -46,7 +76,7 @@ func NewDIDService(config config.DIDServiceConfig, s storage.ServiceStorage, key
 		return nil, errors.Wrap(err, "could not instantiate DID resolver")
 	}
 
-	svc := Service{
+	service := Service{
 		storage:  didStorage,
 		handlers: make(map[didsdk.Method]MethodHandler),
 		keyStore: keyStore,
@@ -55,12 +85,22 @@ func NewDIDService(config config.DIDServiceConfig, s storage.ServiceStorage, key
 
 	// instantiate all handlers for DID methods
 	for _, m := range config.Methods {
-		if err := svc.instantiateHandlerForMethod(didsdk.Method(m)); err != nil {
+		if err = service.instantiateHandlerForMethod(didsdk.Method(m)); err != nil {
 			return nil, errors.Wrap(err, "could not instantiate DID service")
 		}
 	}
 
-	return &svc, nil
+	if !service.Status().IsReady() {
+		return nil, errors.New(service.Status().Message)
+	}
+	return &service, nil
+}
+
+// MethodHandler describes the functionality of *all* possible DID service, regardless of method
+type MethodHandler interface {
+	CreateDID(request CreateDIDRequest) (*CreateDIDResponse, error)
+	GetDID(request GetDIDRequest) (*GetDIDResponse, error)
+	GetDIDs(method didsdk.Method) (*GetDIDsResponse, error)
 }
 
 func (s *Service) instantiateHandlerForMethod(method didsdk.Method) error {
@@ -79,29 +119,6 @@ func (s *Service) instantiateHandlerForMethod(method didsdk.Method) error {
 	return nil
 }
 
-func (s *Service) Type() framework.Type {
-	return framework.DID
-}
-
-// Status is a self-reporting status for the DID service.
-func (s *Service) Status() framework.Status {
-	if s.storage == nil || len(s.handlers) == 0 {
-		return framework.Status{
-			Status:  framework.StatusNotReady,
-			Message: "storage not loaded and/or no DID methods loaded",
-		}
-	}
-	return framework.Status{Status: framework.StatusReady}
-}
-
-func (s *Service) Config() config.DIDServiceConfig {
-	return s.config
-}
-
-func (s *Service) GetResolver() *didsdk.Resolver {
-	return s.resolver
-}
-
 func (s *Service) ResolveDID(request ResolveDIDRequest) (*ResolveDIDResponse, error) {
 	if request.DID == "" {
 		return nil, util.LoggingNewError("cannot resolve empty DID")
diff --git a/pkg/service/did/key.go b/pkg/service/did/key.go
index 15da7fb..bd9c72c 100644
--- a/pkg/service/did/key.go
+++ b/pkg/service/did/key.go
@@ -39,7 +39,7 @@ func (h *keyDIDHandler) CreateDID(request CreateDIDRequest) (*CreateDIDResponse,
 	}
 
 	// store metadata in DID storage
-	id := doc.ToString()
+	id := doc.String()
 	storedDID := storage.StoredDID{
 		ID:  id,
 		DID: *expanded,
diff --git a/pkg/service/dwn/dwn.go b/pkg/service/dwn/dwn.go
index bfd0801..c136968 100644
--- a/pkg/service/dwn/dwn.go
+++ b/pkg/service/dwn/dwn.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 
 	sdkutil "github.com/TBD54566975/ssi-sdk/util"
+	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
 	"github.com/tbd54566975/ssi-service/config"
@@ -27,17 +28,17 @@ func (s Service) Type() framework.Type {
 }
 
 func (s Service) Status() framework.Status {
-	err := sdkutil.NewAppendError()
+	ae := sdkutil.NewAppendError()
 	if s.keyStore == nil {
-		err.AppendString("keystore not set")
+		ae.AppendString("no key store service configured")
 	}
 	if s.manifest == nil {
-		err.AppendString("manifest not set")
+		ae.AppendString("no manifest service configured")
 	}
-	if gotErr := err.Error(); gotErr != nil {
+	if !ae.IsEmpty() {
 		return framework.Status{
 			Status:  framework.StatusNotReady,
-			Message: gotErr.Error(),
+			Message: fmt.Sprintf("dwn service is not ready: %s", ae.Error().Error()),
 		}
 	}
 	return framework.Status{Status: framework.StatusReady}
@@ -48,17 +49,15 @@ func (s Service) Config() config.DWNServiceConfig {
 }
 
 func NewDWNService(config config.DWNServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, manifest *manifest.Service) (*Service, error) {
-	if keyStore == nil {
-		return nil, fmt.Errorf("keystore not set")
-	}
-	if manifest == nil {
-		return nil, fmt.Errorf("manifest not set")
-	}
-	return &Service{
+	service := Service{
 		config:   config,
 		keyStore: keyStore,
 		manifest: manifest,
-	}, nil
+	}
+	if !service.Status().IsReady() {
+		return nil, errors.New(service.Status().Message)
+	}
+	return &service, nil
 }
 
 func (s Service) GetManifest(request DWNPublishManifestRequest) (*DWNPublishManifestResponse, error) {
diff --git a/pkg/service/framework/framework.go b/pkg/service/framework/framework.go
index 3175dc8..c0df108 100644
--- a/pkg/service/framework/framework.go
+++ b/pkg/service/framework/framework.go
@@ -29,6 +29,10 @@ type Status struct {
 	Message string      `json:"message,omitempty"`
 }
 
+func (s Status) IsReady() bool {
+	return s.Status == StatusReady
+}
+
 // Service is an interface each service must comply with to be registered and orchestrated by the http.
 type Service interface {
 	Type() Type
diff --git a/pkg/service/keystore/keystore.go b/pkg/service/keystore/keystore.go
index ae54db4..d635de2 100644
--- a/pkg/service/keystore/keystore.go
+++ b/pkg/service/keystore/keystore.go
@@ -5,6 +5,7 @@ import (
 	"time"
 
 	"github.com/TBD54566975/ssi-sdk/crypto"
+	sdkutil "github.com/TBD54566975/ssi-sdk/util"
 	"github.com/mr-tron/base58"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -27,10 +28,14 @@ func (s Service) Type() framework.Type {
 }
 
 func (s Service) Status() framework.Status {
+	ae := sdkutil.NewAppendError()
 	if s.storage == nil {
+		ae.AppendString("no storage configured")
+	}
+	if !ae.IsEmpty() {
 		return framework.Status{
 			Status:  framework.StatusNotReady,
-			Message: "no storage",
+			Message: fmt.Sprintf("key store service is not ready: %s", ae.Error().Error()),
 		}
 	}
 	return framework.Status{Status: framework.StatusReady}
@@ -54,10 +59,14 @@ func NewKeyStoreService(config config.KeyStoreServiceConfig, s storage.ServiceSt
 		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 
-	return &Service{
+	service := Service{
 		storage: keyStoreStorage,
 		config:  config,
-	}, nil
+	}
+	if !service.Status().IsReady() {
+		return nil, errors.New(service.Status().Message)
+	}
+	return &service, nil
 }
 
 func (s Service) StoreKey(request StoreKeyRequest) error {
diff --git a/pkg/service/manifest/manifest.go b/pkg/service/manifest/manifest.go
index 17e21bc..973e5e5 100644
--- a/pkg/service/manifest/manifest.go
+++ b/pkg/service/manifest/manifest.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	"github.com/TBD54566975/ssi-sdk/credential/manifest"
+	sdkutil "github.com/TBD54566975/ssi-sdk/util"
 	"github.com/sirupsen/logrus"
 
 	"github.com/tbd54566975/ssi-service/config"
@@ -18,8 +19,8 @@ import (
 )
 
 type Service struct {
-	manifestStorage manifeststorage.Storage
-	config          config.ManifestServiceConfig
+	storage manifeststorage.Storage
+	config  config.ManifestServiceConfig
 
 	// external dependencies
 	credential *credential.Service
@@ -31,13 +32,22 @@ func (s Service) Type() framework.Type {
 }
 
 func (s Service) Status() framework.Status {
-	if s.manifestStorage == nil {
+	ae := sdkutil.NewAppendError()
+	if s.storage == nil {
+		ae.AppendString("no storage configured")
+	}
+	if s.credential == nil {
+		ae.AppendString("no credential service configured")
+	}
+	if s.keyStore == nil {
+		ae.AppendString("no keystore service configured")
+	}
+	if !ae.IsEmpty() {
 		return framework.Status{
 			Status:  framework.StatusNotReady,
-			Message: "no manifest storage",
+			Message: fmt.Sprintf("manifest service is not ready: %s", ae.Error().Error()),
 		}
 	}
-
 	return framework.Status{Status: framework.StatusReady}
 }
 
@@ -48,14 +58,14 @@ func (s Service) Config() config.ManifestServiceConfig {
 func NewManifestService(config config.ManifestServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, credential *credential.Service) (*Service, error) {
 	manifestStorage, err := manifeststorage.NewManifestStorage(s)
 	if err != nil {
-		errMsg := "could not instantiate manifestStorage for the manifest service"
+		errMsg := "could not instantiate storage for the manifest service"
 		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 	return &Service{
-		manifestStorage: manifestStorage,
-		config:          config,
-		keyStore:        keyStore,
-		credential:      credential,
+		storage:    manifestStorage,
+		config:     config,
+		keyStore:   keyStore,
+		credential: credential,
 	}, nil
 }
 
@@ -74,7 +84,7 @@ func (s Service) CreateManifest(request CreateManifestRequest) (*CreateManifestR
 		Issuer:   m.Issuer.ID,
 	}
 
-	if err := s.manifestStorage.StoreManifest(storageRequest); err != nil {
+	if err := s.storage.StoreManifest(storageRequest); err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not store manifest")
 	}
 
@@ -87,7 +97,7 @@ func (s Service) GetManifest(request GetManifestRequest) (*GetManifestResponse,
 
 	logrus.Debugf("getting manifest: %s", request.ID)
 
-	gotManifest, err := s.manifestStorage.GetManifest(request.ID)
+	gotManifest, err := s.storage.GetManifest(request.ID)
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get manifest: %s", request.ID)
 		return nil, util.LoggingErrorMsg(err, errMsg)
@@ -98,7 +108,7 @@ func (s Service) GetManifest(request GetManifestRequest) (*GetManifestResponse,
 }
 
 func (s Service) GetManifests() (*GetManifestsResponse, error) {
-	gotManifests, err := s.manifestStorage.GetManifests()
+	gotManifests, err := s.storage.GetManifests()
 
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get manifests(s)")
@@ -116,7 +126,7 @@ func (s Service) DeleteManifest(request DeleteManifestRequest) error {
 
 	logrus.Debugf("deleting manifest: %s", request.ID)
 
-	if err := s.manifestStorage.DeleteManifest(request.ID); err != nil {
+	if err := s.storage.DeleteManifest(request.ID); err != nil {
 		errMsg := fmt.Sprintf("could not delete manifest with id: %s", request.ID)
 		return util.LoggingErrorMsg(err, errMsg)
 	}
@@ -131,7 +141,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 		return nil, util.LoggingErrorMsg(err, "application is not valid")
 	}
 
-	gotManifest, err := s.manifestStorage.GetManifest(credApp.ManifestID)
+	gotManifest, err := s.storage.GetManifest(credApp.ManifestID)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "problem with retrieving manifest during application validation")
 	}
@@ -148,7 +158,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 		ManifestID:  request.Application.ManifestID,
 	}
 
-	if err := s.manifestStorage.StoreApplication(storageRequest); err != nil {
+	if err := s.storage.StoreApplication(storageRequest); err != nil {
 		errMsg := "could not store application"
 		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
@@ -210,7 +220,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 		Response:   *credRes,
 		ManifestID: request.Application.ManifestID,
 	}
-	if err := s.manifestStorage.StoreResponse(storeResponseRequest); err != nil {
+	if err := s.storage.StoreResponse(storeResponseRequest); err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not store manifest response")
 	}
 
@@ -243,7 +253,7 @@ func (s Service) GetApplication(request GetApplicationRequest) (*GetApplicationR
 
 	logrus.Debugf("getting application: %s", request.ID)
 
-	gotApp, err := s.manifestStorage.GetApplication(request.ID)
+	gotApp, err := s.storage.GetApplication(request.ID)
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get application: %s", request.ID)
 		return nil, util.LoggingErrorMsg(err, errMsg)
@@ -257,7 +267,7 @@ func (s Service) GetApplications() (*GetApplicationsResponse, error) {
 
 	logrus.Debugf("getting application(s)")
 
-	gotApps, err := s.manifestStorage.GetApplications()
+	gotApps, err := s.storage.GetApplications()
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get application(s)")
 	}
@@ -275,7 +285,7 @@ func (s Service) DeleteApplication(request DeleteApplicationRequest) error {
 
 	logrus.Debugf("deleting application: %s", request.ID)
 
-	if err := s.manifestStorage.DeleteApplication(request.ID); err != nil {
+	if err := s.storage.DeleteApplication(request.ID); err != nil {
 		errMsg := fmt.Sprintf("could not delete application with id: %s", request.ID)
 		return util.LoggingErrorMsg(err, errMsg)
 	}
@@ -287,7 +297,7 @@ func (s Service) GetResponse(request GetResponseRequest) (*GetResponseResponse,
 
 	logrus.Debugf("getting response: %s", request.ID)
 
-	gotResponse, err := s.manifestStorage.GetResponse(request.ID)
+	gotResponse, err := s.storage.GetResponse(request.ID)
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get response: %s", request.ID)
 		return nil, util.LoggingErrorMsg(err, errMsg)
@@ -301,7 +311,7 @@ func (s Service) GetResponses() (*GetResponsesResponse, error) {
 
 	logrus.Debugf("getting response(s)")
 
-	gotResponses, err := s.manifestStorage.GetResponses()
+	gotResponses, err := s.storage.GetResponses()
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get response(s)")
 	}
@@ -319,7 +329,7 @@ func (s Service) DeleteResponse(request DeleteResponseRequest) error {
 
 	logrus.Debugf("deleting response: %s", request.ID)
 
-	if err := s.manifestStorage.DeleteResponse(request.ID); err != nil {
+	if err := s.storage.DeleteResponse(request.ID); err != nil {
 		errMsg := fmt.Sprintf("could not delete response with id: %s", request.ID)
 		return util.LoggingErrorMsg(err, errMsg)
 	}
diff --git a/pkg/service/schema/schema.go b/pkg/service/schema/schema.go
index d6946f9..0ea6cc6 100644
--- a/pkg/service/schema/schema.go
+++ b/pkg/service/schema/schema.go
@@ -37,10 +37,20 @@ func (s Service) Type() framework.Type {
 }
 
 func (s Service) Status() framework.Status {
+	ae := sdkutil.NewAppendError()
 	if s.storage == nil {
+		ae.AppendString("no storage configured")
+	}
+	if s.keyStore == nil {
+		ae.AppendString("no key store service configured")
+	}
+	if s.resolver == nil {
+		ae.AppendString("no did resolver configured")
+	}
+	if !ae.IsEmpty() {
 		return framework.Status{
 			Status:  framework.StatusNotReady,
-			Message: "storage not loaded",
+			Message: fmt.Sprintf("schema service is not ready: %s", ae.Error().Error()),
 		}
 	}
 	return framework.Status{Status: framework.StatusReady}
@@ -56,12 +66,16 @@ func NewSchemaService(config config.SchemaServiceConfig, s storage.ServiceStorag
 		errMsg := "could not instantiate storage for the schema service"
 		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
-	return &Service{
+	service := Service{
 		storage:  schemaStorage,
 		config:   config,
 		keyStore: keyStore,
 		resolver: resolver,
-	}, nil
+	}
+	if !service.Status().IsReady() {
+		return nil, errors.New(service.Status().Message)
+	}
+	return &service, nil
 }
 
 // CreateSchema houses the main service logic for schema creation. It validates the input, and
@@ -221,6 +235,7 @@ func (s Service) GetSchema(request GetSchemaRequest) (*GetSchemaResponse, error)
 
 	logrus.Debugf("getting schema: %s", request.ID)
 
+	// TODO(gabe) support external schema resolution https://github.com/TBD54566975/ssi-service/issues/125
 	gotSchema, err := s.storage.GetSchema(request.ID)
 	if err != nil {
 		err := errors.Wrapf(err, "error getting schema: %s", request.ID)
diff --git a/pkg/service/service.go b/pkg/service/service.go
index 3f2cdca..11890e2 100644
--- a/pkg/service/service.go
+++ b/pkg/service/service.go
@@ -90,7 +90,7 @@ func instantiateServices(config config.ServicesConfig) ([]framework.Service, err
 		return nil, util.LoggingErrorMsg(err, "could not instantiate the schema service")
 	}
 
-	credentialService, err := credential.NewCredentialService(config.CredentialConfig, storageProvider, keyStoreService, didResolver)
+	credentialService, err := credential.NewCredentialService(config.CredentialConfig, storageProvider, keyStoreService, didResolver, schemaService)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate the credential service")
 	}


Test patch:
diff --git a/pkg/server/router/credential_test.go b/pkg/server/router/credential_test.go
index 980cee0..7bc573a 100644
--- a/pkg/server/router/credential_test.go
+++ b/pkg/server/router/credential_test.go
@@ -15,6 +15,7 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
+	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
@@ -46,7 +47,8 @@ func TestCredentialRouter(t *testing.T) {
 		serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential"}}
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService, err := credential.NewCredentialService(serviceConfig, bolt, keyStoreService, didService.GetResolver())
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credService, err := credential.NewCredentialService(serviceConfig, bolt, keyStoreService, didService.GetResolver(), schemaService)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, credService)
 
@@ -118,8 +120,8 @@ func TestCredentialRouter(t *testing.T) {
 		assert.Equal(tt, cred.ID, byIssuer.Credentials[0].Credential.ID)
 		assert.Equal(tt, cred.Issuer, byIssuer.Credentials[0].Credential.Issuer)
 
-		// create another cred with the same issuer, different subject, different schema
-		anotherCreatedCred, err := credService.CreateCredential(credential.CreateCredentialRequest{
+		// create another cred with the same issuer, different subject, different schema that doesn't exist
+		_, err = credService.CreateCredential(credential.CreateCredentialRequest{
 			Issuer:     issuer,
 			Subject:    "did:abcd:efghi",
 			JSONSchema: "https://test-schema.com",
@@ -128,8 +130,36 @@ func TestCredentialRouter(t *testing.T) {
 			},
 			Expiry: time.Now().Add(24 * time.Hour).Format(time.RFC3339),
 		})
+		assert.Error(tt, err)
+		assert.Contains(tt, err.Error(), "schema not found with id: https://test-schema.com")
+
+		// create schema
+		emailSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"email": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"required":             []interface{}{"email"},
+			"additionalProperties": false,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
+		// create another cred with the same issuer, different subject, different schema that does exist
+		createdCredWithSchema, err := credService.CreateCredential(credential.CreateCredentialRequest{
+			Issuer:     issuer,
+			Subject:    "did:abcd:efghi",
+			JSONSchema: createdSchema.ID,
+			Data: map[string]interface{}{
+				"email": "satoshi@nakamoto.com",
+			},
+			Expiry: time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, anotherCreatedCred)
+		assert.NotEmpty(tt, createdCredWithSchema)
 
 		// get by issuer
 		byIssuer, err = credService.GetCredentialsByIssuer(credential.GetCredentialByIssuerRequest{Issuer: issuer})
diff --git a/pkg/server/router/dwn_test.go b/pkg/server/router/dwn_test.go
index 486d9d7..75644e4 100644
--- a/pkg/server/router/dwn_test.go
+++ b/pkg/server/router/dwn_test.go
@@ -40,7 +40,8 @@ func TestDWNRouter(t *testing.T) {
 		serviceConfig := config.DWNServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "dwn"}}
 		keyStore := testKeyStoreService(t, bolt)
 		didService := testDIDService(t, bolt, keyStore)
-		credentialService := testCredentialService(t, bolt, keyStore, didService)
+		schemaService := testSchemaService(t, bolt, keyStore, didService)
+		credentialService := testCredentialService(t, bolt, keyStore, didService, schemaService)
 		manifestService := testManifestService(t, bolt, keyStore, credentialService)
 		dwnService, err := dwn.NewDWNService(serviceConfig, bolt, keyStore, manifestService)
 		assert.NoError(tt, err)
diff --git a/pkg/server/router/manifest_test.go b/pkg/server/router/manifest_test.go
index 05a53d8..b4d77c9 100644
--- a/pkg/server/router/manifest_test.go
+++ b/pkg/server/router/manifest_test.go
@@ -15,6 +15,7 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest"
+	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
@@ -46,8 +47,9 @@ func TestManifestRouter(t *testing.T) {
 		serviceConfig := config.ManifestServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "manifest"}}
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		testCredentialService := testCredentialService(tt, bolt, keyStoreService, didService)
-		manifestService, err := manifest.NewManifestService(serviceConfig, bolt, keyStoreService, testCredentialService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
+		manifestService, err := manifest.NewManifestService(serviceConfig, bolt, keyStoreService, credentialService)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, manifestService)
 
@@ -68,8 +70,22 @@ func TestManifestRouter(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, applicantDID)
 
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
 		// good manifest request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		createdManifest, err := manifestService.CreateManifest(createManifestRequest)
 		assert.NoError(tt, err)
@@ -87,7 +103,7 @@ func TestManifestRouter(t *testing.T) {
 	})
 }
 
-func getValidManifestRequest(issuerDID string) manifest.CreateManifestRequest {
+func getValidManifestRequest(issuerDID, schemaID string) manifest.CreateManifestRequest {
 	createManifestRequest := manifest.CreateManifestRequest{
 		Manifest: manifestsdk.CredentialManifest{
 			ID:          "WA-DL-CLASS-A",
@@ -113,13 +129,13 @@ func getValidManifestRequest(issuerDID string) manifest.CreateManifestRequest {
 			OutputDescriptors: []manifestsdk.OutputDescriptor{
 				{
 					ID:          "id1",
-					Schema:      "https://test.com/schema",
+					Schema:      schemaID,
 					Name:        "good ID",
 					Description: "it's all good",
 				},
 				{
 					ID:          "id2",
-					Schema:      "https://test.com/schema",
+					Schema:      schemaID,
 					Name:        "good ID",
 					Description: "it's all good",
 				},
diff --git a/pkg/server/router/testutils_test.go b/pkg/server/router/testutils_test.go
index f947971..408c67d 100644
--- a/pkg/server/router/testutils_test.go
+++ b/pkg/server/router/testutils_test.go
@@ -10,6 +10,7 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest"
+	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
@@ -37,10 +38,19 @@ func testDIDService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service
 	return didService
 }
 
-func testCredentialService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service) *credential.Service {
+func testSchemaService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service) *schema.Service {
+	serviceConfig := config.SchemaServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "schema"}}
+	// create a schema service
+	schemaService, err := schema.NewSchemaService(serviceConfig, db, keyStore, did.GetResolver())
+	require.NoError(t, err)
+	require.NotEmpty(t, schemaService)
+	return schemaService
+}
+
+func testCredentialService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service, schema *schema.Service) *credential.Service {
 	serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential"}}
 	// create a credential service
-	credentialService, err := credential.NewCredentialService(serviceConfig, db, keyStore, did.GetResolver())
+	credentialService, err := credential.NewCredentialService(serviceConfig, db, keyStore, did.GetResolver(), schema)
 	require.NoError(t, err)
 	require.NotEmpty(t, credentialService)
 	return credentialService
diff --git a/pkg/server/server_credential_test.go b/pkg/server/server_credential_test.go
index ef829b5..9123126 100644
--- a/pkg/server/server_credential_test.go
+++ b/pkg/server/server_credential_test.go
@@ -18,6 +18,7 @@ import (
 
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
+	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
@@ -34,7 +35,8 @@ func TestCredentialAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService := testCredentialRouter(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
 
 		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
@@ -53,7 +55,7 @@ func TestCredentialAPI(t *testing.T) {
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", badRequestValue)
 		w := httptest.NewRecorder()
 
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "invalid create credential request")
 
@@ -72,7 +74,7 @@ func TestCredentialAPI(t *testing.T) {
 		}
 		missingIssuerRequestValue := newRequestValue(tt, missingIssuerRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", missingIssuerRequestValue)
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not get key for signing credential with key<did:abc:123>")
 
@@ -91,7 +93,7 @@ func TestCredentialAPI(t *testing.T) {
 		}
 		requestValue := newRequestValue(tt, createCredRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var resp router.CreateCredentialResponse
@@ -103,6 +105,104 @@ func TestCredentialAPI(t *testing.T) {
 		assert.Equal(tt, resp.Credential.Issuer, issuerDID.DID.ID)
 	})
 
+	t.Run("Test Create Credential with Schema", func(tt *testing.T) {
+		bolt, err := storage.NewBoltDB()
+		require.NoError(tt, err)
+
+		// remove the db file after the test
+		tt.Cleanup(func() {
+			_ = bolt.Close()
+			_ = os.Remove(storage.DBFile)
+		})
+
+		keyStoreService := testKeyStoreService(tt, bolt)
+		didService := testDIDService(tt, bolt, keyStoreService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
+
+		w := httptest.NewRecorder()
+
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+			Method:  didsdk.KeyMethod,
+			KeyType: crypto.Ed25519,
+		})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, issuerDID)
+
+		// create a schema
+		simpleSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"firstName": map[string]interface{}{
+					"type": "string",
+				},
+				"lastName": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"required":             []interface{}{"firstName", "lastName"},
+			"additionalProperties": false,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: simpleSchema})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
+		createCredRequest := router.CreateCredentialRequest{
+			Issuer:  issuerDID.DID.ID,
+			Subject: "did:abc:456",
+			Schema:  createdSchema.ID,
+			Data: map[string]interface{}{
+				"firstName": "Jack",
+				"lastName":  "Dorsey",
+			},
+			Expiry: time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+		}
+		requestValue := newRequestValue(tt, createCredRequest)
+		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
+		assert.NoError(tt, err)
+
+		var resp router.CreateCredentialResponse
+		err = json.NewDecoder(w.Body).Decode(&resp)
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, resp.CredentialJWT)
+
+		w.Flush()
+
+		// get credential by schema
+		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credential?schema=%s", createdSchema.ID), nil)
+		err = credRouter.GetCredentials(newRequestContext(), w, req)
+		assert.NoError(tt, err)
+
+		var getCredsResp router.GetCredentialsResponse
+		err = json.NewDecoder(w.Body).Decode(&getCredsResp)
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, getCredsResp)
+		assert.Len(tt, getCredsResp.Credentials, 1)
+
+		assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].ID)
+		assert.Equal(tt, resp.Credential.CredentialSchema.ID, getCredsResp.Credentials[0].Credential.CredentialSchema.ID)
+
+		w.Flush()
+
+		// create cred with unknown schema
+		missingSchemaCred := router.CreateCredentialRequest{
+			Issuer:  issuerDID.DID.ID,
+			Subject: "did:abc:456",
+			Schema:  "bad",
+			Data: map[string]interface{}{
+				"firstName": "Jack",
+				"lastName":  "Dorsey",
+			},
+			Expiry: time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+		}
+		requestValue = newRequestValue(tt, missingSchemaCred)
+		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
+		assert.Error(tt, err)
+		assert.Contains(tt, err.Error(), "schema not found")
+	})
+
 	t.Run("Test Get Credential By ID", func(tt *testing.T) {
 		bolt, err := storage.NewBoltDB()
 		require.NoError(tt, err)
@@ -115,13 +215,14 @@ func TestCredentialAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService := testCredentialRouter(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
 
 		w := httptest.NewRecorder()
 
 		// get a cred that doesn't exit
 		req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/credentials/bad", nil)
-		err = credService.GetCredential(newRequestContext(), w, req)
+		err = credRouter.GetCredential(newRequestContext(), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "cannot get credential without ID parameter")
 
@@ -130,7 +231,7 @@ func TestCredentialAPI(t *testing.T) {
 
 		// get a cred with an invalid id parameter
 		req = httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/credentials/bad", nil)
-		err = credService.GetCredential(newRequestContextWithParams(map[string]string{"id": "bad"}), w, req)
+		err = credRouter.GetCredential(newRequestContextWithParams(map[string]string{"id": "bad"}), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not get credential with id: bad")
 
@@ -155,7 +256,7 @@ func TestCredentialAPI(t *testing.T) {
 		}
 		requestValue := newRequestValue(tt, createCredRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		// We expect a JWT credential
@@ -167,7 +268,7 @@ func TestCredentialAPI(t *testing.T) {
 
 		// get credential by id
 		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credentials/%s", resp.Credential.ID), nil)
-		err = credService.GetCredential(newRequestContextWithParams(map[string]string{"id": resp.Credential.ID}), w, req)
+		err = credRouter.GetCredential(newRequestContextWithParams(map[string]string{"id": resp.Credential.ID}), w, req)
 		assert.NoError(tt, err)
 
 		var getCredResp router.GetCredentialResponse
@@ -190,7 +291,8 @@ func TestCredentialAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService := testCredentialRouter(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
 
 		w := httptest.NewRecorder()
 
@@ -201,11 +303,28 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, issuerDID)
 
-		schemaID := "https://test-schema.com/name"
+		// create a schema
+		simpleSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"firstName": map[string]interface{}{
+					"type": "string",
+				},
+				"lastName": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"required":             []interface{}{"firstName", "lastName"},
+			"additionalProperties": false,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: simpleSchema})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
 		createCredRequest := router.CreateCredentialRequest{
 			Issuer:  issuerDID.DID.ID,
 			Subject: "did:abc:456",
-			Schema:  schemaID,
+			Schema:  createdSchema.ID,
 			Data: map[string]interface{}{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -214,7 +333,7 @@ func TestCredentialAPI(t *testing.T) {
 		}
 		requestValue := newRequestValue(tt, createCredRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var resp router.CreateCredentialResponse
@@ -225,8 +344,8 @@ func TestCredentialAPI(t *testing.T) {
 		w.Flush()
 
 		// get credential by schema
-		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credential?schema=%s", schemaID), nil)
-		err = credService.GetCredentials(newRequestContext(), w, req)
+		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credential?schema=%s", createdSchema.ID), nil)
+		err = credRouter.GetCredentials(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var getCredsResp router.GetCredentialsResponse
@@ -251,7 +370,8 @@ func TestCredentialAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService := testCredentialRouter(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
 
 		w := httptest.NewRecorder()
 
@@ -262,11 +382,9 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, issuerDID)
 
-		schemaID := "https://test-schema.com/name"
 		createCredRequest := router.CreateCredentialRequest{
 			Issuer:  issuerDID.DID.ID,
 			Subject: "did:abc:456",
-			Schema:  schemaID,
 			Data: map[string]interface{}{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -275,7 +393,7 @@ func TestCredentialAPI(t *testing.T) {
 		}
 		requestValue := newRequestValue(tt, createCredRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var resp router.CreateCredentialResponse
@@ -287,7 +405,7 @@ func TestCredentialAPI(t *testing.T) {
 
 		// get credential by issuer id
 		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credential?issuer=%s", issuerDID.DID.ID), nil)
-		err = credService.GetCredentials(newRequestContext(), w, req)
+		err = credRouter.GetCredentials(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var getCredsResp router.GetCredentialsResponse
@@ -297,7 +415,6 @@ func TestCredentialAPI(t *testing.T) {
 
 		assert.Len(tt, getCredsResp.Credentials, 1)
 		assert.Equal(tt, resp.Credential.ID, getCredsResp.Credentials[0].ID)
-		assert.Equal(tt, resp.Credential.CredentialSchema.ID, getCredsResp.Credentials[0].Credential.CredentialSchema.ID)
 	})
 
 	t.Run("Test Get Credential By Subject", func(tt *testing.T) {
@@ -312,7 +429,8 @@ func TestCredentialAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService := testCredentialRouter(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
 
 		w := httptest.NewRecorder()
 
@@ -323,12 +441,10 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, issuerDID)
 
-		schemaID := "https://test-schema.com/name"
 		subjectID := "did:abc:456"
 		createCredRequest := router.CreateCredentialRequest{
 			Issuer:  issuerDID.DID.ID,
 			Subject: subjectID,
-			Schema:  schemaID,
 			Data: map[string]interface{}{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -337,7 +453,7 @@ func TestCredentialAPI(t *testing.T) {
 		}
 		requestValue := newRequestValue(tt, createCredRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var resp router.CreateCredentialResponse
@@ -349,7 +465,7 @@ func TestCredentialAPI(t *testing.T) {
 
 		// get credential by subject id
 		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credential?subject=%s", subjectID), nil)
-		err = credService.GetCredentials(newRequestContext(), w, req)
+		err = credRouter.GetCredentials(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var getCredsResp router.GetCredentialsResponse
@@ -374,7 +490,8 @@ func TestCredentialAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService := testCredentialRouter(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
 
 		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
@@ -395,7 +512,7 @@ func TestCredentialAPI(t *testing.T) {
 		requestValue := newRequestValue(tt, createCredRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
 		w := httptest.NewRecorder()
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var resp router.CreateCredentialResponse
@@ -407,7 +524,7 @@ func TestCredentialAPI(t *testing.T) {
 		// get credential by id
 		credID := resp.Credential.ID
 		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credentials/%s", credID), nil)
-		err = credService.GetCredential(newRequestContextWithParams(map[string]string{"id": credID}), w, req)
+		err = credRouter.GetCredential(newRequestContextWithParams(map[string]string{"id": credID}), w, req)
 		assert.NoError(tt, err)
 
 		var getCredResp router.GetCredentialResponse
@@ -420,14 +537,14 @@ func TestCredentialAPI(t *testing.T) {
 
 		// delete it
 		req = httptest.NewRequest(http.MethodDelete, fmt.Sprintf("https://ssi-service.com/v1/credentials/%s", credID), nil)
-		err = credService.DeleteCredential(newRequestContextWithParams(map[string]string{"id": credID}), w, req)
+		err = credRouter.DeleteCredential(newRequestContextWithParams(map[string]string{"id": credID}), w, req)
 		assert.NoError(tt, err)
 
 		w.Flush()
 
 		// get it back
 		req = httptest.NewRequest(http.MethodGet, fmt.Sprintf("https://ssi-service.com/v1/credentials/%s", credID), nil)
-		err = credService.GetCredential(newRequestContextWithParams(map[string]string{"id": credID}), w, req)
+		err = credRouter.GetCredential(newRequestContextWithParams(map[string]string{"id": credID}), w, req)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), fmt.Sprintf("could not get credential with id: %s", credID))
 	})
@@ -444,7 +561,8 @@ func TestCredentialAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credService := testCredentialRouter(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credRouter := testCredentialRouter(tt, bolt, keyStoreService, didService, schemaService)
 
 		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
@@ -466,7 +584,7 @@ func TestCredentialAPI(t *testing.T) {
 		requestValue := newRequestValue(tt, createCredRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", requestValue)
 		w := httptest.NewRecorder()
-		err = credService.CreateCredential(newRequestContext(), w, req)
+		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var resp router.CreateCredentialResponse
@@ -482,7 +600,7 @@ func TestCredentialAPI(t *testing.T) {
 		// verify the credential
 		requestValue = newRequestValue(tt, router.VerifyCredentialRequest{CredentialJWT: resp.CredentialJWT})
 		req = httptest.NewRequest(http.MethodPost, "https://ssi-service.com/v1/credentials/verification", requestValue)
-		err = credService.VerifyCredential(newRequestContext(), w, req)
+		err = credRouter.VerifyCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		var verifyResp router.VerifyCredentialResponse
@@ -494,7 +612,7 @@ func TestCredentialAPI(t *testing.T) {
 		// bad credential
 		requestValue = newRequestValue(tt, router.VerifyCredentialRequest{CredentialJWT: util.StringPtr("badjwt")})
 		req = httptest.NewRequest(http.MethodPost, "https://ssi-service.com/v1/credentials/verification", requestValue)
-		err = credService.VerifyCredential(newRequestContext(), w, req)
+		err = credRouter.VerifyCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
 
 		err = json.NewDecoder(w.Body).Decode(&verifyResp)
diff --git a/pkg/server/server_dwn_test.go b/pkg/server/server_dwn_test.go
index a307650..e625eda 100644
--- a/pkg/server/server_dwn_test.go
+++ b/pkg/server/server_dwn_test.go
@@ -14,6 +14,7 @@ import (
 
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
+	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
@@ -30,22 +31,37 @@ func TestDWNAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, manifestService := testManifest(tt, bolt, keyStoreService, credentialService)
 		dwnService := testDWNRouter(tt, bolt, keyStoreService, manifestService)
 
 		w := httptest.NewRecorder()
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
+		assert.NotEmpty(tt, issuerDID)
+
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDIDDoc.DID.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
diff --git a/pkg/server/server_manifest_test.go b/pkg/server/server_manifest_test.go
index 9f21242..81076dc 100644
--- a/pkg/server/server_manifest_test.go
+++ b/pkg/server/server_manifest_test.go
@@ -15,6 +15,7 @@ import (
 
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
+	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
@@ -31,7 +32,8 @@ func TestManifestAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
 
 		// missing required field: Manifest
@@ -49,17 +51,29 @@ func TestManifestAPI(t *testing.T) {
 		w.Flush()
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
-
-		issuerDID := issuerDIDDoc.DID.ID
+		assert.NotEmpty(tt, issuerDID)
+
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -71,7 +85,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 
 		assert.NotEmpty(tt, resp.Manifest)
-		assert.Equal(tt, resp.Manifest.Issuer.ID, issuerDID)
+		assert.Equal(tt, resp.Manifest.Issuer.ID, issuerDID.DID.ID)
 	})
 
 	t.Run("Test Get Manifest By ID", func(tt *testing.T) {
@@ -86,7 +100,8 @@ func TestManifestAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
 
 		w := httptest.NewRecorder()
@@ -110,15 +125,29 @@ func TestManifestAPI(t *testing.T) {
 		w.Flush()
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
+		assert.NotEmpty(tt, issuerDID)
+
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDIDDoc.DID.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -153,21 +182,36 @@ func TestManifestAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
 
 		w := httptest.NewRecorder()
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
+		assert.NotEmpty(tt, issuerDID)
+
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDIDDoc.DID.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -203,20 +247,34 @@ func TestManifestAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
+		assert.NotEmpty(tt, issuerDID)
+
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-
-		createManifestRequest := getValidManifestRequest(issuerDIDDoc.DID.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -269,8 +327,8 @@ func TestManifestAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
-
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
 
 		// missing required field: Application
@@ -290,18 +348,31 @@ func TestManifestAPI(t *testing.T) {
 		w.Flush()
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
+		assert.NotEmpty(tt, issuerDID)
 
-		issuerDID := issuerDIDDoc.DID.ID
 		applicantDID := "did:example:abcd"
 
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -313,7 +384,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 
 		assert.NotEmpty(tt, resp.Manifest)
-		assert.Equal(tt, resp.Manifest.Issuer.ID, issuerDID)
+		assert.Equal(tt, resp.Manifest.Issuer.ID, issuerDID.DID.ID)
 
 		// good application request
 		createApplicationRequest := getValidApplicationRequest(applicantDID, resp.Manifest.ID, resp.Manifest.PresentationDefinition.InputDescriptors[0].ID)
@@ -343,7 +414,8 @@ func TestManifestAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
 		w := httptest.NewRecorder()
 
@@ -357,18 +429,31 @@ func TestManifestAPI(t *testing.T) {
 		w.Flush()
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
+		assert.NotEmpty(tt, issuerDID)
 
-		issuerDID := issuerDIDDoc.DID.ID
 		applicantDID := "did:example:abcd"
 
-		// good manifest request
-		createManifestRequest := getValidManifestRequest(issuerDID)
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
+		// good request
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -447,22 +532,36 @@ func TestManifestAPI(t *testing.T) {
 
 		keyStoreService := testKeyStoreService(tt, bolt)
 		didService := testDIDService(tt, bolt, keyStoreService)
-		credentialService := testCredentialService(tt, bolt, keyStoreService, didService)
+		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
+		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
 
 		// create an issuer
-		issuerDIDDoc, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
+		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
 			Method:  didsdk.KeyMethod,
 			KeyType: crypto.Ed25519,
 		})
 		assert.NoError(tt, err)
-		assert.NotEmpty(tt, issuerDIDDoc)
+		assert.NotEmpty(tt, issuerDID)
 
-		issuerDID := issuerDIDDoc.DID.ID
 		applicantDID := "did:example:abcd"
 
-		// good manifest request
-		createManifestRequest := getValidManifestRequest(issuerDID)
+		// create a schema for the creds to be issued against
+		licenseSchema := map[string]interface{}{
+			"type": "object",
+			"properties": map[string]interface{}{
+				"licenseType": map[string]interface{}{
+					"type": "string",
+				},
+			},
+			"additionalProperties": true,
+		}
+		createdSchema, err := schemaService.CreateSchema(schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, createdSchema)
+
+		// good request
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go
index 5d49ce3..5cc4f88 100644
--- a/pkg/server/server_test.go
+++ b/pkg/server/server_test.go
@@ -117,13 +117,13 @@ func newRequestContextWithParams(params map[string]string) context.Context {
 	return httptreemux.AddParamsToContext(ctx, params)
 }
 
-func getValidManifestRequest(issuer string) manifest.CreateManifestRequest {
+func getValidManifestRequest(issuerDID, schemaID string) manifest.CreateManifestRequest {
 	createManifestRequest := manifest.CreateManifestRequest{
 		Manifest: manifestsdk.CredentialManifest{
 			ID:          "WA-DL-CLASS-A",
 			SpecVersion: "https://identity.foundation/credential-manifest/spec/v1.0.0/",
 			Issuer: manifestsdk.Issuer{
-				ID: issuer,
+				ID: issuerDID,
 			},
 			PresentationDefinition: &exchange.PresentationDefinition{
 				ID: "pres-def-id",
@@ -143,13 +143,13 @@ func getValidManifestRequest(issuer string) manifest.CreateManifestRequest {
 			OutputDescriptors: []manifestsdk.OutputDescriptor{
 				{
 					ID:          "id1",
-					Schema:      "https://test.com/schema",
+					Schema:      schemaID,
 					Name:        "good ID",
 					Description: "it's all good",
 				},
 				{
 					ID:          "id2",
-					Schema:      "https://test.com/schema",
+					Schema:      schemaID,
 					Name:        "good ID",
 					Description: "it's all good",
 				},
@@ -254,18 +254,18 @@ func testSchemaRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore.Ser
 	return schemaRouter
 }
 
-func testCredentialService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service) *credential.Service {
+func testCredentialService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service, schema *schema.Service) *credential.Service {
 	serviceConfig := config.CredentialServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "credential"}}
 
 	// create a credential service
-	credentialService, err := credential.NewCredentialService(serviceConfig, db, keyStore, did.GetResolver())
+	credentialService, err := credential.NewCredentialService(serviceConfig, db, keyStore, did.GetResolver(), schema)
 	require.NoError(t, err)
 	require.NotEmpty(t, credentialService)
 	return credentialService
 }
 
-func testCredentialRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore.Service, did *did.Service) *router.CredentialRouter {
-	credentialService := testCredentialService(t, bolt, keyStore, did)
+func testCredentialRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore.Service, did *did.Service, schema *schema.Service) *router.CredentialRouter {
+	credentialService := testCredentialService(t, bolt, keyStore, did, schema)
 
 	// create router for service
 	credentialRouter, err := router.NewCredentialRouter(credentialService)