diff --git a/apps/gateway/src/app/managers/attestation.controller.ts b/apps/gateway/src/app/managers/attestation.controller.ts
index 88140a189570219c7d9f3fa5af5614d19f701ee5..536fc82cb7564ea2e17f888c4dcf3bd3ddc9d6b8 100644
--- a/apps/gateway/src/app/managers/attestation.controller.ts
+++ b/apps/gateway/src/app/managers/attestation.controller.ts
@@ -1,12 +1,4 @@
-import {
-  BadRequestException,
-  Body,
-  Controller,
-  Get,
-  Param,
-  Post,
-  UseFilters,
-} from "@nestjs/common";
+import { Body, Controller, Get, Param, Post, UseFilters } from "@nestjs/common";
 import { AllExceptionsHandler } from "../exception.handler";
 import { AttestationManagerClient } from "@ocm-engine/clients";
 import {
diff --git a/apps/gateway/src/app/managers/proof.controller.ts b/apps/gateway/src/app/managers/proof.controller.ts
index 8b5b1347f4ee5330ffb72ecded4789dc31b5a2a2..86e8a2999b23b7709918fdcd98719d1b894b87f6 100644
--- a/apps/gateway/src/app/managers/proof.controller.ts
+++ b/apps/gateway/src/app/managers/proof.controller.ts
@@ -1,18 +1,14 @@
-import {
-  BadRequestException,
-  Body,
-  Controller,
-  Get,
-  Param,
-  Post,
-  UseFilters,
-} from "@nestjs/common";
+import { Body, Controller, Get, Param, Post, UseFilters } from "@nestjs/common";
 import {
   AcceptProofRequestDto,
+  DeclineProofRequestDto,
   GatewayAcceptedResponseDto,
+  GetProofRequestDto,
   GetSchemaRequestDto,
   IssueProofRequestDto,
   PROOF_ACCEPT,
+  PROOF_DECLINE,
+  PROOF_GET,
   PROOF_ISSUE,
   PROOF_LIST,
 } from "@ocm-engine/dtos";
@@ -76,6 +72,55 @@ export class ProofController {
     });
   }
 
+  @Get("/credentials/proof/:proof_record_id")
+  @ApiResponse({
+    status: 200,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiInternalServerErrorResponse({
+    description:
+      "Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.",
+    content: {
+      "application/json": {
+        schema: {
+          type: "object",
+          properties: {
+            statusCode: {
+              type: "number",
+              example: 500,
+            },
+
+            message: {
+              type: "string",
+              example: "connect ECONNREFUSED 0.0.0.0.0:1919",
+            },
+          },
+        },
+      },
+    },
+  })
+  @ApiOperation({
+    summary: "Get a single proof record by providing proof record id.",
+    description:
+      "Method get proof by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket",
+    tags: ["Credentials Proof"],
+  })
+  getProofById(@Param("proof_record_id") proofRecordId: string) {
+    const data = new GetProofRequestDto();
+    data.proofRecordId = proofRecordId;
+
+    return this.pmClient.sendPayload<GetProofRequestDto>({
+      pattern: "proofs",
+      payload: {
+        source: "/credentials/proof/:proof_record_id",
+        data,
+        type: PROOF_GET,
+      },
+    });
+  }
+
   @Post("/credentials/proof/issue")
   @ApiResponse({
     status: 201,
@@ -150,7 +195,7 @@ export class ProofController {
     });
   }
 
-  @Post(`/credentials/proof/:proof_record_id/accept`)
+  @Post(`/credentials/proof/accept`)
   @ApiResponse({
     status: 201,
     description:
@@ -185,16 +230,62 @@ export class ProofController {
       "Method accept credential proof. The id of the response will be matched when you receive event from the websocket",
     tags: ["Credentials Proof"],
   })
-  acceptProof(@Param("proof_record_id") proofRecordId: string) {
-    const data = new AcceptProofRequestDto();
+  acceptProof(@Body() acceptProofRequestDto: AcceptProofRequestDto) {
+    return this.pmClient.sendPayload<AcceptProofRequestDto>({
+      pattern: "proofs",
+      payload: {
+        source: "/credentials/proofs/accept",
+        data: acceptProofRequestDto,
+        type: PROOF_ACCEPT,
+      },
+    });
+  }
+
+  @Post("/credentials/proof/:proof_record_id/decline")
+  @ApiResponse({
+    status: 200,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiInternalServerErrorResponse({
+    description:
+      "Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.",
+    content: {
+      "application/json": {
+        schema: {
+          type: "object",
+          properties: {
+            statusCode: {
+              type: "number",
+              example: 500,
+            },
+
+            message: {
+              type: "string",
+              example: "connect ECONNREFUSED 0.0.0.0.0:1919",
+            },
+          },
+        },
+      },
+    },
+  })
+  @ApiOperation({
+    summary: "Decline a proof request.",
+    description:
+      "Method to decline a proof request by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket",
+    tags: ["Credentials Proof"],
+  })
+  declineProofRequest(@Param("proof_record_id") proofRecordId: string) {
+    const data = new DeclineProofRequestDto();
     data.proofRecordId = proofRecordId;
 
-    return this.pmClient.sendPayload<AcceptProofRequestDto>({
+    return this.pmClient.sendPayload<DeclineProofRequestDto>({
       pattern: "proofs",
       payload: {
-        source: "/credentials/proofs/:id/accept",
+        source: "/credentials/proof/:proof_record_id/decline",
         data,
-        type: PROOF_ACCEPT,
+        type: PROOF_DECLINE,
       },
     });
   }
diff --git a/apps/proof-manager/src/app/app.controller.ts b/apps/proof-manager/src/app/app.controller.ts
index b7e41ea0dda88da0b3225d4bdacb1ba6b9af0f2c..8f80bb48ed6abd241e156069437b38519f8e79a9 100644
--- a/apps/proof-manager/src/app/app.controller.ts
+++ b/apps/proof-manager/src/app/app.controller.ts
@@ -3,6 +3,7 @@ import { Body, Controller, Logger } from "@nestjs/common";
 import { ProducerService } from "@ocm-engine/nats";
 import { MessagePattern, RpcException } from "@nestjs/microservices";
 import {
+  AcceptProofRequestDto,
   CloudEventDto,
   GatewayAcceptedResponseDto,
   makeEvent,
@@ -19,7 +20,7 @@ export class AppController {
   async create(
     @Body()
     payload: {
-      data: null;
+      data: null | AcceptProofRequestDto;
       type: ProofEvent;
       source: string;
     },
diff --git a/gateway-swagger.json b/gateway-swagger.json
index 0da4211542ced768ce3d3628b3b896e7011415af..9455a2b3d686feb26229f0a60333303da6c4a592 100644
--- a/gateway-swagger.json
+++ b/gateway-swagger.json
@@ -1 +1 @@
-{"openapi":"3.0.0","paths":{"/api/v1/invitations":{"post":{"operationId":"ConnectionController_createInvitation","summary":"Create invitation for connection","description":"Method will create invitation url. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/invitations/accept":{"post":{"operationId":"ConnectionController_acceptInvitation","summary":"Accept invitation for connection","description":"Method will accept the invitation and will return connection thought the websocket. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitationResponseDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["invitationUrl must be a string","invitationUrl should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections":{"get":{"operationId":"ConnectionController_list","summary":"List all connections","description":"The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections/{id}":{"get":{"operationId":"ConnectionController_getById","summary":"Get connection by id","description":"The method will search for connection id, if not found null will be returned. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/schemas":{"post":{"operationId":"AttestationController_createSchema","summary":"Create schema","description":"Method will create schema. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["name must be a string","name should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}},"get":{"operationId":"AttestationController_listSchema","summary":"List all schemas","description":"Method will fetch all schemas. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/schemas-by-id":{"post":{"operationId":"AttestationController_getSchemaById","summary":"Get schema by id","description":"Method will fetch specific schema or return null. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/definition":{"post":{"operationId":"AttestationController_createCredentialDefinition","summary":"Create credential definition","description":"Method create credential definition. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCredentialDefinitionRequsetDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty","tag must be a string","tag should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/issue":{"post":{"operationId":"AttestationController_issueCredential","summary":"Issue credential","description":"Method issue credential, it will create an offer and send it to specified receiver (connectionId). The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueCredentialRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","credentialDefinitionId must be a string","credentialDefinitionId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials":{"get":{"operationId":"AttestationController_credentials","summary":"List all credential","description":"Method list credential definition no filters applied. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers":{"get":{"operationId":"AttestationController_getCredentialOffers","summary":"List unaccepted credential offers","description":"Method list offers that are received, but not accepted. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers/{credential_record_id}/accept":{"post":{"operationId":"AttestationController_acceptCredential","summary":"Accept credential offers","description":"Method list accept credential offer. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[{"name":"credential_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/messages":{"post":{"operationId":"AttestationController_sendMeesage","summary":"Send basic message","description":"Method will send basic message to a connection. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MakeBasicMessageRequestDto"}}}},"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","message must be a string","message should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/proof":{"get":{"operationId":"ProofController_proofs","summary":"List received unaccepted proofs","description":"Method list all received unaccepted proofs. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/issue":{"post":{"operationId":"ProofController_issueProof","summary":"Issue proof for credential","description":"Method will issue proof. If connection id is not passed, the proof will be OOB. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueProofRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["attributes must contain at least 1 elements","attributes must be an array"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/{proof_record_id}/accept":{"post":{"operationId":"ProofController_acceptProof","summary":"Accept credential proof","description":"Method accept credential proof. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[{"name":"proof_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}}},"info":{"title":"OCM Gateway","description":"OCM ENGINE GATEWAY API","version":"1.0","contact":{}},"tags":[],"servers":[{"url":"http://0.0.0.0:8081"}],"components":{"schemas":{"CloudEventDto":{"type":"object","properties":{}},"GatewayAcceptedResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"80633e6d-c606-4539-a3df-287fedd09253"}},"required":["id"]},"CreateInvitationResponseDto":{"type":"object","properties":{"invitationUrl":{"type":"string","description":"A list of user's roles","example":"http://0.0.0.0:8001?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiIzYWExNGIzNC04YTk5LTQxY2UtYTY3NC1jODUxYmVhMTIxMWEiLCJsYWJlbCI6IkRFeGNWYXNkX0FHRU5UXzQ1IiwiYWNjZXB0IjpbImRpZGNvbW0vYWlwMSIsImRpZGNvbW0vYWlwMjtlbnY9cmZjMTkiXSwiaGFuZHNoYWtlX3Byb3RvY29scyI6WyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMCIsImh0dHBzOi8vZGlkY29tbS5vcmcvY29ubmVjdGlvbnMvMS4wIl0sInNlcnZpY2VzIjpbeyJpZCI6IiNpbmxpbmUtMCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly8wLjAuMC4wOjgwMDEiLCJ0eXBlIjoiZGlkLWNvbW11bmljYXRpb24iLCJyZWNpcGllbnRLZXlzIjpbImRpZDprZXk6ejZNa3VFcHllc1pNa3k0a1BpQzhEOEplZERlcm55YTFuaTREMUF3ZmdnWWt6YmR4Il0sInJvdXRpbmdLZXlzIjpbXX1dfQ"}},"required":["invitationUrl"]},"CreateSchemaRequestDto":{"type":"object","properties":{"name":{"type":"string","example":"my test schema"},"attributes":{"example":["first_name, last_name"],"type":"array","items":{"type":"string"}},"version":{"type":"string","example":"1.0.2","pattern":"/^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$/"}},"required":["name","attributes","version"]},"GetSchemaRequestDto":{"type":"object","properties":{"schemaId":{"type":"string","example":"did:indy:LEDNGER:SXM76gQwRnjkgoz2oBnGjd/anoncreds/v0/SCHEMA/test schema/1.0.2"}},"required":["schemaId"]},"CreateCredentialDefinitionRequsetDto":{"type":"object","properties":{"schemaId":{"type":"string"},"tag":{"type":"string"}},"required":["schemaId","tag"]},"IssueCredentialAttributes":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"]},"IssueCredentialRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"credentialDefinitionId":{"type":"string"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueCredentialAttributes"}}},"required":["connectionId","credentialDefinitionId","attributes"]},"MakeBasicMessageRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"message":{"type":"string","example":"hello world"}},"required":["connectionId","message"]},"IssueProofAttribute":{"type":"object","properties":{"attributeName":{"type":"string"},"credentialDefinitionId":{"type":"string"},"schemaId":{"type":"string"}},"required":["attributeName","credentialDefinitionId","schemaId"]},"IssueProofRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueProofAttribute"}}},"required":["attributes"]}}}}
\ No newline at end of file
+{"openapi":"3.0.0","paths":{"/api/v1/invitations":{"post":{"operationId":"ConnectionController_createInvitation","summary":"Create invitation for connection","description":"Method will create invitation url. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/invitations/accept":{"post":{"operationId":"ConnectionController_acceptInvitation","summary":"Accept invitation for connection","description":"Method will accept the invitation and will return connection thought the websocket. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitationResponseDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["invitationUrl must be a string","invitationUrl should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections":{"get":{"operationId":"ConnectionController_list","summary":"List all connections","description":"The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections/{id}":{"get":{"operationId":"ConnectionController_getById","summary":"Get connection by id","description":"The method will search for connection id, if not found null will be returned. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/schemas":{"post":{"operationId":"AttestationController_createSchema","summary":"Create schema","description":"Method will create schema. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["name must be a string","name should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}},"get":{"operationId":"AttestationController_listSchema","summary":"List all schemas","description":"Method will fetch all schemas. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/schemas-by-id":{"post":{"operationId":"AttestationController_getSchemaById","summary":"Get schema by id","description":"Method will fetch specific schema or return null. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/definition":{"post":{"operationId":"AttestationController_createCredentialDefinition","summary":"Create credential definition","description":"Method create credential definition. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCredentialDefinitionRequsetDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty","tag must be a string","tag should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/issue":{"post":{"operationId":"AttestationController_issueCredential","summary":"Issue credential","description":"Method issue credential, it will create an offer and send it to specified receiver (connectionId). The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueCredentialRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","credentialDefinitionId must be a string","credentialDefinitionId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials":{"get":{"operationId":"AttestationController_credentials","summary":"List all credential","description":"Method list credential definition no filters applied. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers":{"get":{"operationId":"AttestationController_getCredentialOffers","summary":"List unaccepted credential offers","description":"Method list offers that are received, but not accepted. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers/{credential_record_id}/accept":{"post":{"operationId":"AttestationController_acceptCredential","summary":"Accept credential offers","description":"Method list accept credential offer. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[{"name":"credential_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/messages":{"post":{"operationId":"AttestationController_sendMeesage","summary":"Send basic message","description":"Method will send basic message to a connection. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MakeBasicMessageRequestDto"}}}},"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","message must be a string","message should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/proof":{"get":{"operationId":"ProofController_proofs","summary":"List received unaccepted proofs","description":"Method list all received unaccepted proofs. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/{proof_record_id}":{"get":{"operationId":"ProofController_getProofById","summary":"Get a single proof record by providing proof record id.","description":"Method get proof by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[{"name":"proof_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/issue":{"post":{"operationId":"ProofController_issueProof","summary":"Issue proof for credential","description":"Method will issue proof. If connection id is not passed, the proof will be OOB. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueProofRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["attributes must contain at least 1 elements","attributes must be an array"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/accept":{"post":{"operationId":"ProofController_acceptProof","summary":"Accept credential proof","description":"Method accept credential proof. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptProofRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/{proof_record_id}/decline":{"post":{"operationId":"ProofController_declineProofRequest","summary":"Decline a proof request.","description":"Method to decline a proof request by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[{"name":"proof_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}}},"info":{"title":"OCM Gateway","description":"OCM ENGINE GATEWAY API","version":"1.0","contact":{}},"tags":[],"servers":[{"url":"http://undefined:NaN"}],"components":{"schemas":{"CloudEventDto":{"type":"object","properties":{}},"GatewayAcceptedResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"80633e6d-c606-4539-a3df-287fedd09253"}},"required":["id"]},"CreateInvitationResponseDto":{"type":"object","properties":{"invitationUrl":{"type":"string","description":"A list of user's roles","example":"http://0.0.0.0:8001?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiIzYWExNGIzNC04YTk5LTQxY2UtYTY3NC1jODUxYmVhMTIxMWEiLCJsYWJlbCI6IkRFeGNWYXNkX0FHRU5UXzQ1IiwiYWNjZXB0IjpbImRpZGNvbW0vYWlwMSIsImRpZGNvbW0vYWlwMjtlbnY9cmZjMTkiXSwiaGFuZHNoYWtlX3Byb3RvY29scyI6WyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMCIsImh0dHBzOi8vZGlkY29tbS5vcmcvY29ubmVjdGlvbnMvMS4wIl0sInNlcnZpY2VzIjpbeyJpZCI6IiNpbmxpbmUtMCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly8wLjAuMC4wOjgwMDEiLCJ0eXBlIjoiZGlkLWNvbW11bmljYXRpb24iLCJyZWNpcGllbnRLZXlzIjpbImRpZDprZXk6ejZNa3VFcHllc1pNa3k0a1BpQzhEOEplZERlcm55YTFuaTREMUF3ZmdnWWt6YmR4Il0sInJvdXRpbmdLZXlzIjpbXX1dfQ"}},"required":["invitationUrl"]},"CreateSchemaRequestDto":{"type":"object","properties":{"name":{"type":"string","example":"my test schema"},"attributes":{"example":["first_name, last_name"],"type":"array","items":{"type":"string"}},"version":{"type":"string","example":"1.0.2","pattern":"/^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$/"}},"required":["name","attributes","version"]},"GetSchemaRequestDto":{"type":"object","properties":{"schemaId":{"type":"string","example":"did:indy:LEDNGER:SXM76gQwRnjkgoz2oBnGjd/anoncreds/v0/SCHEMA/test schema/1.0.2"}},"required":["schemaId"]},"CreateCredentialDefinitionRequsetDto":{"type":"object","properties":{"schemaId":{"type":"string"},"tag":{"type":"string"}},"required":["schemaId","tag"]},"IssueCredentialAttributes":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"]},"IssueCredentialRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"credentialDefinitionId":{"type":"string"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueCredentialAttributes"}}},"required":["connectionId","credentialDefinitionId","attributes"]},"MakeBasicMessageRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"message":{"type":"string","example":"hello world"}},"required":["connectionId","message"]},"IssueProofAttribute":{"type":"object","properties":{"attributeName":{"type":"string"},"credentialDefinitionId":{"type":"string"},"schemaId":{"type":"string"}},"required":["attributeName","credentialDefinitionId","schemaId"]},"IssueProofRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueProofAttribute"}}},"required":["attributes"]},"AcceptProofRequestDto":{"type":"object","properties":{"proofRecordId":{"type":"string"},"proofUrl":{"type":"string"}},"required":["proofRecordId","proofUrl"]}}}}
\ No newline at end of file
diff --git a/libs/askar/src/agent.utils.ts b/libs/askar/src/agent.utils.ts
index 30de9c76e6f7304812caf2060d5e391e770dc9ad..9bca784c0838eac47a45b12ac1ca83e3b0f23673 100644
--- a/libs/askar/src/agent.utils.ts
+++ b/libs/askar/src/agent.utils.ts
@@ -2,15 +2,18 @@ import {
   Agent,
   AutoAcceptCredential,
   AutoAcceptProof,
+  BaseEvent,
   ConnectionsModule,
   ConnectionStateChangedEvent,
   CredentialsModule,
   DidExchangeRole,
   DidsModule,
+  EncryptedMessage,
   Key,
   KeyDidResolver,
   KeyType,
   PeerDidResolver,
+  ProofEventTypes,
   ProofsModule,
   ProofState,
   ProofStateChangedEvent,
@@ -40,6 +43,25 @@ import { ariesAskar } from "@hyperledger/aries-askar-nodejs";
 import { Key as C, KeyAlgs } from "@hyperledger/aries-askar-shared";
 import { IConfAgent } from "@ocm-engine/config";
 import axios from "axios";
+import {
+  catchError,
+  filter,
+  lastValueFrom,
+  map,
+  Observable,
+  ReplaySubject,
+  Subject,
+  take,
+  timeout,
+} from "rxjs";
+import { SubjectInboundTransport } from "./askar/transports/agent.subject.inbound.transport";
+import { SubjectOutboundTransport } from "./askar/transports/agent.subject.outbound.transport";
+
+export type EventReplaySubject = ReplaySubject<BaseEvent>;
+export type SubjectMessage = {
+  message: EncryptedMessage;
+  replySubject?: Subject<SubjectMessage>;
+};
 
 export const importDidsToWallet = async (
   agent: Agent,
@@ -147,6 +169,36 @@ export const getAskarAnonCredsIndyModules = (networks: any) => {
   } as const;
 };
 
+export const setupEventReplaySubjects = (
+  agents: Agent[],
+  eventTypes: string[],
+): ReplaySubject<BaseEvent>[] => {
+  const replaySubjects: EventReplaySubject[] = [];
+
+  for (const agent of agents) {
+    const replaySubject = new ReplaySubject<BaseEvent>();
+
+    for (const eventType of eventTypes) {
+      agent.events.observable(eventType).subscribe(replaySubject);
+    }
+
+    replaySubjects.push(replaySubject);
+  }
+
+  return replaySubjects;
+};
+
+export const setupSubjectTransports = (agents: Agent[]) => {
+  const subjectMap: Record<string, Subject<SubjectMessage>> = {};
+
+  for (const agent of agents) {
+    const messages = new Subject<SubjectMessage>();
+    subjectMap[agent.config.endpoints[0]] = messages;
+    agent.registerInboundTransport(new SubjectInboundTransport(messages));
+    agent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap));
+  }
+};
+
 export const svdxProofStateChangeHandler = async (
   ev: ProofStateChangedEvent,
   agent: Agent,
@@ -272,3 +324,64 @@ export const svdxConnectionStateChangeHandler = async (
     console.log("failed to issue credential");
   }
 };
+
+export const isProofStateChangedEvent = (
+  e: BaseEvent,
+): e is ProofStateChangedEvent => e.type === ProofEventTypes.ProofStateChanged;
+
+export const waitForProofExchangeRecordSubject = (
+  subject: ReplaySubject<BaseEvent> | Observable<BaseEvent>,
+  {
+    threadId,
+    parentThreadId,
+    state,
+    previousState,
+    timeoutMs = 10000,
+    count = 1,
+  }: {
+    threadId?: string;
+    parentThreadId?: string;
+    state?: ProofState;
+    previousState?: ProofState | null;
+    timeoutMs?: number;
+    count?: number;
+  },
+) => {
+  const observable: Observable<BaseEvent> =
+    subject instanceof ReplaySubject ? subject.asObservable() : subject;
+  return lastValueFrom(
+    observable.pipe(
+      filter(isProofStateChangedEvent),
+      filter(
+        (e) =>
+          previousState === undefined ||
+          e.payload.previousState === previousState,
+      ),
+      filter(
+        (e) =>
+          threadId === undefined || e.payload.proofRecord.threadId === threadId,
+      ),
+      filter(
+        (e) =>
+          parentThreadId === undefined ||
+          e.payload.proofRecord.parentThreadId === parentThreadId,
+      ),
+      filter(
+        (e) => state === undefined || e.payload.proofRecord.state === state,
+      ),
+      timeout(timeoutMs),
+      catchError(() => {
+        throw new Error(
+          `ProofStateChangedEvent event not emitted within specified timeout: ${timeoutMs}
+          previousState: ${previousState},
+          threadId: ${threadId},
+          parentThreadId: ${parentThreadId},
+          state: ${state}
+        }`,
+        );
+      }),
+      take(count),
+      map((e) => e.payload.proofRecord),
+    ),
+  );
+};
diff --git a/libs/askar/src/askar-nats/event.handler.service.ts b/libs/askar/src/askar-nats/event.handler.service.ts
index 0561068736ff1ec96d3331c210a49683aaa24096..b1a634a6b3b166e1bcb849a4e5d0e6c53a0f87f4 100644
--- a/libs/askar/src/askar-nats/event.handler.service.ts
+++ b/libs/askar/src/askar-nats/event.handler.service.ts
@@ -21,13 +21,17 @@ import {
   IssueCredentialRequestDto,
   IssueProofRequestDto,
   MakeBasicMessageRequestDto,
+  DeclineProofRequestDto,
   MESSAGE_MAKE,
   PROOF_ACCEPT,
   PROOF_ISSUE,
   PROOF_LIST,
+  PROOF_GET,
   SCHEMA_CREATE,
   SCHEMA_GET,
   SCHEMA_LIST,
+  GetProofRequestDto,
+  PROOF_DECLINE,
 } from "@ocm-engine/dtos";
 import asyncRetry from "async-retry";
 
@@ -108,9 +112,22 @@ export class EventHandlerService {
             data = await this.agentService.proofs();
             break;
 
+          case PROOF_GET:
+            dto = event.data as GetProofRequestDto;
+            data = await this.agentService.getProofById(dto.proofRecordId);
+            break;
+
           case PROOF_ACCEPT:
-            dto = event.data as AcceptProofRequestDto;
-            data = await this.agentService.acceptProof(dto.proofRecordId);
+            data = await this.agentService.acceptProof(
+              event.data as AcceptProofRequestDto,
+            );
+            break;
+
+          case PROOF_DECLINE:
+            dto = event.data as DeclineProofRequestDto;
+            data = await this.agentService.declineProofRequest(
+              dto.proofRecordId,
+            );
             break;
 
           case MESSAGE_MAKE:
diff --git a/libs/askar/src/askar-rest/rest.controller.ts b/libs/askar/src/askar-rest/rest.controller.ts
index 53c82aa8e4766e73ed88f97bd58377d6f4800d24..8227d7dd6ab466a4ce94aa370eb68f31f7c8a1b5 100644
--- a/libs/askar/src/askar-rest/rest.controller.ts
+++ b/libs/askar/src/askar-rest/rest.controller.ts
@@ -8,6 +8,8 @@ import {
   IssueProofRequestDto,
   CreateSchemaRequestDto,
   MakeBasicMessageRequestDto,
+  AcceptProofRequestDto,
+  GetProofRequestDto,
 } from "@ocm-engine/dtos";
 import { AllExceptionsHandler } from "./exception.handler";
 
@@ -77,9 +79,19 @@ export class RestController {
     return this.agentService.issueProof(issueProofDto);
   }
 
-  @Post(`/credential/proof/:proof_record_id/accept`)
-  acceptProof(@Param("proof_record_id") proofRecordId: string) {
-    return this.agentService.acceptProof(proofRecordId);
+  @Get("credential/proof/:proof_record_id")
+  getProof(@Param("proof_record_id") data: GetProofRequestDto) {
+    return this.agentService.getProofById(data.proofRecordId);
+  }
+
+  @Post(`/credential/proof/accept`)
+  acceptProof(@Body() acceptProofRequestDto: AcceptProofRequestDto) {
+    return this.agentService.acceptProof(acceptProofRequestDto);
+  }
+
+  @Post(`/credential/proof/:proof_record_id/decline`)
+  declineProofRequest(@Param("proof_record_id") proofRecordId: string) {
+    return this.agentService.declineProofRequest(proofRecordId);
   }
 
   @Post("/resolve")
@@ -88,7 +100,7 @@ export class RestController {
   }
 
   @Post("/messages")
-  async sendMeesage(@Body() message: MakeBasicMessageRequestDto) {
+  sendMeesage(@Body() message: MakeBasicMessageRequestDto) {
     return this.agentService.sendMessage(message);
   }
 }
diff --git a/libs/askar/src/askar/agent.event.listener.servce.ts b/libs/askar/src/askar/agent-event-listener.service.ts
similarity index 97%
rename from libs/askar/src/askar/agent.event.listener.servce.ts
rename to libs/askar/src/askar/agent-event-listener.service.ts
index 08c4fec6be11ee782da60f2ba85f6e9dea9a0666..9cb3722871aefcae414e07427051dfe572d6fc69 100644
--- a/libs/askar/src/askar/agent.event.listener.servce.ts
+++ b/libs/askar/src/askar/agent-event-listener.service.ts
@@ -23,9 +23,9 @@ import {
 } from "../agent.utils";
 
 @Injectable()
-export class AgentEventListenerServce implements OnModuleInit {
+export class AgentEventListenerService implements OnModuleInit {
   private agentConfig: IConfAgent | undefined;
-  private readonly logger: Logger = new Logger(AgentEventListenerServce.name);
+  private readonly logger: Logger = new Logger(AgentEventListenerService.name);
 
   constructor(
     private readonly gatewayClient: GatewayClient,
diff --git a/libs/askar/src/askar/agent.service.ts b/libs/askar/src/askar/agent.service.ts
index 7f95b64e4903789f93afeb894af29d5dc6223e2a..15ace71407fc3eae827b46e1bfcfebabcf9458d6 100644
--- a/libs/askar/src/askar/agent.service.ts
+++ b/libs/askar/src/askar/agent.service.ts
@@ -2,6 +2,7 @@ import { Injectable } from "@nestjs/common";
 import { AskarService } from "./askar.service";
 import {
   AcceptInvitationResponseDto,
+  AcceptProofRequestDto,
   ConnectionNotFoundError,
   CreateCredentialDefinitionRequsetDto,
   CreateCredentialDefinitionResponseDto,
@@ -13,16 +14,21 @@ import {
   IssueCredentialResponseDto,
   IssueProofRequestDto,
   IssueProofResponseDto,
+  GetProofByIdResponseDto,
   MakeBasicMessageRequestDto,
   MakeBasicMessageResponseDto,
   SchemaNotCreatedError,
+  DeclineProofResponseDto,
 } from "@ocm-engine/dtos";
 import {
+  AutoAcceptProof,
   CredentialState,
-  ProofExchangeRecord,
+  JsonEncoder,
   ProofState,
 } from "@aries-framework/core";
 import { AnonCredsRequestedAttribute } from "@aries-framework/anoncreds";
+import { uuid } from "@aries-framework/core/build/utils/uuid";
+import { waitForProofExchangeRecordSubject } from "../agent.utils";
 
 @Injectable()
 export class AgentService {
@@ -228,11 +234,11 @@ export class AgentService {
   };
 
   issueProof = async (issueProofDto: IssueProofRequestDto) => {
-    let exchangeRecord: ProofExchangeRecord;
+    console.log(JSON.stringify(issueProofDto, null, 2));
     const requestedAttributes: Record<string, AnonCredsRequestedAttribute> = {};
 
     for (const attr of issueProofDto.attributes) {
-      requestedAttributes[attr.attributeName] = {
+      requestedAttributes[uuid()] = {
         name: attr.attributeName,
         restrictions: [
           {
@@ -244,32 +250,45 @@ export class AgentService {
     }
 
     if (!issueProofDto.connectionId) {
-      const { proofRecord } = await this.askar.agent.proofs.createRequest({
-        protocolVersion: "v2",
-        proofFormats: {
-          anoncreds: {
-            name: "proof-request",
-            version: "1.0",
-            requested_attributes: requestedAttributes,
+      console.log("connection Id not detected, creating oob proof");
+      const { proofRecord, message } =
+        await this.askar.agent.proofs.createRequest({
+          protocolVersion: "v2",
+          proofFormats: {
+            anoncreds: {
+              name: "proof-request",
+              version: "1.0",
+              requested_attributes: requestedAttributes,
+            },
           },
-        },
-      });
+          autoAcceptProof: AutoAcceptProof.ContentApproved,
+        });
 
-      exchangeRecord = proofRecord;
-    } else {
-      exchangeRecord = await this.askar.agent.proofs.requestProof({
-        protocolVersion: "v2",
-        connectionId: issueProofDto.connectionId,
-        proofFormats: {
-          anoncreds: {
-            name: "proof-request",
-            version: "1.0",
-            requested_attributes: requestedAttributes,
-          },
-        },
-      });
+      console.log({ proofRecord });
+      const { invitationUrl } =
+        await this.askar.agent.oob.createLegacyConnectionlessInvitation({
+          recordId: proofRecord.id,
+          message,
+          domain: this.askar.agentConfig.agentPeerAddress,
+        });
+
+      return { proofUrl: invitationUrl };
     }
 
+    console.log(`${issueProofDto.connectionId} detected, issuing proof`);
+
+    const exchangeRecord = await this.askar.agent.proofs.requestProof({
+      protocolVersion: "v2",
+      connectionId: issueProofDto.connectionId,
+      proofFormats: {
+        anoncreds: {
+          name: "proof-request",
+          version: "1.0",
+          requested_attributes: requestedAttributes,
+        },
+      },
+    });
+
     const response = new IssueProofResponseDto();
     response.proofId = exchangeRecord.id;
     response.connectionId = exchangeRecord.connectionId;
@@ -300,25 +319,102 @@ export class AgentService {
     return response;
   };
 
-  acceptProof = async (proofRecordId: string) => {
+  getProofById = async (proofRecordId: string) => {
+    const proofRecord = await this.askar.agent.proofs.findById(proofRecordId);
+
+    if (!proofRecord) {
+      return proofRecord;
+    }
+
+    const proofResponse = new GetProofByIdResponseDto();
+
+    proofResponse.proofId = proofRecord.id;
+    proofResponse.connectionId = proofRecord.connectionId;
+    proofResponse.state = proofRecord.state;
+    proofResponse.updatedAt = proofRecord.updatedAt;
+    proofResponse.createdAt = proofRecord.createdAt;
+
+    return proofResponse;
+  };
+
+  acceptProof = async (acceptProofDto: AcceptProofRequestDto) => {
+    if (acceptProofDto.proofUrl) {
+      return this.acceptOobProof(acceptProofDto.proofUrl);
+    }
+    return this.acceptConnectionProof(acceptProofDto.proofId);
+  };
+
+  acceptOobProof = async (url: string) => {
+    const param = url.split("d_m=")[1];
+
+    const t = JsonEncoder.fromBase64(param);
+
+    await this.askar.agent.receiveMessage(t);
+
+    const record = await waitForProofExchangeRecordSubject(this.askar.agentR, {
+      state: ProofState.RequestReceived,
+    });
+
+    const requestedCredentials =
+      await this.askar.agent.proofs.selectCredentialsForRequest({
+        proofRecordId: record.id,
+      });
+
+    const acceptedRecord = await this.askar.agent.proofs.acceptRequest({
+      proofRecordId: record.id,
+      proofFormats: requestedCredentials.proofFormats,
+    });
+
+    const response = new IssueProofResponseDto();
+
+    response.proofId = acceptedRecord.id;
+    response.state = acceptedRecord.state;
+    response.updatedAt = acceptedRecord.updatedAt;
+    response.createdAt = acceptedRecord.createdAt;
+
+    return acceptedRecord;
+  };
+
+  acceptConnectionProof = async (proofRecordId: string) => {
+    console.log(`accepting proof request for ${proofRecordId}`);
     const requestedCredentials =
       await this.askar.agent.proofs.selectCredentialsForRequest({
         proofRecordId,
       });
 
+    console.log(JSON.stringify(requestedCredentials, null, 2));
+
     const proof = await this.askar.agent.proofs.acceptRequest({
       proofRecordId,
       proofFormats: requestedCredentials.proofFormats,
     });
 
-    const t = new IssueProofResponseDto();
-    t.proofId = proof.id;
-    t.connectionId = proof.connectionId;
-    t.state = proof.state;
-    t.updatedAt = proof.updatedAt;
-    t.createdAt = proof.createdAt;
+    console.log(JSON.stringify(proof, null, 2));
+
+    const response = new IssueProofResponseDto();
+    response.proofId = proof.id;
+    response.connectionId = proof.connectionId;
+    response.state = proof.state;
+    response.updatedAt = proof.updatedAt;
+    response.createdAt = proof.createdAt;
+
+    return response;
+  };
+
+  declineProofRequest = async (proofRecordId: string) => {
+    const resultFromDecline = await this.askar.agent.proofs.declineRequest({
+      proofRecordId,
+      // sendProblemReport: false, // REVIEW: do we have a use case for this key?
+    });
+
+    const declineResponse = new DeclineProofResponseDto();
+    declineResponse.proofId = resultFromDecline.id;
+    declineResponse.connectionId = resultFromDecline.connectionId;
+    declineResponse.state = resultFromDecline.state;
+    declineResponse.updatedAt = resultFromDecline.updatedAt;
+    declineResponse.createdAt = resultFromDecline.createdAt;
 
-    return t;
+    return declineResponse;
   };
 
   resolve = async (did: string) => {
diff --git a/libs/askar/src/askar/askar.module.ts b/libs/askar/src/askar/askar.module.ts
index 05a8706a87d787f04c2509461d5db4e9463974e0..c2f542cef457dd735b3ff5514299703b737bf903 100644
--- a/libs/askar/src/askar/askar.module.ts
+++ b/libs/askar/src/askar/askar.module.ts
@@ -3,7 +3,7 @@ import { AskarService } from "./askar.service";
 import { AgentService } from "./agent.service";
 import { ConfigModule } from "@nestjs/config";
 import { LedgersModule } from "@ocm-engine/ledgers";
-import { AgentEventListenerServce } from "./agent.event.listener.servce";
+import { AgentEventListenerService } from "./agent-event-listener.service";
 import { GatewayClient } from "@ocm-engine/clients";
 
 @Global()
@@ -12,7 +12,7 @@ import { GatewayClient } from "@ocm-engine/clients";
   providers: [
     AgentService,
     AskarService,
-    AgentEventListenerServce,
+    AgentEventListenerService,
     GatewayClient,
   ],
   exports: [AgentService, AskarService],
diff --git a/libs/askar/src/askar/askar.service.ts b/libs/askar/src/askar/askar.service.ts
index e07eb52a9f77a1f1b57ff7e0df2acdeebf9ec5e8..27c5307f0866f3cd1b07980fcac62b63759a9c91 100644
--- a/libs/askar/src/askar/askar.service.ts
+++ b/libs/askar/src/askar/askar.service.ts
@@ -7,10 +7,12 @@ import {
 
 import {
   Agent,
+  BaseEvent,
   ConsoleLogger,
   HttpOutboundTransport,
   InitConfig,
   LogLevel,
+  ProofEventTypes,
   TypedArrayEncoder,
   WsOutboundTransport,
 } from "@aries-framework/core";
@@ -22,12 +24,16 @@ import {
   generateKey,
   getAskarAnonCredsIndyModules,
   importDidsToWallet,
+  setupEventReplaySubjects,
+  setupSubjectTransports,
 } from "../agent.utils";
 import { IConfAgent } from "@ocm-engine/config";
+import { ReplaySubject } from "rxjs";
 
 @Injectable()
 export class AskarService implements OnModuleInit, OnModuleDestroy {
   public agent: Agent<ReturnType<typeof getAskarAnonCredsIndyModules>>;
+  public agentR: ReplaySubject<BaseEvent>;
   public agentConfig: IConfAgent;
   private readonly logger: Logger = new Logger(AskarService.name);
 
@@ -73,6 +79,14 @@ export class AskarService implements OnModuleInit, OnModuleDestroy {
     this.agent.registerOutboundTransport(new WsOutboundTransport());
     this.agent.registerOutboundTransport(new HttpOutboundTransport());
 
+    setupSubjectTransports([this.agent]);
+
+    const [agentR] = setupEventReplaySubjects(
+      [this.agent],
+      [ProofEventTypes.ProofStateChanged],
+    );
+
+    this.agentR = agentR;
     this.logger.log("Agent setup completed");
   }
 
diff --git a/libs/askar/src/askar/transports/agent.subject.inbound.transport.ts b/libs/askar/src/askar/transports/agent.subject.inbound.transport.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1a78cda63b11033b8eb096daec3831d1fdfc264d
--- /dev/null
+++ b/libs/askar/src/askar/transports/agent.subject.inbound.transport.ts
@@ -0,0 +1,80 @@
+import {
+  Agent,
+  AgentContext,
+  EncryptedMessage,
+  InboundTransport,
+  MessageReceiver,
+  TransportService,
+  TransportSession,
+} from "@aries-framework/core";
+import { Subject, Subscription } from "rxjs";
+import { uuid } from "@aries-framework/core/build/utils/uuid";
+import { SubjectMessage } from "../../agent.utils";
+
+class SubjectTransportSession implements TransportSession {
+  public id: string;
+  public readonly type = "subject";
+  private replySubject: Subject<SubjectMessage>;
+
+  public constructor(id: string, replySubject: Subject<SubjectMessage>) {
+    this.id = id;
+    this.replySubject = replySubject;
+  }
+
+  public async send(
+    agentContext: AgentContext,
+    encryptedMessage: EncryptedMessage,
+  ): Promise<void> {
+    this.replySubject.next({ message: encryptedMessage });
+  }
+
+  public async close(): Promise<void> {
+    this.replySubject.complete();
+  }
+}
+
+export class SubjectInboundTransport implements InboundTransport {
+  public readonly ourSubject: Subject<SubjectMessage>;
+  private subscription?: Subscription;
+
+  public constructor(ourSubject = new Subject<SubjectMessage>()) {
+    this.ourSubject = ourSubject;
+  }
+
+  public async start(agent: Agent) {
+    this.subscribe(agent);
+  }
+
+  public async stop() {
+    this.subscription?.unsubscribe();
+  }
+
+  private subscribe(agent: Agent) {
+    const logger = agent.config.logger;
+    const transportService = agent.dependencyManager.resolve(TransportService);
+    const messageReceiver = agent.dependencyManager.resolve(MessageReceiver);
+
+    this.subscription = this.ourSubject.subscribe({
+      next: async ({ message, replySubject }: SubjectMessage) => {
+        logger.test("Received message");
+
+        let session: SubjectTransportSession | undefined;
+        if (replySubject) {
+          session = new SubjectTransportSession(
+            `subject-session-${uuid()}`,
+            replySubject,
+          );
+
+          // When the subject is completed (e.g. when the session is closed), we need to
+          // remove the session from the transport service so it won't be used for sending messages
+          // in the future.
+          replySubject.subscribe({
+            complete: () => session && transportService.removeSession(session),
+          });
+        }
+
+        await messageReceiver.receiveMessage(message, { session });
+      },
+    });
+  }
+}
diff --git a/libs/askar/src/askar/transports/agent.subject.outbound.transport.ts b/libs/askar/src/askar/transports/agent.subject.outbound.transport.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4c3d77c2471c4935018874a66e9c13df20329586
--- /dev/null
+++ b/libs/askar/src/askar/transports/agent.subject.outbound.transport.ts
@@ -0,0 +1,80 @@
+import {
+  Agent,
+  AriesFrameworkError,
+  InjectionSymbols,
+  MessageReceiver,
+  OutboundPackage,
+  OutboundTransport,
+} from "@aries-framework/core";
+import { Logger } from "@nestjs/common";
+import { Subject, take, takeUntil } from "rxjs";
+import { SubjectMessage } from "../../agent.utils";
+
+export class SubjectOutboundTransport implements OutboundTransport {
+  private logger!: Logger;
+  private subjectMap: { [key: string]: Subject<SubjectMessage> | undefined };
+  private agent!: Agent;
+  private stop$!: Subject<boolean>;
+
+  public supportedSchemes = ["rxjs", "wss"];
+
+  public constructor(subjectMap: {
+    [key: string]: Subject<SubjectMessage> | undefined;
+  }) {
+    this.subjectMap = subjectMap;
+  }
+
+  public async start(agent: Agent): Promise<void> {
+    this.agent = agent;
+
+    this.logger = agent.dependencyManager.resolve(InjectionSymbols.Logger);
+    this.stop$ = agent.dependencyManager.resolve(InjectionSymbols.Stop$);
+  }
+
+  public async stop(): Promise<void> {
+    // No logic needed
+  }
+
+  public async sendMessage(outboundPackage: OutboundPackage) {
+    const messageReceiver =
+      this.agent.dependencyManager.resolve(MessageReceiver);
+    this.logger.debug(
+      `Sending outbound message to endpoint ${outboundPackage.endpoint}`,
+      {
+        endpoint: outboundPackage.endpoint,
+      },
+    );
+    const { payload, endpoint } = outboundPackage;
+
+    if (!endpoint) {
+      throw new AriesFrameworkError(
+        "Cannot send message to subject without endpoint",
+      );
+    }
+
+    const subject = this.subjectMap[endpoint];
+
+    if (!subject) {
+      throw new AriesFrameworkError(
+        `No subject found for endpoint ${endpoint}`,
+      );
+    }
+
+    // Create a replySubject just for this session. Both ends will be able to close it,
+    // mimicking a transport like http or websocket. Close session automatically when agent stops
+    const replySubject = new Subject<SubjectMessage>();
+    this.stop$
+      .pipe(take(1))
+      .subscribe(() => !replySubject.closed && replySubject.complete());
+
+    replySubject.pipe(takeUntil(this.stop$)).subscribe({
+      next: async ({ message }: SubjectMessage) => {
+        this.logger.debug("Received message");
+
+        await messageReceiver.receiveMessage(message);
+      },
+    });
+
+    subject.next({ message: payload, replySubject });
+  }
+}
diff --git a/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts b/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts
index 848258238ee20537fbefc58b906bbcf2d7119cc8..5483583ebef614b46ee6cae700136126f61f8f26 100644
--- a/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts
+++ b/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts
@@ -1,7 +1,13 @@
-import { IsNotEmpty, IsString } from "class-validator";
+import { IsNotEmpty, IsString, ValidateIf } from "class-validator";
 
 export class AcceptProofRequestDto {
   @IsString()
   @IsNotEmpty()
-  proofRecordId: string;
+  @ValidateIf((o) => o.proofUrl === undefined)
+  proofId: string;
+
+  @IsString()
+  @IsNotEmpty()
+  @ValidateIf((o) => o.proofId === undefined)
+  proofUrl: string;
 }
diff --git a/libs/dtos/src/dtos/requests/decline.proof.request.dto.ts b/libs/dtos/src/dtos/requests/decline.proof.request.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2b37d7f4d915c4c193426f7c04d7d1db1ca80da4
--- /dev/null
+++ b/libs/dtos/src/dtos/requests/decline.proof.request.dto.ts
@@ -0,0 +1,10 @@
+import { IsBoolean, IsNotEmpty, IsString } from "class-validator";
+
+export class DeclineProofRequestDto {
+  @IsString()
+  @IsNotEmpty()
+  proofRecordId: string;
+
+  @IsBoolean()
+  sendProblemReport?: boolean;
+}
\ No newline at end of file
diff --git a/libs/dtos/src/dtos/requests/get.proof.request.dto.ts b/libs/dtos/src/dtos/requests/get.proof.request.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fdc7f72fdfbf960f6c20d4d36366cfb9afbfc7fc
--- /dev/null
+++ b/libs/dtos/src/dtos/requests/get.proof.request.dto.ts
@@ -0,0 +1,7 @@
+import { IsNotEmpty, IsString } from "class-validator";
+
+export class GetProofRequestDto {
+  @IsString()
+  @IsNotEmpty()
+  proofRecordId: string;
+}
diff --git a/libs/dtos/src/dtos/responses/decline.proof.response.dto.ts b/libs/dtos/src/dtos/responses/decline.proof.response.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e8e4885995ca4ff29db1dc4ac39b0bd8183389d3
--- /dev/null
+++ b/libs/dtos/src/dtos/responses/decline.proof.response.dto.ts
@@ -0,0 +1,25 @@
+import { 
+  IsDateString, 
+  IsNotEmpty, 
+  IsString 
+} from "class-validator";
+
+export class DeclineProofResponseDto {
+  @IsString()
+  @IsNotEmpty()
+  proofId: string;
+
+  @IsString()
+  connectionId?: string;
+
+  @IsString()
+  @IsNotEmpty()
+  state: string;
+
+  @IsDateString()
+  updatedAt?: Date;
+
+  @IsNotEmpty()
+  @IsDateString()
+  createdAt: Date;
+}
\ No newline at end of file
diff --git a/libs/dtos/src/dtos/responses/get.proof.response.dto.ts b/libs/dtos/src/dtos/responses/get.proof.response.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d044786caa05eadd9a57eb1836369f03ffbbc2e4
--- /dev/null
+++ b/libs/dtos/src/dtos/responses/get.proof.response.dto.ts
@@ -0,0 +1,25 @@
+import { 
+  IsDateString, 
+  IsNotEmpty, 
+  IsString 
+} from "class-validator";
+
+export class GetProofByIdResponseDto {
+  @IsString()
+  @IsNotEmpty()
+  proofId: string;
+
+  @IsString()
+  connectionId?: string;
+
+  @IsString()
+  @IsNotEmpty()
+  state: string;
+
+  @IsDateString()
+  updatedAt?: Date;
+
+  @IsNotEmpty()
+  @IsDateString()
+  createdAt: Date;
+}
diff --git a/libs/dtos/src/events/dtoToEventTransformer.ts b/libs/dtos/src/events/dtoToEventTransformer.ts
index cde079ed94ef10f8e5f83a9badd32af348e51030..a120dee89f47017180b2ffa1d8a3eeab2bf48fd9 100644
--- a/libs/dtos/src/events/dtoToEventTransformer.ts
+++ b/libs/dtos/src/events/dtoToEventTransformer.ts
@@ -17,6 +17,10 @@ import { IssueProofRequestDto } from "../dtos/requests/issue.proof.request.dto";
 import { AcceptCredentialOfferRequestDto } from "../dtos/requests/accept.credential.offer.request.dto";
 import { MakeBasicMessageResponseDto } from "../dtos/responses/make.basic.message.response.dto";
 import { MakeBasicMessageRequestDto } from "../dtos/requests/make.basic.message.request.dto";
+import { AcceptProofRequestDto } from "../dtos/requests/accept.proof.request.dto";
+import { GetProofByIdResponseDto } from "../dtos/responses/get.proof.response.dto";
+import { DeclineProofRequestDto } from '../dtos/requests/decline.proof.request.dto';
+import { DeclineProofResponseDto } from "../dtos/responses/decline.proof.response.dto";
 
 export const makeEvent = (payload: {
   data:
@@ -26,8 +30,12 @@ export const makeEvent = (payload: {
     | CreateInvitationResponseDto
     | GetConnectionRequestDto
     | CreateSchemaRequestDto
+    | AcceptProofRequestDto
+    | DeclineProofRequestDto
+    | DeclineProofResponseDto
     | CreateSchemaRequestDto
     | CreateCredentialDefinitionRequsetDto
+    | GetProofByIdResponseDto
     | IssueCredentialRequestDto
     | MakeBasicMessageResponseDto
     | MakeBasicMessageRequestDto;
diff --git a/libs/dtos/src/events/types.ts b/libs/dtos/src/events/types.ts
index f19e1b6c62fdfb057e40f735a4e762454006e0b7..f226768c0a49887a8e3d4d1e9352301176f59d01 100644
--- a/libs/dtos/src/events/types.ts
+++ b/libs/dtos/src/events/types.ts
@@ -48,16 +48,25 @@ export const CRED_EVENTS: CredentialEvent[] = [
   CRED_OFFER_ACCEPT,
 ];
 
-export type ProofEvent = "proofs.list" | "proofs.accept" | "proofs.issue";
+export type ProofEvent = 
+  | "proofs.list" 
+  | "proofs.accept" 
+  | "proofs.issue" 
+  | "proofs.get"
+  | "proofs.decline"
 
 export const PROOF_LIST = "proofs.list";
+export const PROOF_GET = "proofs.get"
 export const PROOF_ACCEPT = "proofs.accept";
 export const PROOF_ISSUE = "proofs.issue";
+export const PROOF_DECLINE = "proofs.decline"
 
 export const PROOF_EVENTS: ProofEvent[] = [
   PROOF_ACCEPT,
   PROOF_LIST,
   PROOF_ISSUE,
+  PROOF_GET,
+  PROOF_DECLINE,
 ];
 
 export type BasicMessageEvent = "messages.make";
diff --git a/libs/dtos/src/index.ts b/libs/dtos/src/index.ts
index e699d9fee52649b12387d27ab349fd61feaf4a10..ce0ac84aac42b0426913d8f6ed022b7e085fc050 100644
--- a/libs/dtos/src/index.ts
+++ b/libs/dtos/src/index.ts
@@ -8,6 +8,8 @@ export * from "./dtos/requests/get.schema.request.dto";
 export * from "./dtos/requests/accept.credential.offer.request.dto";
 export * from "./dtos/requests/accept.proof.request.dto";
 export * from "./dtos/requests/make.basic.message.request.dto";
+export * from "./dtos/requests/get.proof.request.dto";
+export * from "./dtos/requests/decline.proof.request.dto";
 
 export * from "./dtos/responses/create.invitation.response.dto";
 export * from "./dtos/responses/accept.invitation.response.dto";
@@ -17,6 +19,8 @@ export * from "./dtos/responses/issue.credential.response.dto";
 export * from "./dtos/responses/issue.proof.response.dto";
 export * from "./dtos/responses/gateway.accepted.response.dto";
 export * from "./dtos/responses/make.basic.message.response.dto";
+export * from "./dtos/responses/get.proof.response.dto";
+export * from "./dtos/responses/decline.proof.response.dto";
 
 export * from "./errors/connection.not.found.error";
 export * from "./errors/schema.not.created.error";
diff --git a/package.json b/package.json
index 1e94baaca7f1934074d4d47753c7ec0922c192b2..9979d29e05059f82ce25ba14d6862250ac668218 100644
--- a/package.json
+++ b/package.json
@@ -27,8 +27,8 @@
     "infra:holder": "cd compose && docker-compose --profile holder up -d --build",
     "infra:issuer:stop": "cd compose && docker-compose --profile issuer stop",
     "infra:holder:stop": "cd compose && docker-compose --profile holder stop",
-    "infra:local": "cd compose && docker-compose -f=docker-compose.infra.yml up -d",
-    "infra:local:stop": "cd compose && docker-compose -f=docker-compose.infra.yml stop",
+    "infra:local": "cd compose && docker-compose -f docker-compose.infra.yml up -d",
+    "infra:local:stop": "cd compose && docker-compose -f docker-compose.infra.yml stop",
     "infra:simple": "cd compose && docker-compose -f docker-compose.simple.yml up -d"
   },
   "private": true,