diff --git a/README.md b/README.md
index 4c9c80617f0a6e96dcf0b334bee7888db099527d..ed8047d9d9088c9db17c68b8c7c7bdd690f8684f 100644
--- a/README.md
+++ b/README.md
@@ -11,3 +11,6 @@ TODO - how key is selected if the request doesn't mention explicit key
 
 TODO - how signature suite is constructed based on key type
 
+### Counterfeiter 
+
+TODO - how to use it for generating fake implementations of interfaces
\ No newline at end of file
diff --git a/cmd/signer/main.go b/cmd/signer/main.go
index 9f2727ee17be5a3bd0e6826870e8d99f90e9d913..a11b6d61916e33776261c703e8bc5b41e1002e6a 100644
--- a/cmd/signer/main.go
+++ b/cmd/signer/main.go
@@ -105,6 +105,8 @@ func main() {
 		openapiServer = goaopenapisrv.New(openapiEndpoints, mux, dec, enc, nil, errFormatter, nil, nil)
 	}
 
+	// set custom request decoder, so that request body bytes are simply
+	// read and not decoded in some other way
 	signerServer.CredentialProof = goasignersrv.NewCredentialProofHandler(
 		signerEndpoints.CredentialProof,
 		mux,
@@ -114,6 +116,17 @@ func main() {
 		errFormatter,
 	)
 
+	// set custom request decoder, so that request body bytes are simply
+	// read and not decoded in some other way
+	signerServer.PresentationProof = goasignersrv.NewPresentationProofHandler(
+		signerEndpoints.PresentationProof,
+		mux,
+		decoder.RequestDecoder,
+		enc,
+		nil,
+		errFormatter,
+	)
+
 	// Configure the mux.
 	goasignersrv.Mount(mux, signerServer)
 	goahealthsrv.Mount(mux, healthServer)
diff --git a/internal/service/signer/service.go b/internal/service/signer/service.go
index f216f1a8f39627221e3c8598ef02bfb7a9b8eb46..06755754577a21cf4db4c77c181f216d651783c6 100644
--- a/internal/service/signer/service.go
+++ b/internal/service/signer/service.go
@@ -50,9 +50,11 @@ func New(signer Signer, defaultKey string, httpClient *http.Client, logger *zap.
 
 // CredentialProof adds a proof to a given Verifiable Credential.
 func (s *Service) CredentialProof(ctx context.Context, req *signer.CredentialProofRequest) (interface{}, error) {
+	logger := s.logger.With(zap.String("operation", "credentialProof"))
+
 	vc, err := verifiable.ParseCredential(req.Credential, verifiable.WithJSONLDDocumentLoader(s.docLoader))
 	if err != nil {
-		s.logger.Error("error parsing credential", zap.Error(err))
+		logger.Error("error parsing verifiable credential", zap.Error(err))
 		return nil, err
 	}
 
@@ -63,24 +65,60 @@ func (s *Service) CredentialProof(ctx context.Context, req *signer.CredentialPro
 
 	key, err := s.signer.Key(keyname)
 	if err != nil {
-		s.logger.Error("error getting signing key", zap.String("key", keyname), zap.Error(err))
+		logger.Error("error getting signing key", zap.String("key", keyname), zap.Error(err))
 		return nil, errors.New("error getting signing key", err)
 	}
 
 	proofContext, err := s.proofContext(key.Name, key.Type)
 	if err != nil {
-		s.logger.Error("error building proof context", zap.Error(err))
+		logger.Error("error building proof context", zap.Error(err))
 		return nil, err
 	}
 
 	if err := vc.AddLinkedDataProof(proofContext, jsonld.WithDocumentLoader(s.docLoader)); err != nil {
-		s.logger.Error("error adding linked data proof", zap.Error(err))
+		logger.Error("error adding linked data proof", zap.Error(err))
 		return nil, err
 	}
 
 	return vc, nil
 }
 
+// PresentationProof adds a proof to a given Verifiable Presentation.
+func (s *Service) PresentationProof(ctx context.Context, req *signer.PresentationProofRequest) (interface{}, error) {
+	logger := s.logger.With(zap.String("operation", "presentationProof"))
+
+	vp, err := verifiable.ParsePresentation(req.Presentation, verifiable.WithPresJSONLDDocumentLoader(s.docLoader))
+	if err != nil {
+		logger.Error("error parsing verifiable presentation", zap.Error(err))
+		return nil, err
+	}
+
+	keyname := s.defaultKey
+	if req.Key != nil && *req.Key != "" {
+		keyname = *req.Key
+	}
+
+	key, err := s.signer.Key(keyname)
+	if err != nil {
+		logger.Error("error getting signing key", zap.String("key", keyname), zap.Error(err))
+		return nil, errors.New("error getting signing key", err)
+	}
+
+	proofContext, err := s.proofContext(key.Name, key.Type)
+	if err != nil {
+		logger.Error("error building proof context", zap.Error(err))
+		return nil, err
+	}
+
+	if err := vp.AddLinkedDataProof(proofContext, jsonld.WithDocumentLoader(s.docLoader)); err != nil {
+		logger.Error("error adding linked data proof", zap.Error(err))
+		return nil, err
+	}
+
+	return vp, nil
+}
+
+// proofContext is used to create proofs.
 func (s *Service) proofContext(key string, keyType string) (*verifiable.LinkedDataProofContext, error) {
 	sigSuite, sigType, err := s.signatureSuite(key, keyType)
 	if err != nil {
@@ -97,6 +135,7 @@ func (s *Service) proofContext(key string, keyType string) (*verifiable.LinkedDa
 	return proofContext, nil
 }
 
+// signatureSuite is used to create digital signatures on proofs.
 func (s *Service) signatureSuite(key string, keyType string) (sigSuite ariesigner.SignatureSuite, sigType string, err error) {
 	signer := s.signer.WithKey(key)