diff --git a/apps/attestation-manager/.eslintrc.json b/apps/attestation-manager/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..9d9c0db55bb1e91c5f2e7b64a02bc6bf69fc7cb5
--- /dev/null
+++ b/apps/attestation-manager/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+  "extends": ["../../.eslintrc.json"],
+  "ignorePatterns": ["!**/*"],
+  "overrides": [
+    {
+      "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+      "rules": {}
+    },
+    {
+      "files": ["*.ts", "*.tsx"],
+      "rules": {}
+    },
+    {
+      "files": ["*.js", "*.jsx"],
+      "rules": {}
+    }
+  ]
+}
diff --git a/apps/attestation-manager/deployment/Dockerfile b/apps/attestation-manager/deployment/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..96750a73306698cfc0764db1b0b45ed468d90042
--- /dev/null
+++ b/apps/attestation-manager/deployment/Dockerfile
@@ -0,0 +1,15 @@
+FROM node:18.16.0-buster-slim
+
+RUN apt update -y && apt install python3 git make build-essential -y
+
+WORKDIR app
+
+COPY ./dist/apps/attestation-manager .
+COPY package.json yarn.lock ./
+
+RUN yarn install
+
+
+EXPOSE 8883
+
+CMD ["node", "main.js"]
diff --git a/apps/attestation-manager/jest.config.ts b/apps/attestation-manager/jest.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..18a7bc1cca8e8df5a07ea18aabbaebf20e93c204
--- /dev/null
+++ b/apps/attestation-manager/jest.config.ts
@@ -0,0 +1,11 @@
+/* eslint-disable */
+export default {
+  displayName: "attestation-manager",
+  preset: "../../jest.preset.js",
+  testEnvironment: "node",
+  transform: {
+    "^.+\\.[tj]s$": ["ts-jest", { tsconfig: "<rootDir>/tsconfig.spec.json" }],
+  },
+  moduleFileExtensions: ["ts", "js", "html"],
+  coverageDirectory: "../../coverage/apps/attestation-manager",
+};
diff --git a/apps/attestation-manager/project.json b/apps/attestation-manager/project.json
new file mode 100644
index 0000000000000000000000000000000000000000..193c32f5168234cb3987d52c361801507db9e3f3
--- /dev/null
+++ b/apps/attestation-manager/project.json
@@ -0,0 +1,63 @@
+{
+  "name": "attestation-manager",
+  "$schema": "../../node_modules/nx/schemas/project-schema.json",
+  "sourceRoot": "apps/attestation-manager/src",
+  "projectType": "application",
+  "targets": {
+    "build": {
+      "executor": "@nx/webpack:webpack",
+      "outputs": ["{options.outputPath}"],
+      "defaultConfiguration": "production",
+      "options": {
+        "target": "node",
+        "compiler": "tsc",
+        "outputPath": "dist/apps/attestation-manager",
+        "main": "apps/attestation-manager/src/main.ts",
+        "tsConfig": "apps/attestation-manager/tsconfig.app.json",
+        "isolatedConfig": true,
+        "webpackConfig": "apps/attestation-manager/webpack.config.js"
+      },
+      "configurations": {
+        "development": {},
+        "production": {}
+      }
+    },
+    "serve": {
+      "executor": "@nx/js:node",
+      "defaultConfiguration": "development",
+      "options": {
+        "buildTarget": "attestation-manager:build"
+      },
+      "configurations": {
+        "development": {
+          "buildTarget": "attestation-manager:build:development"
+        },
+        "production": {
+          "buildTarget": "attestation-manager:build:production"
+        }
+      }
+    },
+    "lint": {
+      "executor": "@nx/linter:eslint",
+      "outputs": ["{options.outputFile}"],
+      "options": {
+        "lintFilePatterns": ["apps/attestation-manager/**/*.ts"]
+      }
+    },
+    "test": {
+      "executor": "@nx/jest:jest",
+      "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+      "options": {
+        "jestConfig": "apps/attestation-manager/jest.config.ts",
+        "passWithNoTests": true
+      },
+      "configurations": {
+        "ci": {
+          "ci": true,
+          "codeCoverage": true
+        }
+      }
+    }
+  },
+  "tags": []
+}
diff --git a/apps/attestation-manager/src/app/app.controller.ts b/apps/attestation-manager/src/app/app.controller.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3c778ceaf87f265b48165656ea5320f0ef4d7fb3
--- /dev/null
+++ b/apps/attestation-manager/src/app/app.controller.ts
@@ -0,0 +1,89 @@
+import { Body, Controller, Get, Logger } from "@nestjs/common";
+
+import { AppService } from "./app.service";
+import { MessagePattern, RpcException } from "@nestjs/microservices";
+import {
+  CloudEventDto,
+  ConnectionEvent,
+  CreateCredentialDefinitionRequsetDto,
+  CreateInvitationResponseDto,
+  CreateSchemaRequestDto,
+  CredentialEvent,
+  GetConnectionRequestDto,
+  IssueCredentialRequestDto,
+  SchemaEvent,
+} from "@ocm-engine/dtos";
+import { ProducerService } from "@ocm-engine/nats";
+
+@Controller()
+export class AppController {
+  private readonly logger: Logger = new Logger(AppController.name);
+
+  constructor(
+    private readonly producerService: ProducerService,
+    private readonly appService: AppService,
+  ) {}
+
+  @MessagePattern("schemas")
+  async create(
+    @Body()
+    payload: {
+      data: null | CreateSchemaRequestDto | CreateSchemaRequestDto;
+      type: SchemaEvent;
+      source: string;
+    },
+  ): Promise<{ id: string }> {
+    this.logger.debug(JSON.stringify(payload, null, 2));
+
+    try {
+      const event = this.appService.toEvent(payload);
+      this.logger.debug(JSON.stringify(event, null, 2));
+      await this.producerService.publish<typeof payload.data>(
+        payload.type,
+        event as CloudEventDto<typeof payload.data>,
+      );
+
+      return { id: event.id };
+    } catch (e) {
+      this.logger.debug(JSON.stringify(e, null, 2));
+      if (e instanceof Error) {
+        throw new RpcException(e.message);
+      }
+
+      throw new RpcException("Internal server error");
+    }
+  }
+
+  @MessagePattern("credentials")
+  async createCredential(
+    @Body()
+    payload: {
+      data:
+        | null
+        | CreateCredentialDefinitionRequsetDto
+        | IssueCredentialRequestDto;
+      type: CredentialEvent;
+      source: string;
+    },
+  ): Promise<{ id: string }> {
+    this.logger.debug(JSON.stringify(payload, null, 2));
+
+    try {
+      const event = this.appService.toEvent(payload);
+      this.logger.debug(JSON.stringify(event, null, 2));
+      await this.producerService.publish<typeof payload.data>(
+        payload.type,
+        event as CloudEventDto<typeof payload.data>,
+      );
+
+      return { id: event.id };
+    } catch (e) {
+      this.logger.debug(JSON.stringify(e, null, 2));
+      if (e instanceof Error) {
+        throw new RpcException(e.message);
+      }
+
+      throw new RpcException("Internal server error");
+    }
+  }
+}
diff --git a/apps/attestation-manager/src/app/app.module.ts b/apps/attestation-manager/src/app/app.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5fbe1f9a3d38d356789cb2985914f5f1fe66386e
--- /dev/null
+++ b/apps/attestation-manager/src/app/app.module.ts
@@ -0,0 +1,26 @@
+import { Module } from "@nestjs/common";
+
+import { AppController } from "./app.controller";
+import { AppService } from "./app.service";
+import { ConfigModule } from "@nestjs/config";
+import { amConfig, amSchema, natsConfig, natsSchema } from "@ocm-engine/config";
+import { ProducerService } from "@ocm-engine/nats";
+import Joi from "joi";
+
+const validationSchema = Joi.object({
+  nats: natsSchema,
+  am: amSchema,
+});
+
+@Module({
+  imports: [
+    ConfigModule.forRoot({
+      isGlobal: true,
+      load: [natsConfig, amConfig],
+      validationSchema,
+    }),
+  ],
+  controllers: [AppController],
+  providers: [ProducerService, AppService],
+})
+export class AppModule {}
diff --git a/apps/attestation-manager/src/app/app.service.ts b/apps/attestation-manager/src/app/app.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bb195327d59df12ccbb3cdb032316c8592f1da71
--- /dev/null
+++ b/apps/attestation-manager/src/app/app.service.ts
@@ -0,0 +1,37 @@
+import { Injectable } from "@nestjs/common";
+import {
+  ALL_EVENTS,
+  CloudEventDto,
+  ConnectionUnsupportedTypeError,
+  CreateCredentialDefinitionRequsetDto,
+  CreateSchemaRequestDto,
+  CredentialEvent,
+  IssueCredentialRequestDto,
+  SchemaEvent,
+} from "@ocm-engine/dtos";
+
+@Injectable()
+export class AppService {
+  toEvent = (payload: {
+    data:
+      | null
+      | CreateSchemaRequestDto
+      | CreateSchemaRequestDto
+      | CreateCredentialDefinitionRequsetDto
+      | IssueCredentialRequestDto;
+    type: SchemaEvent | CredentialEvent;
+    source: string;
+  }) => {
+    if (ALL_EVENTS.includes(payload.type)) {
+      throw new ConnectionUnsupportedTypeError();
+    }
+
+    const event = new CloudEventDto<typeof payload.data>();
+    event.subject = payload.type;
+    event.source = payload.source;
+    event.type = payload.type;
+    event.data = payload.data;
+
+    return event;
+  };
+}
diff --git a/apps/attestation-manager/src/main.ts b/apps/attestation-manager/src/main.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b9c9619988ba69898f38e48f5d5b77b109bcf043
--- /dev/null
+++ b/apps/attestation-manager/src/main.ts
@@ -0,0 +1,37 @@
+/**
+ * This is not a production server yet!
+ * This is only a minimal backend to get started.
+ */
+
+import { Logger } from "@nestjs/common";
+import { NestFactory } from "@nestjs/core";
+
+import { AppModule } from "./app/app.module";
+
+import { MicroserviceOptions, Transport } from "@nestjs/microservices";
+import { ConfigService } from "@nestjs/config";
+import { IAttestationManagerConfig } from "@ocm-engine/config";
+async function bootstrap() {
+  const app = await NestFactory.create(AppModule);
+
+  const configService = app.get(ConfigService);
+  const am = configService.get<IAttestationManagerConfig>("am")!;
+
+  app.enableShutdownHooks();
+
+  const microservice = app.connectMicroservice<MicroserviceOptions>({
+    transport: Transport.TCP,
+    options: {
+      host: am.host,
+      port: am.port,
+    },
+  });
+
+  await app.startAllMicroservices();
+
+  app.enableShutdownHooks();
+
+  Logger.log("Application is running");
+}
+
+bootstrap();
diff --git a/apps/attestation-manager/tsconfig.app.json b/apps/attestation-manager/tsconfig.app.json
new file mode 100644
index 0000000000000000000000000000000000000000..954f3ad1c11170724606b4b020297567c518a86b
--- /dev/null
+++ b/apps/attestation-manager/tsconfig.app.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../dist/out-tsc",
+    "module": "commonjs",
+    "types": ["node"],
+    "emitDecoratorMetadata": true,
+    "target": "es2015"
+  },
+  "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
+  "include": ["src/**/*.ts"]
+}
diff --git a/apps/attestation-manager/tsconfig.json b/apps/attestation-manager/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..c1e2dd4e8be6f4fe3dca35d044fd912ff41b1c18
--- /dev/null
+++ b/apps/attestation-manager/tsconfig.json
@@ -0,0 +1,16 @@
+{
+  "extends": "../../tsconfig.base.json",
+  "files": [],
+  "include": [],
+  "references": [
+    {
+      "path": "./tsconfig.app.json"
+    },
+    {
+      "path": "./tsconfig.spec.json"
+    }
+  ],
+  "compilerOptions": {
+    "esModuleInterop": true
+  }
+}
diff --git a/apps/attestation-manager/tsconfig.spec.json b/apps/attestation-manager/tsconfig.spec.json
new file mode 100644
index 0000000000000000000000000000000000000000..9b2a121d114b68dcdb5b834ebca032814b499a74
--- /dev/null
+++ b/apps/attestation-manager/tsconfig.spec.json
@@ -0,0 +1,14 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../dist/out-tsc",
+    "module": "commonjs",
+    "types": ["jest", "node"]
+  },
+  "include": [
+    "jest.config.ts",
+    "src/**/*.test.ts",
+    "src/**/*.spec.ts",
+    "src/**/*.d.ts"
+  ]
+}
diff --git a/apps/attestation-manager/webpack.config.js b/apps/attestation-manager/webpack.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..0ab513e830c33d6687ae9e14f62f69df7c0df36b
--- /dev/null
+++ b/apps/attestation-manager/webpack.config.js
@@ -0,0 +1,8 @@
+const { composePlugins, withNx } = require("@nx/webpack");
+
+// Nx plugins for webpack.
+module.exports = composePlugins(withNx(), (config) => {
+  // Update the webpack config as needed here.
+  // e.g. `config.plugins.push(new MyPlugin())`
+  return config;
+});
diff --git a/apps/connection-manager/src/main.ts b/apps/connection-manager/src/main.ts
index 58d5133a4b4cc97a9208e1df050f3a4a01d85798..eb1af5cf3cff5730e41d42e222ec6a219d48f72b 100644
--- a/apps/connection-manager/src/main.ts
+++ b/apps/connection-manager/src/main.ts
@@ -9,21 +9,20 @@ import { NestFactory } from "@nestjs/core";
 import { AppModule } from "./app/app.module";
 import { MicroserviceOptions, Transport } from "@nestjs/microservices";
 import { ConfigService } from "@nestjs/config";
-import { IConnectionManager, IGateway } from "@ocm-engine/config";
-import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
+import { IConnectionManagerConfig } from "@ocm-engine/config";
 async function bootstrap() {
   const app = await NestFactory.create(AppModule);
 
   const configService = app.get(ConfigService);
-  const gatewayConfig = configService.get<IConnectionManager>("cm")!;
+  const cmConfig = configService.get<IConnectionManagerConfig>("cm")!;
 
   app.enableShutdownHooks();
 
   const microservice = app.connectMicroservice<MicroserviceOptions>({
     transport: Transport.TCP,
     options: {
-      host: gatewayConfig.host,
-      port: gatewayConfig.port,
+      host: cmConfig.host,
+      port: cmConfig.port,
     },
   });
 
diff --git a/apps/gateway/src/app/app.module.ts b/apps/gateway/src/app/app.module.ts
index 5c54c0585730b619541655f16e5067d00dbb906e..cc91a8cec459825dd035e10bb6d2821339aa9e47 100644
--- a/apps/gateway/src/app/app.module.ts
+++ b/apps/gateway/src/app/app.module.ts
@@ -4,33 +4,41 @@ import { EventsGateway } from "./events.gateway";
 import { ConfigModule } from "@nestjs/config";
 import { AppController } from "./app.controller";
 import {
+  amConfig,
+  amSchema,
   cmConfig,
   cmSchema,
   gatewayConfig,
   gatewaySchema,
 } from "@ocm-engine/config";
-import { ConnectionManagerClient } from "@ocm-engine/clients";
+import {
+  AttestationManagerClient,
+  ConnectionManagerClient,
+} from "@ocm-engine/clients";
 import Joi from "joi";
-import { ConnectionController } from "./connection.controller";
+import { ConnectionController } from "./managers/connection.controller";
 import { APP_PIPE } from "@nestjs/core";
+import { AttestationController } from "./managers/attestation.controller";
 
 const validationSchema = Joi.object({
   gateway: gatewaySchema,
   cm: cmSchema,
+  am: amSchema,
 });
 
 @Module({
   imports: [
     ConfigModule.forRoot({
       isGlobal: true,
-      load: [gatewayConfig, cmConfig],
+      load: [gatewayConfig, cmConfig, amConfig],
       validationSchema,
     }),
   ],
-  controllers: [AppController, ConnectionController],
+  controllers: [AppController, ConnectionController, AttestationController],
   providers: [
     EventsGateway,
     ConnectionManagerClient,
+    AttestationManagerClient,
     {
       provide: APP_PIPE,
       useValue: new ValidationPipe({
diff --git a/apps/gateway/src/app/managers/attestation.controller.ts b/apps/gateway/src/app/managers/attestation.controller.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f4f4d47b36a47d1db5ec9fface825d82157020c0
--- /dev/null
+++ b/apps/gateway/src/app/managers/attestation.controller.ts
@@ -0,0 +1,316 @@
+import {
+  BadRequestException,
+  Body,
+  Controller,
+  Get,
+  Param,
+  Post,
+  UseFilters,
+} from "@nestjs/common";
+import { AllExceptionsHandler } from "../exception.handler";
+import { AttestationManagerClient } from "@ocm-engine/clients";
+import {
+  AcceptCredentialOfferRequestDto,
+  CONNECTION_ACCEPT,
+  CreateCredentialDefinitionRequsetDto,
+  CreateSchemaRequestDto,
+  CRED_DEF_CREATE,
+  CRED_ISSUE,
+  CRED_LIST,
+  CRED_OFFER_ACCEPT,
+  CRED_OFFER_LIST,
+  GatewayAcceptedResponseDto,
+  GetSchemaRequestDto,
+  IssueCredentialRequestDto,
+  SCHEMA_CREATE,
+  SCHEMA_GET,
+  SCHEMA_LIST,
+} from "@ocm-engine/dtos";
+import {
+  ApiBadRequestResponse,
+  ApiInternalServerErrorResponse,
+  ApiOperation,
+  ApiResponse,
+} from "@nestjs/swagger";
+
+@UseFilters(AllExceptionsHandler)
+@Controller("v1")
+export class AttestationController {
+  constructor(private readonly amClient: AttestationManagerClient) {}
+
+  @Post("/schemas")
+  @ApiResponse({
+    status: 201,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    description:
+      "Error in sending data to connection manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    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"],
+  })
+  async createSchema(@Body() schemaDto: CreateSchemaRequestDto) {
+    return this.amClient.sendPayload<CreateSchemaRequestDto>({
+      pattern: "schemas",
+      payload: {
+        source: "/schema",
+        data: schemaDto,
+        type: SCHEMA_CREATE,
+      },
+    });
+  }
+
+  @Post("/schemas-by-id")
+  @ApiResponse({
+    status: 201,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    description:
+      "Error in sending data to connection manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    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"],
+  })
+  async getSchemaById(@Body() schemaRequestDto: GetSchemaRequestDto) {
+    return this.amClient.sendPayload<GetSchemaRequestDto>({
+      pattern: "schemas",
+      payload: {
+        source: "/schemas-by-id",
+        data: schemaRequestDto,
+        type: SCHEMA_GET,
+      },
+    });
+  }
+
+  @Get("/schemas")
+  @ApiResponse({
+    status: 200,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    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.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    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"],
+  })
+  async listSchema() {
+    return this.amClient.sendPayload<null>({
+      pattern: "schemas",
+      payload: {
+        source: "/schema",
+        data: null,
+        type: SCHEMA_LIST,
+      },
+    });
+  }
+
+  @Post("credential/definition")
+  @ApiResponse({
+    status: 201,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    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.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    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"],
+  })
+  createCredentialDefinition(
+    @Body() credentialDefinitionDto: CreateCredentialDefinitionRequsetDto,
+  ) {
+    return this.amClient.sendPayload({
+      pattern: "credentials",
+      payload: {
+        source: "/credential/definition",
+        data: credentialDefinitionDto,
+        type: CRED_DEF_CREATE,
+      },
+    });
+  }
+
+  @Post("credential/issue")
+  @ApiResponse({
+    status: 201,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    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.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    summary: "Issue credential definition",
+    description:
+      "Method issue credential definition. The id of the response will be matched when you receive event from the websocket",
+    tags: ["Credentials"],
+  })
+  issueCredential(@Body() issueCredentialDto: IssueCredentialRequestDto) {
+    return this.amClient.sendPayload({
+      pattern: "credentials",
+      payload: {
+        source: "credential/issue",
+        data: issueCredentialDto,
+        type: CRED_ISSUE,
+      },
+    });
+  }
+
+  @Get("/credentials")
+  @ApiResponse({
+    status: 200,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    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.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    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"],
+  })
+  credentials() {
+    return this.amClient.sendPayload({
+      pattern: "credentials",
+      payload: {
+        source: "credentials",
+        data: null,
+        type: CRED_LIST,
+      },
+    });
+  }
+
+  @Get("/credential/offers")
+  @ApiResponse({
+    status: 200,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    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.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    summary: "List all credential offers",
+    description:
+      "Method list offers that are sent, but not accepted. The id of the response will be matched when you receive event from the websocket",
+    tags: ["Credentials"],
+  })
+  getCredentialOffers() {
+    return this.amClient.sendPayload({
+      pattern: "credentials",
+      payload: {
+        source: "credentials/offers",
+        data: null,
+        type: CRED_OFFER_LIST,
+      },
+    });
+  }
+
+  @Post("/credential/offers/:credential_record_id/accept")
+  @ApiResponse({
+    status: 200,
+    description:
+      "Request is accepted for execution, the response id will match the event id received from the web socket",
+    type: GatewayAcceptedResponseDto,
+  })
+  @ApiBadRequestResponse({
+    status: 400,
+    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.",
+    type: BadRequestException,
+  })
+  @ApiInternalServerErrorResponse({
+    status: 500,
+    description: "Unknown error",
+  })
+  @ApiOperation({
+    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"],
+  })
+  acceptCredential(@Param("credential_record_id") credentialRecordId: string) {
+    const data = new AcceptCredentialOfferRequestDto();
+    data.credentialRecordId = credentialRecordId;
+    return this.amClient.sendPayload({
+      pattern: "credentials",
+      payload: {
+        source: "credential/:id/accept",
+        data,
+        type: CRED_OFFER_ACCEPT,
+      },
+    });
+  }
+}
diff --git a/apps/gateway/src/app/connection.controller.ts b/apps/gateway/src/app/managers/connection.controller.ts
similarity index 98%
rename from apps/gateway/src/app/connection.controller.ts
rename to apps/gateway/src/app/managers/connection.controller.ts
index 47c866f5abfa38362d6a326da8867a751753ca01..52c86c6940baa9896c050e026b81306b68733349 100644
--- a/apps/gateway/src/app/connection.controller.ts
+++ b/apps/gateway/src/app/managers/connection.controller.ts
@@ -17,7 +17,7 @@ import {
   GatewayAcceptedResponseDto,
   GetConnectionRequestDto,
 } from "@ocm-engine/dtos";
-import { AllExceptionsHandler } from "./exception.handler";
+import { AllExceptionsHandler } from "../exception.handler";
 import {
   ApiBadRequestResponse,
   ApiBody,
diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml
index 145594f59efdbdbf91121906e54552db86dd54d6..2a0c5fb5ac8a488ffac5bb6ce7a9b9a4777c8def 100644
--- a/compose/docker-compose.yml
+++ b/compose/docker-compose.yml
@@ -44,6 +44,20 @@ services:
       broker:
         condition: service_started
 
+  am-issuer:
+    container_name: am-issuer
+    build:
+      context: "../"
+      dockerfile: "./apps/attestation-manager/deployment/Dockerfile"
+    env_file:
+      - ./env/issuer.env
+    ports:
+      - "8883"
+    depends_on:
+      broker:
+        condition: service_started
+
+
   pg_db:
     image: 'postgres:latest'
     ports:
diff --git a/compose/env/issuer.env b/compose/env/issuer.env
index 813e39d527cdfcb9f1edeb617670fd4ac6d9fbff..aa7308f2eb4a20dcd44f71819f828b9083907c69 100644
--- a/compose/env/issuer.env
+++ b/compose/env/issuer.env
@@ -26,3 +26,6 @@ GATEWAY_HOST=gateway-issuer
 
 CONNECTION_SERVICE_TCP_PORT=8882
 CONNECTION_SERVICE_HOST=cm-issuer
+
+CONNECTION_SERVICE_TCP_PORT=8883
+CONNECTION_SERVICE_HOST=am-issuer
diff --git a/gateway-swagger.json b/gateway-swagger.json
index 0b4ba37b7148b7f7927696fe6212187ebe1d2827..7abc420082b25e60f8ce051ad2a4245f400c9f58 100644
--- a/gateway-swagger.json
+++ b/gateway-swagger.json
@@ -1 +1 @@
-{"openapi":"3.0.0","paths":{"/api/v1/invitation":{"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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/api/v1/invitation/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":"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}}},"info":{"title":"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"]},"BadRequestException":{"type":"object","properties":{}},"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"]}}}}
\ No newline at end of file
+{"openapi":"3.0.0","paths":{"/api/v1/invitation":{"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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/api/v1/invitation/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":"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/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":"Error in sending data to connection 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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}},"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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/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":"Error in sending data to connection 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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/api/v1/credential/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":"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/api/v1/credential/issue":{"post":{"operationId":"AttestationController_issueCredential","summary":"Issue credential definition","description":"Method issue 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/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":"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/api/v1/credential/offers":{"get":{"operationId":"AttestationController_getCredentialOffers","summary":"List all credential offers","description":"Method list offers that are sent, but not accepted. 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"}}}},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}},"/api/v1/credential/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"],"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":""},"400":{"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":{"$ref":"#/components/schemas/BadRequestException"}}}},"500":{"description":"Unknown error"}}}}},"info":{"title":"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"]},"BadRequestException":{"type":"object","properties":{}},"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"},"credentialDefinitionId":{"type":"string"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueCredentialAttributes"}}},"required":["connectionId","credentialDefinitionId","attributes"]}}}}
\ No newline at end of file
diff --git a/libs/asker/src/asker-nats/agent.consumer.service.ts b/libs/asker/src/asker-nats/agent.consumer.service.ts
index 751211a02ab6f56f815c3cb5e29cc61db094f3c5..1a333e3a5d238661a53c3087b36b7213cf98be2f 100644
--- a/libs/asker/src/asker-nats/agent.consumer.service.ts
+++ b/libs/asker/src/asker-nats/agent.consumer.service.ts
@@ -10,12 +10,25 @@ import { ConfigService } from "@nestjs/config";
 import { IConfAgent } from "@ocm-engine/config";
 import { GatewayClient } from "@ocm-engine/clients";
 import {
+  AcceptCredentialOfferRequestDto,
   CONNECTION_ACCEPT,
   CONNECTION_CREATE,
   CONNECTION_GET,
   CONNECTION_LIST,
+  CreateCredentialDefinitionRequsetDto,
   CreateInvitationResponseDto,
+  CreateSchemaRequestDto,
+  CRED_DEF_CREATE,
+  CRED_ISSUE,
+  CRED_LIST,
+  CRED_OFFER_ACCEPT,
+  CRED_OFFER_LIST,
   GetConnectionRequestDto,
+  GetSchemaRequestDto,
+  IssueCredentialRequestDto,
+  SCHEMA_CREATE,
+  SCHEMA_GET,
+  SCHEMA_LIST,
 } from "@ocm-engine/dtos";
 
 @Injectable()
@@ -41,15 +54,15 @@ export class AgentConsumerService implements OnModuleInit, OnModuleDestroy {
     await this.consumerService.subscribe(async (event) => {
       this.logger.debug(JSON.stringify(event, null, 2));
       let data;
+      let dto;
 
       switch (event.type) {
         case CONNECTION_CREATE:
           data = await this.agentService.createInvitation();
           break;
         case CONNECTION_ACCEPT:
-          // eslint-disable-next-line no-case-declarations
-          const c = event.data as CreateInvitationResponseDto;
-          data = await this.agentService.acceptInvitation(c.invitationUrl);
+          dto = event.data as CreateInvitationResponseDto;
+          data = await this.agentService.acceptInvitation(dto.invitationUrl);
           break;
 
         case CONNECTION_LIST:
@@ -57,9 +70,47 @@ export class AgentConsumerService implements OnModuleInit, OnModuleDestroy {
           break;
 
         case CONNECTION_GET:
-          // eslint-disable-next-line no-case-declarations
-          const g = event.data as GetConnectionRequestDto;
-          data = await this.agentService.getConnectionById(g.connectionId);
+          dto = event.data as GetConnectionRequestDto;
+          data = await this.agentService.getConnectionById(dto.connectionId);
+          break;
+
+        case SCHEMA_CREATE:
+          dto = event.data as CreateSchemaRequestDto;
+          data = await this.agentService.createSchema(dto);
+          break;
+        case SCHEMA_LIST:
+          data = await this.agentService.fetchSchemas();
+          break;
+
+        case SCHEMA_GET:
+          dto = event.data as GetSchemaRequestDto;
+          data = await this.agentService.getSchemaById(dto.schemaId);
+          break;
+        case CRED_DEF_CREATE:
+          data = await this.agentService.createCredentialDefinition(
+            event.data as CreateCredentialDefinitionRequsetDto,
+          );
+          break;
+
+        case CRED_ISSUE:
+          data = await this.agentService.issueCredential(
+            event.data as IssueCredentialRequestDto,
+          );
+          break;
+
+        case CRED_LIST:
+          data = await this.agentService.credentials();
+          break;
+
+        case CRED_OFFER_LIST:
+          data = await this.agentService.credentialByStatedOfferReceived();
+          break;
+
+        case CRED_OFFER_ACCEPT:
+          dto = event.data as AcceptCredentialOfferRequestDto;
+          data = await this.agentService.acceptCredential(
+            dto.credentialRecordId,
+          );
       }
 
       event.data = data;
diff --git a/libs/asker/src/asker/agent.service.ts b/libs/asker/src/asker/agent.service.ts
index 88013bdbc91c76abbeec755f5bee2c867e204890..d311a3eaeda17537995f89fa7a4c1e85470d1f52 100644
--- a/libs/asker/src/asker/agent.service.ts
+++ b/libs/asker/src/asker/agent.service.ts
@@ -63,6 +63,14 @@ export class AgentService {
     return this.asker.agent.connections.findById(id);
   };
 
+  fetchSchemas = () => {
+    return this.asker.agent.modules.anoncreds.getCreatedSchemas({});
+  };
+
+  getSchemaById = (schemaId: string) => {
+    return this.asker.agent.modules.anoncreds.getSchema(schemaId);
+  };
+
   createSchema = async (schema: CreateSchemaRequestDto) => {
     const dids = await this.asker.agent.dids.getCreatedDids({ method: "indy" });
 
@@ -82,6 +90,7 @@ export class AgentService {
     }
 
     const response = new CreateSchemaResponseDto();
+
     response.name = schemaResult.schemaState.schema.name;
     response.schemaId = schemaResult.schemaState.schemaId;
     response.issuerId = schemaResult.schemaState.schema.issuerId;
diff --git a/libs/clients/src/index.ts b/libs/clients/src/index.ts
index 8191daf640fdfb1a5726344f7023277e2696f268..76a58bf05b250a6fda72297b742165eddd0e54a9 100644
--- a/libs/clients/src/index.ts
+++ b/libs/clients/src/index.ts
@@ -1,2 +1,3 @@
 export * from "./lib/gateway.client";
 export * from "./lib/connection.manager.client";
+export * from "./lib/attestation.manager.client";
diff --git a/libs/clients/src/lib/attestation.manager.client.ts b/libs/clients/src/lib/attestation.manager.client.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4b66e730d589a90217df024762b7302ae285988b
--- /dev/null
+++ b/libs/clients/src/lib/attestation.manager.client.ts
@@ -0,0 +1,66 @@
+import {
+  BadRequestException,
+  Injectable,
+  InternalServerErrorException,
+  Logger,
+} from "@nestjs/common";
+import {
+  ClientProxy,
+  ClientProxyFactory,
+  Transport,
+} from "@nestjs/microservices";
+import { ConfigService } from "@nestjs/config";
+import {
+  IAttestationManagerConfig,
+  IConnectionManagerConfig,
+} from "@ocm-engine/config";
+import { lastValueFrom } from "rxjs";
+
+@Injectable()
+export class AttestationManagerClient {
+  private client: ClientProxy;
+  private cmConfig: IAttestationManagerConfig;
+  private readonly logger: Logger = new Logger(AttestationManagerClient.name);
+
+  constructor(configService: ConfigService) {
+    this.cmConfig = configService.get<IConnectionManagerConfig>("am")!;
+
+    this.client = ClientProxyFactory.create({
+      transport: Transport.TCP,
+      options: {
+        host: this.cmConfig.host,
+        port: this.cmConfig.port,
+      },
+    });
+  }
+
+  async sendPayload<T>({
+    pattern,
+    payload,
+  }: {
+    pattern: string;
+    payload: {
+      data: T;
+      type: string;
+      source: string;
+    };
+  }): Promise<{
+    id: string;
+  }> {
+    this.logger.debug(
+      `sending payload to attestation manager ${JSON.stringify(
+        payload,
+        null,
+        2,
+      )}`,
+    );
+
+    return lastValueFrom(this.client.send(pattern, payload)).catch((e) => {
+      if (e.message === "Internal server error") {
+        throw new InternalServerErrorException();
+      }
+
+      throw new BadRequestException(e.message);
+    });
+  }
+}
diff --git a/libs/clients/src/lib/connection.manager.client.ts b/libs/clients/src/lib/connection.manager.client.ts
index 04183ed7e8764a701b7f36546b8bf60acdd7d52a..3554fb1e95286ef0ab00a8f576af095d05d331c3 100644
--- a/libs/clients/src/lib/connection.manager.client.ts
+++ b/libs/clients/src/lib/connection.manager.client.ts
@@ -10,17 +10,17 @@ import {
   Transport,
 } from "@nestjs/microservices";
 import { ConfigService } from "@nestjs/config";
-import { IConnectionManager } from "@ocm-engine/config";
+import { IConnectionManagerConfig } from "@ocm-engine/config";
 import { lastValueFrom } from "rxjs";
 
 @Injectable()
 export class ConnectionManagerClient {
   private client: ClientProxy;
-  private cmConfig: IConnectionManager;
+  private cmConfig: IConnectionManagerConfig;
   private readonly logger: Logger = new Logger(ConnectionManagerClient.name);
 
   constructor(configService: ConfigService) {
-    this.cmConfig = configService.get<IConnectionManager>("cm")!;
+    this.cmConfig = configService.get<IConnectionManagerConfig>("cm")!;
 
     this.client = ClientProxyFactory.create({
       transport: Transport.TCP,
diff --git a/libs/config/src/config/attestation.manager.ts b/libs/config/src/config/attestation.manager.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d7e28623b3d5a8b6d64d577c2885b80e22cd5d97
--- /dev/null
+++ b/libs/config/src/config/attestation.manager.ts
@@ -0,0 +1,11 @@
+import { registerAs } from "@nestjs/config";
+import * as process from "process";
+import { IAttestationManagerConfig } from "../interfaces/attestation.manager.config.interface";
+
+export const amConfig = registerAs(
+  "am",
+  (): IAttestationManagerConfig => ({
+    host: process.env["ATTESTATION_SERVICE_HOST"]!,
+    port: parseInt(process.env["ATTESTATION_SERVICE_TCP_PORT"]!),
+  }),
+);
diff --git a/libs/config/src/config/connection.manager.config.ts b/libs/config/src/config/connection.manager.config.ts
index ea3c981b395d7098571f89f2952d2b0a104c2d3a..1ae947bd47c90b8473a3fa1186a268acc01a2152 100644
--- a/libs/config/src/config/connection.manager.config.ts
+++ b/libs/config/src/config/connection.manager.config.ts
@@ -1,10 +1,10 @@
 import { registerAs } from "@nestjs/config";
 import * as process from "process";
-import { IConnectionManager } from "../interfaces/connection.manager.interface";
+import { IConnectionManagerConfig } from "../interfaces/connection.manager.config.interface";
 
 export const cmConfig = registerAs(
   "cm",
-  (): IConnectionManager => ({
+  (): IConnectionManagerConfig => ({
     host: process.env["CONNECTION_SERVICE_HOST"]!,
     port: parseInt(process.env["CONNECTION_SERVICE_TCP_PORT"]!),
   }),
diff --git a/libs/config/src/index.ts b/libs/config/src/index.ts
index 7bd3b78d59f22078020dd10873f83bd434a3e91e..6ecbe3f4fe991891573fd5590d29998ecfef8bbe 100644
--- a/libs/config/src/index.ts
+++ b/libs/config/src/index.ts
@@ -3,15 +3,18 @@ export * from "./config/agent.config";
 export * from "./config/ledgers.config";
 export * from "./config/gateway.config";
 export * from "./config/connection.manager.config";
+export * from "./config/attestation.manager";
 
 export * from "./interfaces/nats.config.interface";
 export * from "./interfaces/agent.config.interface";
 export * from "./interfaces/ledgers.config.interface";
 export * from "./interfaces/gateway.config.interface";
-export * from "./interfaces/connection.manager.interface";
+export * from "./interfaces/connection.manager.config.interface";
+export * from "./interfaces/attestation.manager.config.interface";
 
 export * from "./schemas/nats.schema";
 export * from "./schemas/agent.schema";
 export * from "./schemas/ledgers.schema";
 export * from "./schemas/gateway.schema";
 export * from "./schemas/connection.manager.schema";
+export * from "./schemas/attestation.manager.schema";
diff --git a/libs/config/src/interfaces/attestation.manager.config.interface.ts b/libs/config/src/interfaces/attestation.manager.config.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1ad4a74b3b9dde7ed40c86f855f329a9b74572d6
--- /dev/null
+++ b/libs/config/src/interfaces/attestation.manager.config.interface.ts
@@ -0,0 +1,4 @@
+export interface IAttestationManagerConfig {
+  host: string;
+  port: number;
+}
diff --git a/libs/config/src/interfaces/connection.manager.config.interface.ts b/libs/config/src/interfaces/connection.manager.config.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..51b1dfa8e2253f58843ece847ba74345215eadad
--- /dev/null
+++ b/libs/config/src/interfaces/connection.manager.config.interface.ts
@@ -0,0 +1,4 @@
+export interface IConnectionManagerConfig {
+  host: string;
+  port: number;
+}
diff --git a/libs/config/src/interfaces/connection.manager.interface.ts b/libs/config/src/interfaces/connection.manager.interface.ts
deleted file mode 100644
index 80092b731d2d06aa5699f11f8c5a5d620e53052f..0000000000000000000000000000000000000000
--- a/libs/config/src/interfaces/connection.manager.interface.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export interface IConnectionManager {
-  host: string;
-  port: number;
-}
diff --git a/libs/config/src/schemas/attestation.manager.schema.ts b/libs/config/src/schemas/attestation.manager.schema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..da7bbf862353178dc93362a037dfe0a1c922073c
--- /dev/null
+++ b/libs/config/src/schemas/attestation.manager.schema.ts
@@ -0,0 +1,6 @@
+import Joi from "joi";
+
+export const amSchema = Joi.object({
+  ATTESTATION_SERVICE_TCP_PORT: Joi.string().required(),
+  ATTESTATION_SERVICE_HOST: Joi.string().required(),
+});
diff --git a/libs/dtos/src/dtos/requests/accept.credential.offer.request.dto.ts b/libs/dtos/src/dtos/requests/accept.credential.offer.request.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..baaa860e4e40458f64af76f576939d8e72eb8779
--- /dev/null
+++ b/libs/dtos/src/dtos/requests/accept.credential.offer.request.dto.ts
@@ -0,0 +1,8 @@
+import { IsNotEmpty, IsString } from "class-validator";
+
+export class AcceptCredentialOfferRequestDto {
+  //@example cf8395a5-9a53-4e06-8a5d-04e0fc00ca04
+  @IsNotEmpty()
+  @IsString()
+  credentialRecordId: string;
+}
diff --git a/libs/dtos/src/dtos/requests/create.schema.request.dto.ts b/libs/dtos/src/dtos/requests/create.schema.request.dto.ts
index ef98564fec6fe6d07ea82424fdf970acfb7e0830..01d49ccdefddf83767d45a7e2de040ca7cd7d3e4 100644
--- a/libs/dtos/src/dtos/requests/create.schema.request.dto.ts
+++ b/libs/dtos/src/dtos/requests/create.schema.request.dto.ts
@@ -1,13 +1,16 @@
 import { IsNotEmpty, IsString, Matches } from "class-validator";
 
 export class CreateSchemaRequestDto {
+  //@example "my test schema"
   @IsNotEmpty()
   @IsString()
   name: string;
 
+  //@example ['first_name, last_name']
   @IsNotEmpty()
   attributes: string[];
 
+  //@example 1.0.2
   @IsNotEmpty()
   @Matches(/^(\d+\.)?(\d+\.)?(\*|\d+)$/)
   version: string;
diff --git a/libs/dtos/src/dtos/requests/get.schema.request.dto.ts b/libs/dtos/src/dtos/requests/get.schema.request.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..acdf35ca546ede92f0f5aa27097b892a9ba14bfc
--- /dev/null
+++ b/libs/dtos/src/dtos/requests/get.schema.request.dto.ts
@@ -0,0 +1,8 @@
+import { IsNotEmpty, IsString } from "class-validator";
+
+export class GetSchemaRequestDto {
+  //@example "did:indy:LEDNGER:SXM76gQwRnjkgoz2oBnGjd/anoncreds/v0/SCHEMA/test schema/1.0.2"
+  @IsNotEmpty()
+  @IsString()
+  schemaId: string;
+}
diff --git a/libs/dtos/src/events/types.ts b/libs/dtos/src/events/types.ts
index 748a1aad40589f956aa91ad1c599849db62f5190..128a81f8437f29e263fb89fed01201f4319401e7 100644
--- a/libs/dtos/src/events/types.ts
+++ b/libs/dtos/src/events/types.ts
@@ -15,3 +15,37 @@ export const CONNECTION_EVENTS: ConnectionEvent[] = [
   CONNECTION_LIST,
   CONNECTION_GET,
 ];
+
+export type SchemaEvent = "schemas.create" | "schemas.get" | "schemas.list";
+export const SCHEMA_CREATE: SchemaEvent = "schemas.create";
+export const SCHEMA_GET: SchemaEvent = "schemas.get";
+export const SCHEMA_LIST: SchemaEvent = "schemas.list";
+
+export const SCHEMA_EVENTS: SchemaEvent[] = [
+  SCHEMA_CREATE,
+  SCHEMA_LIST,
+  SCHEMA_GET,
+];
+
+export type CredentialEvent =
+  | "credential.definition.create"
+  | "credential.issue"
+  | "credential.list"
+  | "credential.offer.list"
+  | "credential.offer.accept";
+
+export const CRED_DEF_CREATE = "credential.definition.create";
+export const CRED_ISSUE = "credential.issue";
+export const CRED_LIST = "credential.list";
+export const CRED_OFFER_LIST = "credential.offer.list";
+export const CRED_OFFER_ACCEPT = "credential.offer.accept";
+
+export const CRED_EVENTS: CredentialEvent[] = [
+  CRED_DEF_CREATE,
+  CRED_ISSUE,
+  CRED_LIST,
+  CRED_OFFER_LIST,
+  CRED_OFFER_ACCEPT,
+];
+
+export const ALL_EVENTS = [...SCHEMA_EVENTS, ...CRED_EVENTS];
diff --git a/libs/dtos/src/index.ts b/libs/dtos/src/index.ts
index 8ed6a97500170a5be088ed6c304ead573c514e8d..cf82a2c82268d0c6c5fddb9d53da6e2654418885 100644
--- a/libs/dtos/src/index.ts
+++ b/libs/dtos/src/index.ts
@@ -4,6 +4,8 @@ export * from "./dtos/requests/create.credential.definition.requset.dto";
 export * from "./dtos/requests/issue.credential.request.dto";
 export * from "./dtos/requests/issue.proof.request.dto";
 export * from "./dtos/requests/get.connection.request.dto";
+export * from "./dtos/requests/get.schema.request.dto";
+export * from "./dtos/requests/accept.credential.offer.request.dto";
 
 export * from "./dtos/responses/create.invitation.response.dto";
 export * from "./dtos/responses/accept.invitation.response.dto";